This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH v2 3/4] [SPARC] Errata workaround for GRLIB-TN-0010
- From: Daniel Cederman <cederman at gaisler dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: ebotcazou at adacore dot com, sebastian dot huber at embedded-brains dot de, daniel at gaisler dot com
- Date: Mon, 27 Nov 2017 10:57:14 +0100
- Subject: [PATCH v2 3/4] [SPARC] Errata workaround for GRLIB-TN-0010
- Authentication-results: sourceware.org; auth=none
- Authorized-sender: cederman at gaisler dot com
- References: <20171127095715.5938-1-cederman@gaisler.com>
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.
gcc/ChangeLog:
2017-11-17 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.
---
gcc/config/sparc/sparc.c | 41 +++++++++++++++++++++++++++++++++++++++++
gcc/config/sparc/sync.md | 2 +-
2 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 51045db..401dfcb 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:
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)
--
2.9.3