Hi, The atomic-compare-exchange-3.c and atomic-op-3.c tests are failing when using the -mfix-r10000 option. This is due to the fact that the delay slot of the branch instruction that checks if the atomic operation was not successful can be filled with an operation that returns the output result. For the branch likely case this operation can not go in the delay slot because it wont execute when the atomic operation was successful and therefore the wrong result will be returned. This patch forces a nop to be placed in the delay slot if a branch likely is used. The fix is as simple as possible; it does cause a second nop to be introduced after the branch instruction in the branch likely case. As this option is rarely used, it makes more sense to keep the code readable than trying to optimise it.
The atomic tests now pass successfully. The ChangeLog and patch are below. Ok to commit? Many thanks, Andrew gcc/ * config/mips/mips.c (mips_process_sync_loop): Place a nop in the delay slot of the branch likely instruction. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 02268f3..6dd3728 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -12997,7 +12997,12 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands) This will sometimes be a delayed branch; see the write code below for details. */ mips_multi_add_insn (is_64bit_p ? "scd\t%0,%1" : "sc\t%0,%1", at, mem, NULL); - mips_multi_add_insn ("beq%?\t%0,%.,1b", at, NULL); + + /* We can not put the NEWVAL = $TMP3 or CMP = 1 operations in the delay slot + of the branch if it is a branch likely because they will not execute when + the atomic operation is successful, so place a NOP in there instead. */ + + mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL); /* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]. */ if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval)