Hi Eric, This patch adds a workaround to the Sparc backend for the LEON3FT store-store errata. It is enabled using the -mfix-b2bst flag.
The workaround inserts NOP instructions to prevent the following two instruction sequences from being generated: std -> stb/sth/st/std stb/sth/st -> any single non-store/load instruction -> stb/sth/st/std The __FIX_B2BST define can be used to only enable workarounds in assembly code when the flag is used. See GRLIB-TN-0009, "LEON3FT Stale Cache Entry After Store with Data Tag Parity Error", for more information. gcc/ChangeLog: 2017-01-18 Daniel Cederman <ceder...@gaisler.com> * config/sparc/sparc.c (sparc_do_work_around_errata): Insert NOP instructions to prevent sequences that can trigger the store-store errata for certain LEON3FT processors. Enable with -mfix-b2bst. (sparc_option_override): -mfix-ut699 implies -mfix-b2bst. * config/sparc/sparc-c.c (sparc_target_macros): Define __FIX_B2BST. * config/sparc/sparc.md: Prevent stores in delay slot. * config/sparc/sparc.opt: Add -mfix-b2bst flag. * doc/invoke.texi: Document -mfix-b2bst flag. --- gcc/config/sparc/sparc-c.c | 3 ++ gcc/config/sparc/sparc.c | 104 ++++++++++++++++++++++++++++++++++++++++++++- gcc/config/sparc/sparc.md | 10 ++++- gcc/config/sparc/sparc.opt | 4 ++ gcc/doc/invoke.texi | 7 ++- 5 files changed, 123 insertions(+), 5 deletions(-) diff --git a/gcc/config/sparc/sparc-c.c b/gcc/config/sparc/sparc-c.c index 9603173..6979f9c 100644 --- a/gcc/config/sparc/sparc-c.c +++ b/gcc/config/sparc/sparc-c.c @@ -60,4 +60,7 @@ sparc_target_macros (void) cpp_define (parse_in, "__VIS__=0x100"); cpp_define (parse_in, "__VIS=0x100"); } + + if (sparc_fix_b2bst) + builtin_define_std ("__FIX_B2BST"); } diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index b9213c3..8d3d5f6 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -896,6 +896,12 @@ mem_ref (rtx x) to properly detect the various hazards. Therefore, this machine specific pass runs as late as possible. */ +/* True if INSN is a md pattern or asm statement. */ +#define USEFUL_INSN_P(INSN) \ + (NONDEBUG_INSN_P (INSN) \ + && GET_CODE (PATTERN (INSN)) != USE \ + && GET_CODE (PATTERN (INSN)) != CLOBBER) + static unsigned int sparc_do_work_around_errata (void) { @@ -915,6 +921,95 @@ sparc_do_work_around_errata (void) if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn))) insn = seq->insn (1); + /* Look for a double-word store. */ + if (sparc_fix_b2bst + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_DEST (set))) == 8 + && MEM_P (SET_DEST (set))) + { + next = next_active_insn (insn); + if (!next) + break; + + /* Skip empty assembly statements. */ + if (USEFUL_INSN_P (next) + && (asm_noperands (PATTERN (next))>=0) + && !strcmp (decode_asm_operands (PATTERN (next), + NULL, NULL, NULL, + NULL, NULL), "")) + next = next_active_insn (next); + if (!next) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + if ((set = single_set (next)) == NULL_RTX) + continue; + + /* Add NOP if double-word store is followed by any type of store. */ + if (MEM_P (SET_DEST (set))) + insert_nop = true; + } + else + /* Look for single-word, half-word, or byte store. */ + if (sparc_fix_b2bst + && NONJUMP_INSN_P (insn) + && (set = single_set (insn)) != NULL_RTX + && GET_MODE_SIZE (GET_MODE (SET_DEST (set))) <= 4 + && MEM_P (SET_DEST (set))) + { + rtx_insn *after; + + next = next_active_insn (insn); + if (!next) + break; + + /* Skip empty assembly statements. */ + if (USEFUL_INSN_P (next) + && (asm_noperands (PATTERN (next))>=0) + && !strcmp (decode_asm_operands (PATTERN (next), + NULL, NULL, NULL, + NULL, NULL), "")) + next = next_active_insn (next); + if (!next) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) == SEQUENCE) + continue; + + /* If the insn is a load or store, then it cannot be problematic. */ + if ((set = single_set (next)) != NULL_RTX + && (MEM_P (SET_DEST (set)) || MEM_P (SET_SRC (set)))) + continue; + + after = next_active_insn (next); + if (!after) + continue; + + /* Skip empty assembly statements. */ + if (USEFUL_INSN_P (after) + && (asm_noperands (PATTERN (after))>=0) + && !strcmp (decode_asm_operands (PATTERN (after), + NULL, NULL, NULL, + NULL, NULL), "")) + after = next_active_insn (after); + if (!after) + break; + + /* If the insn is a branch, then it cannot be problematic. */ + if (!NONJUMP_INSN_P (after) || GET_CODE (PATTERN (after)) == SEQUENCE) + continue; + + /* Add NOP if third instruction is a store. */ + if (((set = single_set (after)) != NULL_RTX) + && MEM_P (SET_DEST (set))) + insert_nop = true; + } + else /* Look for a single-word load into an odd-numbered FP register. */ if (sparc_fix_at697f && NONJUMP_INSN_P (insn) @@ -1167,8 +1262,9 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { - /* The only errata we handle are those of the AT697F and UT699. */ - return sparc_fix_at697f != 0 || sparc_fix_ut699 != 0; + /* The only errata we handle are those of the AT697F, + UT699 and certain LEON3FT. */ + return sparc_fix_at697f || sparc_fix_ut699 || sparc_fix_b2bst; } virtual unsigned int execute (function *) @@ -1527,6 +1623,10 @@ sparc_option_override (void) if (!(target_flags_explicit & MASK_LRA)) target_flags |= MASK_LRA; + /* -mfix-ut699 implies -mfix-b2bst. */ + if (sparc_fix_ut699) + sparc_fix_b2bst = 1; + /* Supply a default value for align_functions. */ if (align_functions == 0 && (sparc_cpu == PROCESSOR_ULTRASPARC diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 29a8bcf..a98acf7 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -329,6 +329,10 @@ (symbol_ref "(sparc_fix_ut699 != 0 ? FIX_UT699_TRUE : FIX_UT699_FALSE)")) +(define_attr "fix_b2bst" "false,true" + (symbol_ref "(sparc_fix_b2bst != 0 + ? FIX_B2BST_TRUE : FIX_B2BST_FALSE)")) + ;; Length (in # of insns). ;; Beware that setting a length greater or equal to 3 for conditional branches ;; has a side-effect (see output_cbranch and output_v9branch). @@ -475,6 +479,8 @@ (define_attr "in_branch_delay" "false,true" (cond [(eq_attr "type" "uncond_branch,branch,cbcond,uncond_cbcond,call,sibcall,call_no_delay_slot,multi") (const_string "false") + (and (eq_attr "fix_b2bst" "true") (eq_attr "type" "store,fpstore")) + (const_string "false") (and (eq_attr "fix_ut699" "true") (eq_attr "type" "load,sload")) (const_string "false") (and (eq_attr "fix_ut699" "true") @@ -6060,7 +6066,7 @@ (div:DF (match_operand:DF 1 "register_operand" "e") (match_operand:DF 2 "register_operand" "e")))] "TARGET_FPU && sparc_fix_ut699" - "fdivd\t%1, %2, %0\n\tstd\t%0, [%%sp-8]" + "fdivd\t%1, %2, %0\n\tnop\n\tstd\t%0, [%%sp-8]\n\tnop" [(set_attr "type" "fpdivd") (set_attr "fptype" "double") (set_attr "length" "2")]) @@ -6312,7 +6318,7 @@ [(set (match_operand:DF 0 "register_operand" "=e") (sqrt:DF (match_operand:DF 1 "register_operand" "e")))] "TARGET_FPU && sparc_fix_ut699" - "fsqrtd\t%1, %0\n\tstd\t%0, [%%sp-8]" + "fsqrtd\t%1, %0\n\tnop\n\tstd\t%0, [%%sp-8]\n\tnop" [(set_attr "type" "fpsqrtd") (set_attr "fptype" "double") (set_attr "length" "2")]) diff --git a/gcc/config/sparc/sparc.opt b/gcc/config/sparc/sparc.opt index 86f85d9..02b52be 100644 --- a/gcc/config/sparc/sparc.opt +++ b/gcc/config/sparc/sparc.opt @@ -230,6 +230,10 @@ mfix-ut699 Target Report RejectNegative Var(sparc_fix_ut699) Enable workarounds for the errata of the UT699 processor. +mfix-b2bst +Target Report RejectNegative Var(sparc_fix_b2bst) +Enable workarounds for LEON3FT store-store errata + Mask(LONG_DOUBLE_128) ;; Use 128-bit long double diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 99f193e..870b795 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -1117,7 +1117,7 @@ See RS/6000 and PowerPC Options. -mvis2 -mno-vis2 -mvis3 -mno-vis3 @gol -mcbcond -mno-cbcond -mfmaf -mno-fmaf @gol -mpopc -mno-popc -msubxc -mno-subxc@gol --mfix-at697f -mfix-ut699 @gol +-mfix-at697f -mfix-ut699 -mfix-b2bst @gol -mlra -mno-lra} @emph{SPU Options} @@ -23513,6 +23513,11 @@ processor (which corresponds to erratum #13 of the AT697E processor). @opindex mfix-ut699 Enable the documented workarounds for the floating-point errata and the data cache nullify errata of the UT699 processor. + +@item -mfix-b2bst +@opindex mfix-b2bst +Enable the documented workaround for the back-to-back store errata of +certain LEON3FT processors. @end table These @samp{-m} options are supported in addition to the above -- 2.9.3