This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

head: MIPS: A workaround for the R4400MC divide/shift erratum


Hello,

 There is a divide/shift erratum in all versions of the R4400MC and the
R4400MC, similar to the one in the R4000, I've sent a patch for
previously.  Here's a workaround, taking the same precautions as for the
other erratum.  See the patch for a description of the faulting condition.

2004-03-01  Maciej W. Rozycki  <macro@ds2.pg.gda.pl>

	* 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_idiv_insns): Take TARGET_FIX_R4400 into 
	account.
	(mips_output_division): Likewise.
	(override_options): Make -march=r4400 imply -mfix-r4400 by default.

 The patch was tested by building a cross-compiler for the mips64el-linux
target, then building a Linux kernel.

 Please apply.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

gcc-3.5.0-20040301-mips-R4400-div.patch
diff -up --recursive --new-file gcc-3.5.0-20040301.macro/gcc/config/mips/mips.c gcc-3.5.0-20040301/gcc/config/mips/mips.c
--- gcc-3.5.0-20040301.macro/gcc/config/mips/mips.c	2004-02-29 02:26:55.000000000 +0000
+++ gcc-3.5.0-20040301/gcc/config/mips/mips.c	2004-03-01 14:39:22.000000000 +0000
@@ -1365,7 +1365,7 @@ mips_idiv_insns (void)
       else
 	count += 3;
     }
-  if (TARGET_FIX_R4000)
+  if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
     count++;
   return count;
 }
@@ -5137,6 +5137,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.  */
@@ -9220,6 +9226,27 @@ mips_output_conditional_branch (rtx insn
    R4000PC/SC Errata, Processor Revision 2.2 and 3.0" in mips.md for
    details.
 
+   A similar bug 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.
+
+   These processors have PRId values of 0x00004220 and 0x00004300 for
+   the R4000 and 0x00004400, 0x00004500 and 0x00004600 for the R4400.
+
    Otherwise just return DIVISION itself.  */
 
 const char *
@@ -9236,7 +9263,7 @@ mips_output_division (const char *divisi
       else
 	s = "bne\t%2,%.,1f%#\n\tbreak\t7\n1:";
     }
-  if (TARGET_FIX_R4000)
+  if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
     {
       output_asm_insn (s, operands);
       s = "nop";
diff -up --recursive --new-file gcc-3.5.0-20040301.macro/gcc/config/mips/mips.h gcc-3.5.0-20040301/gcc/config/mips/mips.h
--- gcc-3.5.0-20040301.macro/gcc/config/mips/mips.h	2004-02-29 02:26:55.000000000 +0000
+++ gcc-3.5.0-20040301/gcc/config/mips/mips.h	2004-03-01 14:39:22.000000000 +0000
@@ -170,7 +170,8 @@ extern const struct mips_cpu_info *mips_
 			   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_
 					/* 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_
      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,			\
diff -up --recursive --new-file gcc-3.5.0-20040301.macro/gcc/doc/invoke.texi gcc-3.5.0-20040301/gcc/doc/invoke.texi
--- gcc-3.5.0-20040301.macro/gcc/doc/invoke.texi	2004-02-29 02:27:05.000000000 +0000
+++ gcc-3.5.0-20040301/gcc/doc/invoke.texi	2004-03-01 14:40:06.000000000 +0000
@@ -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}
 
@@ -8060,6 +8061,17 @@ A double-word or a variable shift may gi
 while an integer multiplication is in progress.
 @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
 @itemx -mno-fix-sb1
 @opindex mfix-sb1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]