From 47c72733ab0cc1ca5b7bb196298ce9ecd91c1896 Mon Sep 17 00:00:00 2001 From: Daniel Cederman Date: Wed, 29 Nov 2017 15:23:40 +0000 Subject: [PATCH] [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 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 | 9 +++++++++ gcc/config/sparc/sparc.c | 43 +++++++++++++++++++++++++++++++++++++++- gcc/config/sparc/sync.md | 2 +- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 02cb730e3cf..53f4b45e82f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-11-29 Daniel Cederman + + * 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 * config/sparc/sync.md (swapsi): 16-byte align if sparc_fix_gr712rc. diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 32081659e99..7ba3fbf0c1f 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 ead7c777cab..43c66e96ba3 100644 --- a/gcc/config/sparc/sync.md +++ b/gcc/config/sparc/sync.md @@ -212,7 +212,7 @@ "cas\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.30.2