This is the mail archive of the
mailing list for the GCC project.
Re: head: MIPS: Workaround an R4000SC/MC branch/divide erratum
- From: "Maciej W. Rozycki" <macro at ds2 dot pg dot gda dot pl>
- To: Richard Sandiford <rsandifo at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 1 Mar 2004 20:12:25 +0100 (CET)
- Subject: Re: head: MIPS: Workaround an R4000SC/MC branch/divide erratum
- Organization: Technical University of Gdansk
- References: <Pine.LNX.firstname.lastname@example.org><email@example.com>
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
2004-03-01 Richard Sandiford <firstname.lastname@example.org>
Maciej W. Rozycki <email@example.com>
* 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 W. Rozycki, Technical University of Gdansk, Poland +
+ e-mail: firstname.lastname@example.org, PGP key available +
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.
+ div r8, r9
+ ------------------- # end-of page. -tlb-refill
+ div r8, r9
+ ------------------- # end-of page. -tlb-invalid
+ 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.
+ 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
+ beq r0, r0, NextPage # to Next page
+ div r8,r9
+ This bug is present for div, divu, ddiv, and ddivu
+ 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";
@@ -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";
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
A double-word or a variable shift may give an incorrect result if executed
while an integer multiplication is in progress.
+An integer division may give an incorrect result if started in a delay slot
+of a taken branch or a jump.