[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. Backport from mainline 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: r255242
This commit is contained in:
parent
e3f124c72d
commit
304d27a099
|
@ -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>
|
||||
|
||||
Backport from mainline
|
||||
|
|
|
@ -939,6 +939,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
|
||||
|
@ -993,6 +1009,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:
|
||||
|
@ -1321,7 +1362,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 *)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue