+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>
* config/sparc/sync.md (swapsi): 16-byte align if sparc_fix_gr712rc.
}
}
+/* 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
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:
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 *)
"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)