* config/mips/mips.h (MASK_FIX_SB1): Bump.
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Mar 2004 08:59:31 +0000 (08:59 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 3 Mar 2004 08:59:31 +0000 (08:59 +0000)
(MASK_FIX_R4400, TARGET_FIX_R4400): New macros.
(TARGET_SWITCHES): Add -mfix-r4400 and -mno-fix-r4400.
* config/mips/mips.c (mips_output_division): Fill the branch delay
slot with a nop if TARGET_FIX_R4000.  Extend R4000 workarounds to
TARGET_FIX_R4400.
(mips_output_division): Adjust accordingly.
(override_options): Make -march=r4400 imply -mfix-r4400 by default.
* doc/invoke.texi: Document -mfix-r4400 and new errata workarounds.

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

gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/doc/invoke.texi

index e5e5266..e812431 100644 (file)
@@ -1,3 +1,16 @@
+2004-03-03  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>
+           Richard Sandiford  <rsandifo@redhat.com>
+
+       * config/mips/mips.h (MASK_FIX_SB1): Bump.
+       (MASK_FIX_R4400, TARGET_FIX_R4400): New macros.
+       (TARGET_SWITCHES): Add -mfix-r4400 and -mno-fix-r4400.
+       * config/mips/mips.c (mips_output_division): Fill the branch delay
+       slot with a nop if TARGET_FIX_R4000.  Extend R4000 workarounds to
+       TARGET_FIX_R4400.
+       (mips_output_division): Adjust accordingly.
+       (override_options): Make -march=r4400 imply -mfix-r4400 by default.
+       * doc/invoke.texi: Document -mfix-r4400 and new errata workarounds.
+
 2004-03-03  Paolo Bonzini  <bonzini@gnu.org>
 
        * alias.c (rtx_equal_for_memref_p): Use predicates
index ee69fa3..bfd5970 100644 (file)
@@ -1321,7 +1321,7 @@ mips_idiv_insns (void)
   count = 1;
   if (TARGET_CHECK_ZERO_DIV)
     count += 2;
-  if (TARGET_FIX_R4000)
+  if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
     count++;
   return count;
 }
@@ -5101,6 +5101,12 @@ override_options (void)
   if ((target_flags_explicit & MASK_FIX_R4000) == 0
       && mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
     target_flags |= MASK_FIX_R4000;
+
+  /* Default to working around R4400 errata only if the processor
+     was selected explicitly.  */
+  if ((target_flags_explicit & MASK_FIX_R4400) == 0
+      && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
+    target_flags |= MASK_FIX_R4400;
 }
 
 /* Implement CONDITIONAL_REGISTER_USAGE.  */
@@ -9171,19 +9177,94 @@ mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p,
   return 0;
 }
 \f
-/* 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.
-
-   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.  */
+/* Used to output div or ddiv instruction DIVISION, which has the operands
+   given by OPERANDS.  Add in a divide-by-zero check if needed.
+
+   When working around R4000 and R4400 errata, we need to make sure that
+   the division is not immediately followed by a shift[1][2].  We also
+   need to stop the division from being put into a branch delay slot[3].
+   The easiest way to avoid both problems is to add a nop after the
+   division.  When a divide-by-zero check is neeeded, this nop can be
+   used to fill the branch delay slot.
+
+   [1] If a double-word or a variable shift executes immediately
+       after starting an integer division, the shift may give an
+       incorrect result.  See quotations of errata #16 and #28 from
+       "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
+       in mips.md for details.
+
+   [2] A similar bug to [1] exists for all revisions of the
+       R4000 and the R4400 when run in an MC configuration.
+       From "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0":
+
+       "19. In this following sequence:
+
+                   ddiv                (or ddivu or div or divu)
+                   dsll32              (or dsrl32, dsra32)
+
+           if an MPT stall occurs, while the divide is slipping the cpu
+           pipeline, then the following double shift would end up with an
+           incorrect result.
+
+           Workaround: The compiler needs to avoid generating any
+           sequence with divide followed by extended double shift."
+
+       This erratum is also present in "MIPS R4400MC Errata, Processor
+       Revision 1.0" and "MIPS R4400MC Errata, Processor Revision 2.0
+       & 3.0" as errata #10 and #4, respectively.
+
+   [3] From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
+       (also valid for MIPS R4000MC processors):
+
+       "52. R4000SC: This bug does not apply for the R4000PC.
+
+           There are two flavors of this bug:
+
+           1) If the instruction just after divide takes an RF exception
+              (tlb-refill, tlb-invalid) and gets an instruction cache
+              miss (both primary and secondary) and the line which is
+              currently in secondary cache at this index had the first
+              data word, where the bits 5..2 are set, then R4000 would
+              get a wrong result for the div.
+
+           ##1
+                   nop
+                   div r8, r9
+                   -------------------         # end-of page. -tlb-refill
+                   nop
+           ##2
+                   nop
+                   div r8, r9
+                   -------------------         # end-of page. -tlb-invalid
+                   nop
+
+           2) If the divide is in the taken branch delay slot, where the
+              target takes RF exception and gets an I-cache miss for the
+              exception vector or where I-cache miss occurs for the
+              target address, under the above mentioned scenarios, the
+              div would get wrong results.
+
+           ##1
+                   j   r2              # to next page mapped or unmapped
+                   div r8,r9           # this bug would be there as long
+                                       # as there is an ICache miss and
+                   nop                 # the "data pattern" is present
+
+           ##2
+                   beq r0, r0, NextPage        # to Next page
+                   div r8,r9
+                   nop
+
+           This bug is present for div, divu, ddiv, and ddivu
+           instructions.
+
+           Workaround: For item 1), OS could make sure that the next page
+           after the divide instruction is also mapped.  For item 2), the
+           compiler could make sure that the divide instruction is not in
+           the branch delay slot."
+
+       These processors have PRId values of 0x00004220 and 0x00004300 for
+       the R4000 and 0x00004400, 0x00004500 and 0x00004600 for the R4400.  */
 
 const char *
 mips_output_division (const char *division, rtx *operands)
@@ -9191,6 +9272,11 @@ mips_output_division (const char *division, rtx *operands)
   const char *s;
 
   s = division;
+  if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
+    {
+      output_asm_insn (s, operands);
+      s = "nop";
+    }
   if (TARGET_CHECK_ZERO_DIV)
     {
       if (TARGET_MIPS16)
@@ -9205,11 +9291,6 @@ mips_output_division (const char *division, rtx *operands)
          s = "break\t7%)\n1:";
        }
     }
-  if (TARGET_FIX_R4000)
-    {
-      output_asm_insn (s, operands);
-      s = "nop";
-    }
   return s;
 }
 \f
index 585b6f1..d2612c9 100644 (file)
@@ -170,7 +170,8 @@ extern const struct mips_cpu_info *mips_tune_info;
                           0x00800000   /* Store uninitialized
                                           consts in rodata */
 #define MASK_FIX_R4000    0x01000000   /* Work around R4000 errata.  */
-#define MASK_FIX_SB1       0x02000000   /* Work around SB-1 errata.  */
+#define MASK_FIX_R4400    0x02000000   /* Work around R4400 errata.  */
+#define MASK_FIX_SB1      0x04000000   /* Work around SB-1 errata.  */
 
                                        /* Debug switches, not documented */
 #define MASK_DEBUG     0               /* unused */
@@ -252,6 +253,9 @@ extern const struct mips_cpu_info *mips_tune_info;
                                        /* Work around R4000 errata.  */
 #define TARGET_FIX_R4000       (target_flags & MASK_FIX_R4000)
 
+                                       /* Work around R4400 errata.  */
+#define TARGET_FIX_R4400               (target_flags & MASK_FIX_R4400)
+
 /* True if we should use NewABI-style relocation operators for
    symbolic addresses.  This is never true for mips16 code,
    which has its own conventions.  */
@@ -596,6 +600,10 @@ extern const struct mips_cpu_info *mips_tune_info;
      N_("Work around R4000 errata")},                                  \
   {"no-fix-r4000",      -MASK_FIX_R4000,                               \
      N_("Don't work around R4000 errata")},                            \
+  {"fix-r4400",                  MASK_FIX_R4400,                               \
+     N_("Work around R4400 errata")},                                  \
+  {"no-fix-r4400",      -MASK_FIX_R4400,                               \
+     N_("Don't work around R4400 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 a3e6232..4fb703c 100644 (file)
@@ -478,7 +478,8 @@ 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-r4000  -mno-fix-r4000  -mfix-sb1  -mno-fix-sb1 @gol
+-mfix-r4000  -mno-fix-r4000  -mfix-r4400  -mno-fix-r4400 @gol
+-mfix-sb1  -mno-fix-sb1 @gol
 -mflush-func=@var{func}  -mno-flush-func @gol
 -mbranch-likely  -mno-branch-likely}
 
@@ -8048,6 +8049,20 @@ immediately after starting an integer division.
 @item
 A double-word or a variable shift may give an incorrect result if executed
 while an integer multiplication is in progress.
+@item
+An integer division may give an incorrect result if started in a delay slot
+of a taken branch or a jump.
+@end itemize
+
+@item -mfix-r4400
+@itemx -mno-fix-r4400
+@opindex mfix-r4400
+@opindex mno-fix-r4400
+Work around certain R4400 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