MIPS: Fix delay slot bug in `atomic*_sub_if_positive' for R10000_LLSC_WAR
authorJoshua Kinard <kumba@gentoo.org>
Sun, 19 Nov 2017 03:29:56 +0000 (22:29 -0500)
committerPaul Burton <paul.burton@mips.com>
Thu, 12 Jul 2018 18:14:10 +0000 (11:14 -0700)
This patch fixes an old bug in MIPS ll/sc atomics, in the
`atomic_sub_if_positive' and `atomic64_sub_if_positive' functions, for
the R10000_LLSC_WAR case where the result of the subu/dsubu instruction
would potentially not be made available to the sc/scd instruction due
to being in the delay-slot of the branch-likely (beqzl) instruction.

This also removes the need for the `noreorder' directive, allowing GAS
to use delay slot scheduling as needed.

The same fix is also applied to the standard branch (beqz) case in
preparation for a follow-up patch that will cleanup/merge the
R10000_LLSC_WAR and non-R10K sections together.

Signed-off-by: Joshua Kinard <kumba@gentoo.org>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Tested-by: Joshua Kinard <kumba@gentoo.org>
Patchwork: https://patchwork.linux-mips.org/patch/17735/
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <james.hogan@mips.com>
Cc: "Maciej W. Rozycki" <macro@mips.com>
Cc: linux-mips@linux-mips.org
arch/mips/include/asm/atomic.h

index 0ab176bdb8e8107e3a8b700215ce9a96471b3ee9..0babf2775d8edc8310b4ed6713704bae07d6ea9e 100644 (file)
@@ -225,12 +225,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
                "       .set    arch=r4000                              \n"
                "1:     ll      %1, %2          # atomic_sub_if_positive\n"
                "       subu    %0, %1, %3                              \n"
+               "       move    %1, %0                                  \n"
                "       bltz    %0, 1f                                  \n"
-               "       sc      %0, %2                                  \n"
-               "       .set    noreorder                               \n"
-               "       beqzl   %0, 1b                                  \n"
-               "        subu   %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
+               "       sc      %1, %2                                  \n"
+               "       beqzl   %1, 1b                                  \n"
                "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp),
@@ -244,12 +242,10 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v)
                "       .set    "MIPS_ISA_LEVEL"                        \n"
                "1:     ll      %1, %2          # atomic_sub_if_positive\n"
                "       subu    %0, %1, %3                              \n"
+               "       move    %1, %0                                  \n"
                "       bltz    %0, 1f                                  \n"
-               "       sc      %0, %2                                  \n"
-               "       .set    noreorder                               \n"
-               "       beqz    %0, 1b                                  \n"
-               "        subu   %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
+               "       sc      %1, %2                                  \n"
+               "       beqz    %1, 1b                                  \n"
                "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp),
@@ -570,12 +566,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
                "       .set    arch=r4000                              \n"
                "1:     lld     %1, %2          # atomic64_sub_if_positive\n"
                "       dsubu   %0, %1, %3                              \n"
+               "       move    %1, %0                                  \n"
                "       bltz    %0, 1f                                  \n"
-               "       scd     %0, %2                                  \n"
-               "       .set    noreorder                               \n"
-               "       beqzl   %0, 1b                                  \n"
-               "        dsubu  %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
+               "       scd     %1, %2                                  \n"
+               "       beqzl   %1, 1b                                  \n"
                "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp),
@@ -589,12 +583,10 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v)
                "       .set    "MIPS_ISA_LEVEL"                        \n"
                "1:     lld     %1, %2          # atomic64_sub_if_positive\n"
                "       dsubu   %0, %1, %3                              \n"
+               "       move    %1, %0                                  \n"
                "       bltz    %0, 1f                                  \n"
-               "       scd     %0, %2                                  \n"
-               "       .set    noreorder                               \n"
-               "       beqz    %0, 1b                                  \n"
-               "        dsubu  %0, %1, %3                              \n"
-               "       .set    reorder                                 \n"
+               "       scd     %1, %2                                  \n"
+               "       beqz    %1, 1b                                  \n"
                "1:                                                     \n"
                "       .set    mips0                                   \n"
                : "=&r" (result), "=&r" (temp),