OSDN Git Service

* config/mips/mips-protos.h (mips_idiv_insns): Declare.
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Feb 2004 19:59:24 +0000 (19:59 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Feb 2004 19:59:24 +0000 (19:59 +0000)
* config/mips/mips.h (MASK_FIX_SB1): Bump.
(MASK_FIX_R4000, TARGET_FIX_R4000): New macros.
(TARGET_SWITCHES): Add -mfix-r4000 and -mno-fix-r4000.
* config/mips/mips.c (mips_idiv_insns): New function.
(override_options): Make -march=r4000 imply -mfix-r4000 by default.
(mips_output_division): Add a workaround for the R4000 divide/shift
errata.
* config/mips/mips.md (length): Use mips_idiv_insns() to calculate
the length of an "idiv" instruction.
* doc/invoke.texi: Document the new switches.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@78621 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/mips/mips-protos.h
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/doc/invoke.texi

index 21e6db0..417c012 100644 (file)
@@ -1,3 +1,17 @@
+2004-02-28  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+
+       * config/mips/mips-protos.h (mips_idiv_insns): Declare.
+       * config/mips/mips.h (MASK_FIX_SB1): Bump.
+       (MASK_FIX_R4000, TARGET_FIX_R4000): New macros.
+       (TARGET_SWITCHES): Add -mfix-r4000 and -mno-fix-r4000.
+       * config/mips/mips.c (mips_idiv_insns): New function.
+       (override_options): Make -march=r4000 imply -mfix-r4000 by default.
+       (mips_output_division): Add a workaround for the R4000 divide/shift
+       errata.
+       * config/mips/mips.md (length): Use mips_idiv_insns() to calculate
+       the length of an "idiv" instruction.
+       * doc/invoke.texi: Document the new switches.
+
 2004-02-28  Kazu Hirata  <kazu@cs.umass.edu>
 
        * doc/tm.texi (IS_COSTLY_DEPENDENCE): Change to
index 222c93d..b5128ba 100644 (file)
@@ -30,6 +30,7 @@ extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, int);
 extern int mips_address_insns (rtx, enum machine_mode);
 extern int mips_const_insns (rtx);
 extern int mips_fetch_insns (rtx);
+extern int mips_idiv_insns (void);
 extern bool mips_legitimate_address_p (enum machine_mode, rtx, int);
 extern bool mips_legitimize_address (rtx *, enum machine_mode);
 extern rtx mips_gotoff_page (rtx);
index 852a8c8..84494c2 100644 (file)
@@ -1350,6 +1350,27 @@ mips_fetch_insns (rtx x)
 }
 
 
+/* Return the number of instructions needed for an integer division.  */
+
+int
+mips_idiv_insns (void)
+{
+  int count;
+
+  count = 1;
+  if (TARGET_CHECK_ZERO_DIV)
+    {
+      if (TARGET_MIPS16)
+       count += 2;
+      else
+       count += 3;
+    }
+  if (TARGET_FIX_R4000)
+    count++;
+  return count;
+}
+
+
 /* Return truth value of whether OP can be used as an operands
    where a register or 16 bit unsigned integer is needed.  */
 
@@ -5111,6 +5132,12 @@ override_options (void)
       mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
       mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
     }
+
+  /* Default to working around R4000 errata only if the processor
+     was selected explicitly.  */
+  if ((target_flags_explicit & MASK_FIX_R4000) == 0
+      && mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
+    target_flags |= MASK_FIX_R4000;
 }
 
 /* Implement CONDITIONAL_REGISTER_USAGE.  */
@@ -9185,21 +9212,37 @@ mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p,
 /* Used to output div or ddiv instruction DIVISION, which has the
    operands given by OPERANDS.  If we need a divide-by-zero check,
    output the instruction and return an asm string that traps if
-   operand 2 is zero.  Otherwise just return DIVISION itself.  */
+   operand 2 is zero.
+
+   The original R4000 has a cpu bug.  If a double-word or a variable
+   shift executes immediately after starting an integer division, the
+   shift may give an incorrect result.  Avoid this by adding a nop on
+   the R4000.  See quotations of errata #16 and #28 from "MIPS
+   R4000PC/SC Errata, Processor Revision 2.2 and 3.0" in mips.md for
+   details.
+
+   Otherwise just return DIVISION itself.  */
 
 const char *
 mips_output_division (const char *division, rtx *operands)
 {
+  const char *s = division;
+
   if (TARGET_CHECK_ZERO_DIV)
     {
-      output_asm_insn (division, operands);
+      output_asm_insn (s, operands);
 
       if (TARGET_MIPS16)
-       return "bnez\t%2,1f\n\tbreak\t7\n1:";
+       s = "bnez\t%2,1f\n\tbreak\t7\n1:";
       else
-       return "bne\t%2,%.,1f%#\n\tbreak\t7\n1:";
+       s = "bne\t%2,%.,1f%#\n\tbreak\t7\n1:";
+    }
+  if (TARGET_FIX_R4000)
+    {
+      output_asm_insn (s, operands);
+      s = "nop";
     }
-  return division;
+  return s;
 }
 \f
 /* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL
index e404d3d..9c9ab0e 100644 (file)
@@ -169,7 +169,8 @@ extern const struct mips_cpu_info *mips_tune_info;
 #define MASK_UNINIT_CONST_IN_RODATA \
                           0x00800000   /* Store uninitialized
                                           consts in rodata */
-#define MASK_FIX_SB1       0x01000000   /* Work around SB-1 errata.  */
+#define MASK_FIX_R4000    0x01000000   /* Work around R4000 errata.  */
+#define MASK_FIX_SB1       0x02000000   /* Work around SB-1 errata.  */
 
                                        /* Debug switches, not documented */
 #define MASK_DEBUG     0               /* unused */
@@ -248,6 +249,9 @@ extern const struct mips_cpu_info *mips_tune_info;
 
 #define TARGET_FIX_SB1         (target_flags & MASK_FIX_SB1)
 
+                                       /* Work around R4000 errata.  */
+#define TARGET_FIX_R4000       (target_flags & MASK_FIX_R4000)
+
 /* True if we should use NewABI-style relocation operators for
    symbolic addresses.  This is never true for mips16 code,
    which has its own conventions.  */
@@ -588,6 +592,10 @@ extern const struct mips_cpu_info *mips_tune_info;
      N_("Work around errata for early SB-1 revision 2 cores")},                \
   {"no-fix-sb1",         -MASK_FIX_SB1,                                        \
      N_("Don't work around errata for early SB-1 revision 2 cores")},  \
+  {"fix-r4000",                  MASK_FIX_R4000,                               \
+     N_("Work around R4000 errata")},                                  \
+  {"no-fix-r4000",      -MASK_FIX_R4000,                               \
+     N_("Don't work around R4000 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,                   \
index ae6b898..5b6af02 100644 (file)
               (ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
          (const_int 8)
 
-         (and (eq_attr "type" "idiv")
-              (ne (symbol_ref "TARGET_CHECK_ZERO_DIV") (const_int 0)))
-         (cond [(ne (symbol_ref "TARGET_MIPS16") (const_int 0))
-                (const_int 12)]
-               (const_int 16))
+         (eq_attr "type" "idiv")
+         (symbol_ref "mips_idiv_insns () * 4")
          ] (const_int 4)))
 
 ;; Attribute describing the processor.  This attribute must match exactly
index dcf11d7..3544332 100644 (file)
@@ -478,8 +478,9 @@ in the following sections.
 -mcheck-zero-division  -mno-check-zero-division @gol
 -mmemcpy  -mno-memcpy  -mlong-calls  -mno-long-calls @gol
 -mmad  -mno-mad  -mfused-madd  -mno-fused-madd  -nocpp @gol
--mfix-sb1  -mno-fix-sb1  -mflush-func=@var{func} @gol
--mno-flush-func  -mbranch-likely  -mno-branch-likely}
+-mfix-r4000  -mno-fix-r4000  -mfix-sb1  -mno-fix-sb1 @gol
+-mflush-func=@var{func}  -mno-flush-func @gol
+-mbranch-likely  -mno-branch-likely}
 
 @emph{i386 and x86-64 Options}
 @gccoptlist{-mtune=@var{cpu-type}  -march=@var{cpu-type} @gol
@@ -8045,6 +8046,17 @@ circumstances.
 Tell the MIPS assembler to not run its preprocessor over user
 assembler files (with a @samp{.s} suffix) when assembling them.
 
+@item -mfix-r4000
+@itemx -mno-fix-r4000
+@opindex mfix-r4000
+@opindex mno-fix-r4000
+Work around certain R4000 CPU errata:
+@itemize @minus
+@item
+A double-word or a variable shift may give an incorrect result if executed
+immediately after starting an integer division.
+@end itemize
+
 @item -mfix-sb1
 @itemx -mno-fix-sb1
 @opindex mfix-sb1