@@ -4265,7 +4265,7 @@ case "${target}" in
;;
mips*-*-*)
- supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1 madd4"
+ supported_defaults="abi arch arch_32 arch_64 float fpu nan fp_32 odd_spreg_32 tune tune_32 tune_64 divide llsc mips-plt synci lxc1-sxc1 madd4 fix-loongson3-llsc"
case ${with_float} in
"" | soft | hard)
@@ -4418,6 +4418,21 @@ case "${target}" in
exit 1
;;
esac
+
+ case ${with_fix_loongson3_llsc} in
+ yes)
+ with_fix_loongson3_llsc=fix-loongson3-llsc
+ ;;
+ no)
+ with_fix_loongson3_llsc=no-fix-loongson3-llsc
+ ;;
+ "")
+ ;;
+ *)
+ echo "Unknown fix-loongson3-llsc type used in --with-fix-loongson3-llsc" 1>&2
+ exit 1
+ ;;
+ esac
;;
nds32*-*-*)
@@ -4937,7 +4952,7 @@ case ${target} in
esac
t=
-all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1 madd4"
+all_defaults="abi cpu cpu_32 cpu_64 arch arch_32 arch_64 tune tune_32 tune_64 schedule float mode fpu nan fp_32 odd_spreg_32 divide llsc mips-plt synci tls lxc1-sxc1 madd4 fix-loongson3-llsc"
for option in $all_defaults
do
eval "val=\$with_"`echo $option | sed s/-/_/g`
@@ -14127,7 +14127,7 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
mips_multi_start ();
/* Output the release side of the memory barrier. */
- if (need_atomic_barrier_p (model, true))
+ if (need_atomic_barrier_p (model, true) && !FIX_LOONGSON3_LLSC)
{
if (required_oldval == 0 && TARGET_OCTEON)
{
@@ -14148,6 +14148,10 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
/* Output the branch-back label. */
mips_multi_add_label ("1:");
+ /* Loongson3 target need sync before ll/lld. */
+ if (need_atomic_barrier_p (model, true) && FIX_LOONGSON3_LLSC)
+ mips_multi_add_insn ("sync", NULL);
+
/* OLDVAL = *MEM. */
mips_multi_add_insn (is_64bit_p ? "lld\t%0,%1" : "ll\t%0,%1",
oldval, mem, NULL);
@@ -14257,13 +14261,18 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands)
mips_multi_add_insn ("li\t%0,1", cmp, NULL);
/* Output the acquire side of the memory barrier. */
- if (TARGET_SYNC_AFTER_SC && need_atomic_barrier_p (model, false))
+ if (TARGET_SYNC_AFTER_SC && need_atomic_barrier_p (model, false)
+ && !FIX_LOONGSON3_LLSC)
mips_multi_add_insn ("sync", NULL);
/* Output the exit label, if needed. */
if (required_oldval)
mips_multi_add_label ("2:");
+ /* Loongson3 need a sync before branch target that between ll and sc. */
+ if (FIX_LOONGSON3_LLSC)
+ mips_multi_add_insn ("sync", NULL);
+
#undef READ_OPERAND
}
@@ -655,6 +655,8 @@ struct mips_cpu_info {
builtin_define ("__mips_no_lxc1_sxc1"); \
if (!ISA_HAS_UNFUSED_MADD4 && !ISA_HAS_FUSED_MADD4) \
builtin_define ("__mips_no_madd4"); \
+ if (FIX_LOONGSON3_LLSC) \
+ builtin_define ("__mips_fix_loongson3_llsc"); \
} \
while (0)
@@ -890,7 +892,9 @@ struct mips_cpu_info {
{"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }, \
{"synci", "%{!msynci:%{!mno-synci:-m%(VALUE)}}" }, \
{"lxc1-sxc1", "%{!mlxc1-sxc1:%{!mno-lxc1-sxc1:-m%(VALUE)}}" }, \
- {"madd4", "%{!mmadd4:%{!mno-madd4:-m%(VALUE)}}" } \
+ {"madd4", "%{!mmadd4:%{!mno-madd4:-m%(VALUE)}}" }, \
+ {"fix-loongson3-llsc", "%{!mfix-loongson3-llsc: \
+ %{!mno-fix-loongson3-llsc:-m%(VALUE)}}" }
/* A spec that infers the:
-mnan=2008 setting from a -mips argument,
@@ -1415,6 +1419,7 @@ struct mips_cpu_info {
%{mfix-rm7000} %{mno-fix-rm7000} \
%{mfix-vr4120} %{mfix-vr4130} \
%{mfix-24k} \
+%{mfix-loongson3-llsc} %{mno-fix-loongson3-llsc} \
%{noasmopt:-O0; O0|fno-delayed-branch:-O1; O*:-O2; :-O1} \
%(subtarget_asm_debugging_spec) \
%{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \
@@ -193,6 +193,10 @@ mfix4300
Target Report Var(TARGET_4300_MUL_FIX)
Work around an early 4300 hardware bug.
+mfix-loongson3-llsc
+Target Report Var(FIX_LOONGSON3_LLSC)
+Work around an Loongson3 llsc errata.
+
mfp-exceptions
Target Report Var(TARGET_FP_EXCEPTIONS) Init(1)
FP exceptions are enabled.
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "-mfix-loongson3-llsc" } */
+
+NOMIPS16 int foo (int *v)
+{
+ return __sync_val_compare_and_swap (v, 0, 1);
+}
+
+/* { dg-final { scan-assembler "1:\n\tsync\n\tll" } } */
+/* { dg-final { scan-assembler "2:\n\tsync\n" } } */
@@ -281,6 +281,7 @@ foreach option {
fix-r4000
fix-r10000
fix-vr4130
+ fix-loongson3-llsc
gpopt
local-sdata
long-calls
From: Paul Hua <paul.hua.gm@gmail.com> In some older Loongson3 processors there is a LL/SC errata that can cause the CPU to deadlock occasionally. The details are very complicated. We find a way to work around this errata by a) adding a sync before ll/lld instruction, b) adding a sync before branch target that between ll and sc. The assembler do the jobs 'a', gcc do the jobs 'b'. This patch add an option '-mfix-loongson3-llsc' option, and it will also call 'as' with the same option. So if 'as' doesn't support this option, an error will happen. The macro '__mips_fix_loongson3_llsc' is predefined, when this option is enabled, as some program, like linux kernel will need to aware this option is used. This patch also add a configure options --with-mips-fix-loongson3-llsc=[yes|no] to enable fix-loongson3-llsc by config. v1 -> v2: * Predefine __mips_fix_loongson3_llsc. * Add to ASM_SPECS. gcc/ * config.gcc (supported_defaults): Add fix-loongson3-llsc (with_fix_loongson3_llsc): Add validation. (all_defaults): Add fix-loongson3-llsc. * config/mips/mips.c (mips_process_sync_loop): Add sync before branch target that between ll and sc. * config/mips/mips.h (OPTION_DEFAULT_SPECS): Add a default for fix-loongson3-llsc. (ASM_SPECS): Add a default for fix-loongson3-llsc. (TARGET_CPU_CPP_BUILTINS): Predefine __mips_fix_loongson3_llsc. gcc/config/mips/mips.opt: New option. * doc/install.texi (--with-fix-loongson3-llsc):Document the new option. * doc/invoke.texi (-mfix-loongson3-llsc):Document the new option. gcc/testsuite/ * gcc.target/mips/fix-loongson3-llsc.c: New test. * gcc.target/mips/mips.exp (option): Add fix-loongson3-llsc. --- gcc/config.gcc | 19 +++++++++++++++++-- gcc/config/mips/mips.c | 13 +++++++++++-- gcc/config/mips/mips.h | 7 ++++++- gcc/config/mips/mips.opt | 4 ++++ .../gcc.target/mips/fix-loongson3-llsc.c | 10 ++++++++++ gcc/testsuite/gcc.target/mips/mips.exp | 1 + 6 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/fix-loongson3-llsc.c