Message ID | 20171120125003.22670-4-cederman@gaisler.com |
---|---|
State | New |
Headers | show |
Series | Workarounds for UT699, UT700, and GR712RC errata | expand |
> 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. OK for mainline and 7 branch modulo the following nits: > +/* True if complex atomic instruction. */ > + > +static int > +atomic_insn_p (rtx_insn *insn) 'bool' instead of 'int'. "True if INSN is an atomic instruction." I'd rename the function into "atomic_insn_for_leon3_p" since you're handling only the LEON3 instructions. > @@ -1021,6 +1037,33 @@ 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. */ Double space after colon. > + 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; > + > + target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); rtx_insn *target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); > + if (target > + && atomic_insn_p (target)) On a single line.
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 8f6eb48..9faf774 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 complex atomic instruction. */ + +static int +atomic_insn_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 @@ -1021,6 +1037,33 @@ 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; + + target = next_active_insn (JUMP_LABEL_AS_INSN (jump)); + if (target + && atomic_insn_p (target)) + emit_insn_before (gen_nop (), target); + } + + next = next_active_insn (insn); + if (!next) + break; + + if (atomic_insn_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 d5c505b..b1baa73 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)