aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDaniel Cederman <cederman@gaisler.com>2017-11-29 15:23:40 +0000
committerDaniel Hellstrom <danielh@gcc.gnu.org>2017-11-29 16:23:40 +0100
commit47c72733ab0cc1ca5b7bb196298ce9ecd91c1896 (patch)
tree6d04b95f61c870986f2a7454cab083392e50b7d0 /gcc
parentaed173734df52b9c48425840c0977c34c23a882a (diff)
downloadgcc-47c72733ab0cc1ca5b7bb196298ce9ecd91c1896.zip
gcc-47c72733ab0cc1ca5b7bb196298ce9ecd91c1896.tar.gz
gcc-47c72733ab0cc1ca5b7bb196298ce9ecd91c1896.tar.bz2
[SPARC] Errata workaround for GRLIB-TN-0010
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/sparc/sparc.c43
-rw-r--r--gcc/config/sparc/sync.md2
3 files changed, 52 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 02cb730..53f4b45 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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.
(atomic_compare_and_swap_leon3_1): Likewise.
(ldstub): Likewise.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 3208165..7ba3fbf 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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 *)
diff --git a/gcc/config/sparc/sync.md b/gcc/config/sparc/sync.md
index ead7c77..43c66e9 100644
--- a/gcc/config/sparc/sync.md
+++ b/gcc/config/sparc/sync.md
@@ -212,7 +212,7 @@
"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)