[SPARC] Errata workaround for GRLIB-TN-0010
authorDaniel Cederman <cederman@gaisler.com>
Wed, 29 Nov 2017 15:23:40 +0000 (15:23 +0000)
committerDaniel Hellstrom <danielh@gcc.gnu.org>
Wed, 29 Nov 2017 15:23:40 +0000 (16:23 +0100)
This patch provides a workaround for the errata described in GRLIB-TN-0010.

If the workaround is enabled it will:

 * Insert a NOP between load instruction and atomic
   instruction (swap, ldstub, casa).

 * Insert a NOP at branch target if load in delay slot
   and atomic instruction at branch target.

It is applicable to UT700.

2017-11-29  Daniel Cederman  <cederman@gaisler.com>

gcc/
* config/sparc/sparc.c (atomic_insn_p): New function.
(sparc_do_work_around_errata): Insert NOP instructions to
prevent sequences that could trigger the TN-0010 errata for
UT700.
* config/sparc/sync.md (atomic_compare_and_swap_leon3_1): Make
instruction referable in atomic_insns_p.

From-SVN: r255236

gcc/ChangeLog
gcc/config/sparc/sparc.c
gcc/config/sparc/sync.md

index 02cb730e3cf836a63d679803e2c9a98c3f3d03e3..53f4b45e82fc436b46b9908daa0c4d9abf8e77da 100644 (file)
@@ -1,3 +1,12 @@
+2017-11-29  Daniel Cederman  <cederman@gaisler.com>
+
+       * config/sparc/sparc.c (atomic_insn_p): New function.
+       (sparc_do_work_around_errata): Insert NOP instructions to
+       prevent sequences that could trigger the TN-0010 errata for
+       UT700.
+       * config/sparc/sync.md (atomic_compare_and_swap_leon3_1): Make
+       instruction referable in atomic_insns_p.
+
 2017-11-29  Daniel Cederman  <cederman@gaisler.com>
 
        * config/sparc/sync.md (swapsi): 16-byte align if sparc_fix_gr712rc.
index 32081659e99dd794c0e39fa0bdc714107f7ffe46..7ba3fbf0c1f73262017977af7e7e0dc8dc55b77e 100644 (file)
@@ -970,6 +970,22 @@ fpop_insn_p (rtx_insn *insn)
     }
 }
 
+/* True if INSN is an atomic instruction.  */
+
+static bool
+atomic_insn_for_leon3_p (rtx_insn *insn)
+{
+  switch (INSN_CODE (insn))
+    {
+    case CODE_FOR_swapsi:
+    case CODE_FOR_ldstub:
+    case CODE_FOR_atomic_compare_and_swap_leon3_1:
+      return true;
+    default:
+      return false;
+    }
+}
+
 /* We use a machine specific pass to enable workarounds for errata.
 
    We need to have the (essentially) final form of the insn stream in order
@@ -1024,6 +1040,31 @@ sparc_do_work_around_errata (void)
            emit_insn_before (gen_nop (), target);
        }
 
+      /* Insert a NOP between load instruction and atomic
+        instruction.  Insert a NOP at branch target if load
+        in delay slot and atomic instruction at branch target.  */
+      if (sparc_fix_ut700
+         && NONJUMP_INSN_P (insn)
+         && (set = single_set (insn)) != NULL_RTX
+         && MEM_P (SET_SRC (set))
+         && REG_P (SET_DEST (set)))
+       {
+         if (jump)
+           {
+             rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump));
+             if (target
+                 && atomic_insn_for_leon3_p (target))
+               emit_insn_before (gen_nop (), target);
+           }
+
+         next = next_active_insn (insn);
+         if (!next)
+           break;
+
+         if (atomic_insn_for_leon3_p (next))
+           insert_nop = true;
+       }
+
       /* Look for either of these two sequences:
 
         Sequence A:
@@ -1352,7 +1393,7 @@ public:
   virtual bool gate (function *)
     {
       return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst
-         || sparc_fix_gr712rc;
+         || sparc_fix_gr712rc || sparc_fix_ut700;
     }
 
   virtual unsigned int execute (function *)
index ead7c777caba449e30f3cf8e2e112a4ea572fbde..43c66e96ba34f13af406947fbaa51f486c747e94 100644 (file)
   "cas<modesuffix>\t%1, %2, %0"
   [(set_attr "type" "multi")])
 
-(define_insn "*atomic_compare_and_swap_leon3_1"
+(define_insn "atomic_compare_and_swap_leon3_1"
   [(set (match_operand:SI 0 "register_operand" "=r")
        (match_operand:SI 1 "mem_noofs_operand" "+w"))
    (set (match_dup 1)