[PATCH] [SPARC] Add a workaround for the LEON3FT store-store errata
Daniel Cederman
cederman@gaisler.com
Wed Jun 21 13:28:00 GMT 2017
Hello all,
I have modified the patch so that the workaround is enabled by using
either mfix-ut699, -mfix-ut700, or -mfix-gr712rc.
Daniel
-
This patch adds a workaround to the Sparc backend for the LEON3FT
store-store errata. It is enabled when using the -mfix-ut699,
-mfix-ut700, or -mfix-gr712rc 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-06-21 Daniel Cederman <cederman@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.
(sparc_option_override): -mfix-ut699, -mfix-ut700, and
-mfix-gr712rc enables the errata workaround.
* config/sparc/sparc-c.c (sparc_target_macros): Define __FIX_B2BST
when errata workaround is enabled.
* config/sparc/sparc.md: Prevent stores in delay slot.
* config/sparc/sparc.opt: Add -mfix-ut700 and -mfix-gr712rc flag.
* doc/invoke.texi: Document -mfix-ut700 and -mfix-gr712rc flag.
---
gcc/config/sparc/sparc-c.c | 3 ++
gcc/config/sparc/sparc.c | 115 ++++++++++++++++++++++++++++++++++++++++++++-
gcc/config/sparc/sparc.md | 10 +++-
gcc/config/sparc/sparc.opt | 12 +++++
gcc/doc/invoke.texi | 14 +++++-
5 files changed, 148 insertions(+), 6 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 790a036..6d6c941 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,98 @@ 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 ((GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE)
+ || (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 ((GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE)
+ || (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 ((GET_CODE (PATTERN (after)) == UNSPEC_VOLATILE)
+ || (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 +1265,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 *)
@@ -1519,6 +1618,18 @@ sparc_option_override (void)
if (!(target_flags_explicit & MASK_LRA))
target_flags |= MASK_LRA;
+ /* -mfix-ut699 enables the back-to-back store errata workaround. */
+ if (sparc_fix_ut699)
+ sparc_fix_b2bst = 1;
+
+ /* -mfix-ut700 enables the back-to-back store errata workaround. */
+ if (sparc_fix_ut700)
+ sparc_fix_b2bst = 1;
+
+ /* -mfix-gr712rc enables the back-to-back store errata workaround. */
+ if (sparc_fix_gr712rc)
+ sparc_fix_b2bst = 1;
+
/* Supply a default value for align_functions. */
if (align_functions == 0)
{
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 5c5096b..6c1b1e3 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).
@@ -476,6 +480,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")
@@ -6061,7 +6067,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")])
@@ -6313,7 +6319,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..a44945f 100644
--- a/gcc/config/sparc/sparc.opt
+++ b/gcc/config/sparc/sparc.opt
@@ -230,6 +230,18 @@ mfix-ut699
Target Report RejectNegative Var(sparc_fix_ut699)
Enable workarounds for the errata of the UT699 processor.
+mfix-ut700
+Target Report RejectNegative Var(sparc_fix_ut700)
+Enable workarounds for the errata of the UT699E/UT700 processor.
+
+mfix-gr712rc
+Target Report RejectNegative Var(sparc_fix_gr712rc)
+Enable workarounds for the errata of the GR712RC processor.
+
+;; Enable workaround for back-to-back store errata
+TargetVariable
+unsigned int sparc_fix_b2bst
+
Mask(LONG_DOUBLE_128)
;; Use 128-bit long double
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 86c8d62..b926e73 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1127,8 +1127,8 @@ 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
--mlra -mno-lra}
+-mfix-at697f -mfix-ut699 -mfix-ut700 @gol
+-mfix-gr712rc -mlra -mno-lra}
@emph{SPU Options}
@gccoptlist{-mwarn-reloc -merror-reloc @gol
@@ -24013,6 +24013,16 @@ 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-ut700
+@opindex mfix-ut700
+Enable the documented workaround for the back-to-back store errata of
+the UT699E/UT700 processor.
+
+@item -mfix-gr712rc
+@opindex mfix-gr712rc
+Enable the documented workaround for the back-to-back store errata of
+the GR712RC processor.
@end table
These @samp{-m} options are supported in addition to the above
--
2.9.3
More information about the Gcc-patches
mailing list