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]

Re: head: MIPS: Workaround an R4000SC/MC branch/divide erratum


On Mon, 1 Mar 2004, Richard Sandiford wrote:

> Anyhow, after the change to force division into the delay slot,
> I think all we need to do is swap the clauses around, like so:
[...]
> If you agree, I'll test your patch with that change.

 It looks promising.  Here's a rediffed version with associated 
documentation updates.

2004-03-01  Richard Sandiford  <rsandifo@redhat.com>
            Maciej W. Rozycki  <macro@ds2.pg.gda.pl>

	* gcc/config/mips/mips.c (mips_output_division): Work around the
	R4000SC/MC branch/divide erratum.
	gcc/doc/invoke.texi: Document the new workaround.

  Maciej

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

gcc-3.4-20031107-mips-r4000-brdiv.patch
diff -up --recursive --new-file gcc-3.4-20031107.macro/gcc/config/mips/mips.c gcc-3.4-20031107/gcc/config/mips/mips.c
--- gcc-3.4-20031107.macro/gcc/config/mips/mips.c	2004-03-01 18:56:29.000000000 +0000
+++ gcc-3.4-20031107/gcc/config/mips/mips.c	2004-03-01 19:08:08.000000000 +0000
@@ -9107,6 +9107,58 @@ mips_output_conditional_branch (rtx insn
    Revision 1.0" and "MIPS R4400MC Errata, Processor Revision 2.0
    & 3.0" as errata #10 and #4, respectively.
 
+   Another bug is present in the R4000SC processor.  Under certain
+   conditions if an integer division is started in the delay slot of
+   a taken branch or a jump, the result of the division may be
+   incorrect.  Avoid this by placing a division outside a delay slot.
+
+   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
+		nop				# ICache miss and 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."
+
+   I've been able to observe item 2) as described above even when
+   branching within a single page. --macro
+
    These processors have PRId values of 0x00004220 and 0x00004300 for
    the R4000 and 0x00004400, 0x00004500 and 0x00004600 for the R4400.
 
@@ -9118,6 +9170,11 @@ mips_output_division (const char *divisi
   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)
@@ -9132,11 +9189,6 @@ mips_output_division (const char *divisi
 	  s = "break\t7%)\n1:";
 	}
     }
-  if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
-    {
-      output_asm_insn (s, operands);
-      s = "nop";
-    }
   return s;
 }
 
diff -up --recursive --new-file gcc-3.4-20031107.macro/gcc/doc/invoke.texi gcc-3.4-20031107/gcc/doc/invoke.texi
--- gcc-3.4-20031107.macro/gcc/doc/invoke.texi	2004-03-01 12:09:15.000000000 +0000
+++ gcc-3.4-20031107/gcc/doc/invoke.texi	2004-03-01 12:10:29.000000000 +0000
@@ -8453,6 +8453,9 @@ immediately after starting an integer di
 @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


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