Fix a potential deadlock in some older Loongson 3A1000 MIPS processors.
authorPaul Hua <paul.hua.gm@gmail.com>
Tue, 19 Feb 2019 17:57:16 +0000 (17:57 +0000)
committerNick Clifton <nickc@redhat.com>
Tue, 19 Feb 2019 17:57:16 +0000 (17:57 +0000)
* NEWS: Mention -m[no-]fix-loongson3-llsc.
* configure.ac: Add --enable-mips-fix-loongson3-llsc.
Define DEFAULT_MIPS_FIX_LOONGSON3_LLSC.
* config.in: Regenerated.
* configure: Likewise.
* config/tc-mips.c (sync_insn, mips_fix_loongson3_llsc):
New variables.
(options): New OPTION_FIX_LOONGSON3_LLSC,
OPTION_NO_FIX_LOONGSON3_LLSC.
(md_longopts): Add -m[no-]fix-loongson3-llsc.
(md_begin): Initialize sync insn.
(fix_loongson3_llsc): New.
(append_insn): Call fix_loongson3_llsc.
(md_parse_option): Handle OPTION_FIX_LOONGSON3_LLSC,
OPTION_NO_FIX_LOONGSON3_LLSC.
(md_show_usage): Display -m[no-]fix-loongson3-llsc.
* doc/c-mips.texi: Document -m[no-]fix-loongson3-llsc,
--enable-mips-fix-loongson3-llsc=[yes|no].

gas/ChangeLog
gas/NEWS
gas/config.in
gas/config/tc-mips.c
gas/configure
gas/configure.ac
gas/doc/c-mips.texi

index 04ad383e89dcc44f78566fa9f43c119ac5be1733..2a4f194814444775eee019e94a16e0e26e805740 100644 (file)
@@ -1,3 +1,24 @@
+2019-02-19  Paul Hua  <paul.hua.gm@gmail.com>
+
+       * NEWS: Mention -m[no-]fix-loongson3-llsc.
+       * configure.ac: Add --enable-mips-fix-loongson3-llsc.
+       Define DEFAULT_MIPS_FIX_LOONGSON3_LLSC.
+       * config.in: Regenerated.
+       * configure: Likewise.
+       * config/tc-mips.c (sync_insn, mips_fix_loongson3_llsc):
+       New variables.
+       (options): New OPTION_FIX_LOONGSON3_LLSC,
+       OPTION_NO_FIX_LOONGSON3_LLSC.
+       (md_longopts): Add -m[no-]fix-loongson3-llsc.
+       (md_begin): Initialize sync insn.
+       (fix_loongson3_llsc): New.
+       (append_insn): Call fix_loongson3_llsc.
+       (md_parse_option): Handle OPTION_FIX_LOONGSON3_LLSC,
+       OPTION_NO_FIX_LOONGSON3_LLSC.
+       (md_show_usage): Display -m[no-]fix-loongson3-llsc.
+       * doc/c-mips.texi: Document -m[no-]fix-loongson3-llsc,
+       --enable-mips-fix-loongson3-llsc=[yes|no].
+
 2019-02-10  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR gas/24165
index 3eecf71a5fba9047f4d8150e60cd1bc88240ba84..3903c383c191428f0e39cf4a036d8d6243e2552f 100644 (file)
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -1,5 +1,10 @@
 -*- text -*-
 
+* For MIPS, Add -m[no-]fix-loongson3-llsc option to fix (or not) Loongson3 LLSC
+  Errata.  Add a --enable-mips-fix-loongson3-llsc=[yes|no] configure time option
+  to set the default behavior. Set the default if the configure option is not used
+  to "no".
+
 Changes in 2.32:
 
 * Add -mvexwig=[0|1] option to x86 assembler to control encoding of
index 88b215873bd85ec742b5568bd18ab65711776acf..8724eb153ae6a56ce5645025484cba15ebec3bc6 100644 (file)
@@ -50,6 +50,9 @@
 /* Define to 1 if you want to generate x86 relax relocations by default. */
 #undef DEFAULT_GENERATE_X86_RELAX_RELOCATIONS
 
+/* Define to 1 if you want to fix Loongson3 LLSC Errata by default. */
+#undef DEFAULT_MIPS_FIX_LOONGSON3_LLSC
+
 /* Define to 1 if you want to generate RISC-V arch attribute by default. */
 #undef DEFAULT_RISCV_ATTR
 
index ae5590422941347825dc38af2791759436e7a422..81b729a295d13d7b240910eb0e2277b5ff3df6c0 100644 (file)
@@ -141,6 +141,12 @@ struct mips_cl_insn
      extension.  */
   unsigned long insn_opcode;
 
+  /* The name if this is an label.  */
+  char label[16];
+
+  /* The target label name if this is an branch.  */
+  char target[16];
+
   /* The frag that contains the instruction.  */
   struct frag *frag;
 
@@ -511,7 +517,7 @@ static int mips_32bitmode = 0;
 /* True if CPU has a ror instruction.  */
 #define CPU_HAS_ROR(CPU)       CPU_HAS_DROR (CPU)
 
-/* True if CPU is in the Octeon family */
+/* True if CPU is in the Octeon family */
 #define CPU_IS_OCTEON(CPU) ((CPU) == CPU_OCTEON || (CPU) == CPU_OCTEONP \
                            || (CPU) == CPU_OCTEON2 || (CPU) == CPU_OCTEON3)
 
@@ -660,7 +666,7 @@ static int g_switch_seen = 0;
    fixed it for the non-PIC mode.  KR 95/04/07  */
 static int nopic_need_relax (symbolS *, int);
 
-/* handle of the OPCODE hash table */
+/* Handle of the OPCODE hash table.  */
 static struct hash_control *op_hash = NULL;
 
 /* The opcode hash table we use for the mips16.  */
@@ -670,12 +676,12 @@ static struct hash_control *mips16_op_hash = NULL;
 static struct hash_control *micromips_op_hash = NULL;
 
 /* This array holds the chars that always start a comment.  If the
-    pre-processor is disabled, these aren't very useful */
+    pre-processor is disabled, these aren't very useful */
 const char comment_chars[] = "#";
 
 /* This array holds the chars that only start a comment at the beginning of
    a line.  If the line seems to have the form '# 123 filename'
-   .line and .file directives will appear in the pre-processed output */
+   .line and .file directives will appear in the pre-processed output */
 /* Note that input_file.c hand checks for '#' at the beginning of the
    first line of the input file.  This is because the compiler outputs
    #NO_APP at the beginning of its output.  */
@@ -685,22 +691,22 @@ const char line_comment_chars[] = "#";
 /* This array holds machine specific line separator characters.  */
 const char line_separator_chars[] = ";";
 
-/* Chars that can be used to separate mant from exp in floating point nums */
+/* Chars that can be used to separate mant from exp in floating point nums */
 const char EXP_CHARS[] = "eE";
 
-/* Chars that mean this number is a floating point constant */
-/* As in 0f12.456 */
-/* or    0d1.2345e12 */
+/* Chars that mean this number is a floating point constant.
+   As in 0f12.456
+   or    0d1.2345e12.  */
 const char FLT_CHARS[] = "rRsSfFdDxXpP";
 
 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
    changed in read.c .  Ideally it shouldn't have to know about it at all,
-   but nothing is ideal around here.
- */
+   but nothing is ideal around here.  */
 
 /* Types of printf format used for instruction-related error messages.
-   "I" means int ("%d") and "S" means string ("%s"). */
-enum mips_insn_error_format {
+   "I" means int ("%d") and "S" means string ("%s").  */
+enum mips_insn_error_format
+{
   ERR_FMT_PLAIN,
   ERR_FMT_I,
   ERR_FMT_SS,
@@ -708,7 +714,8 @@ enum mips_insn_error_format {
 
 /* Information about an error that was found while assembling the current
    instruction.  */
-struct mips_insn_error {
+struct mips_insn_error
+{
   /* We sometimes need to match an instruction against more than one
      opcode table entry.  Errors found during this matching are reported
      against a particular syntactic argument rather than against the
@@ -727,7 +734,8 @@ struct mips_insn_error {
   /* The printf()-style message, including its format and arguments.  */
   enum mips_insn_error_format format;
   const char *msg;
-  union {
+  union
+  {
     int i;
     const char *ss[2];
   } u;
@@ -786,16 +794,20 @@ static int mips_debug = 0;
 /* The maximum number of NOPs needed for any purpose.  */
 #define MAX_NOPS 4
 
+/* The maximum range of context length of ll/sc.  */
+#define MAX_LLSC_RANGE 20
+
 /* A list of previous instructions, with index 0 being the most recent.
    We need to look back MAX_NOPS instructions when filling delay slots
    or working around processor errata.  We need to look back one
    instruction further if we're thinking about using history[0] to
    fill a branch delay slot.  */
-static struct mips_cl_insn history[1 + MAX_NOPS];
+static struct mips_cl_insn history[1 + MAX_NOPS + MAX_LLSC_RANGE];
 
 /* Arrays of operands for each instruction.  */
 #define MAX_OPERANDS 6
-struct mips_operand_array {
+struct mips_operand_array
+{
   const struct mips_operand *operand[MAX_OPERANDS];
 };
 static struct mips_operand_array *mips_operands;
@@ -808,6 +820,9 @@ static struct mips_cl_insn mips16_nop_insn;
 static struct mips_cl_insn micromips_nop16_insn;
 static struct mips_cl_insn micromips_nop32_insn;
 
+/* Sync instructions used by insert sync.  */
+static struct mips_cl_insn sync_insn;
+
 /* The appropriate nop for the current mode.  */
 #define NOP_INSN (mips_opts.mips16                                     \
                  ? &mips16_nop_insn                                    \
@@ -943,6 +958,9 @@ static bfd_boolean mips_fix_cn63xxp1;
 static bfd_boolean mips_fix_r5900;
 static bfd_boolean mips_fix_r5900_explicit;
 
+/* ...likewise -mfix-loongson3-llsc.  */
+static bfd_boolean mips_fix_loongson3_llsc = DEFAULT_MIPS_FIX_LOONGSON3_LLSC;
+
 /* We don't relax branches by default, since this causes us to expand
    `la .l2 - .l1' if there's a branch between .l1 and .l2, because we
    fail to compute the offset before expanding the macro to the most
@@ -1482,6 +1500,8 @@ enum options
     OPTION_NO_FIX_24K,
     OPTION_FIX_RM7000,
     OPTION_NO_FIX_RM7000,
+    OPTION_FIX_LOONGSON3_LLSC,
+    OPTION_NO_FIX_LOONGSON3_LLSC,
     OPTION_FIX_LOONGSON2F_JUMP,
     OPTION_NO_FIX_LOONGSON2F_JUMP,
     OPTION_FIX_LOONGSON2F_NOP,
@@ -1628,6 +1648,8 @@ struct option md_longopts[] =
   {"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX},
   {"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
   {"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX},
+  {"mfix-loongson3-llsc",   no_argument, NULL, OPTION_FIX_LOONGSON3_LLSC},
+  {"mno-fix-loongson3-llsc", no_argument, NULL, OPTION_NO_FIX_LOONGSON3_LLSC},
   {"mfix-loongson2f-jump", no_argument, NULL, OPTION_FIX_LOONGSON2F_JUMP},
   {"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP},
   {"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP},
@@ -2774,7 +2796,7 @@ struct regname {
     {"$ta2",   RTYPE_GP | 14}, /* alias for $t6 */ \
     {"$ta3",   RTYPE_GP | 15}  /* alias for $t7 */
 
-/* Remaining symbolic register names */
+/* Remaining symbolic register names */
 #define SYMBOLIC_REGISTER_NAMES \
     {"$zero",  RTYPE_GP | 0},  \
     {"$at",    RTYPE_GP | 1},  \
@@ -2809,8 +2831,8 @@ struct regname {
     {"$pc",    RTYPE_PC | 0}
 
 #define MDMX_VECTOR_REGISTER_NAMES \
-    /* {"$v0", RTYPE_VEC | 0},  clash with REG 2 above */ \
-    /* {"$v1", RTYPE_VEC | 1},  clash with REG 3 above */ \
+    /* {"$v0", RTYPE_VEC | 0},  Clash with REG 2 above.  */ \
+    /* {"$v1", RTYPE_VEC | 1},  Clash with REG 3 above.  */ \
     {"$v2",    RTYPE_VEC | 2},  \
     {"$v3",    RTYPE_VEC | 3},  \
     {"$v4",    RTYPE_VEC | 4},  \
@@ -3671,6 +3693,7 @@ md_begin (void)
          if (!validate_mips_insn (&mips_opcodes[i], 0xffffffff,
                                   decode_mips_operand, &mips_operands[i]))
            broken = 1;
+
          if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0)
            {
              create_insn (&nop_insn, mips_opcodes + i);
@@ -3678,6 +3701,10 @@ md_begin (void)
                nop_insn.insn_opcode = LOONGSON2F_NOP_INSN;
              nop_insn.fixed_p = 1;
            }
+
+          if (sync_insn.insn_mo == NULL && strcmp (name, "sync") == 0)
+           create_insn (&sync_insn, mips_opcodes + i);
+
          ++i;
        }
       while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name));
@@ -3833,7 +3860,7 @@ md_begin (void)
 
     /* The ABI says this section should be loaded so that the
        running program can access it.  However, we don't load it
-       if we are configured for an embedded target */
+       if we are configured for an embedded target */
     flags = SEC_READONLY | SEC_DATA;
     if (strncmp (TARGET_OS, "elf", 3) != 0)
       flags |= SEC_ALLOC | SEC_LOAD;
@@ -6859,6 +6886,103 @@ fix_loongson2f (struct mips_cl_insn * ip)
     fix_loongson2f_jump (ip);
 }
 
+/* Fix loongson3 llsc errata: Insert sync before ll/lld. */
+
+static void
+fix_loongson3_llsc (struct mips_cl_insn * ip)
+{
+  gas_assert (!HAVE_CODE_COMPRESSION);
+
+  /* If is an local label and the insn is not sync,
+     look forward that whether an branch between ll/sc jump to here
+     if so, insert a sync.  */
+  if (seg_info (now_seg)->label_list
+      && S_IS_LOCAL (seg_info (now_seg)->label_list->label)
+      && (strcmp (ip->insn_mo->name, "sync") != 0))
+    {
+      const char *label_name = S_GET_NAME (seg_info (now_seg)->label_list->label);
+      unsigned long lookback = ARRAY_SIZE (history);
+      unsigned long i;
+
+      for (i = 0; i < lookback; i++)
+       {
+         if (streq (history[i].insn_mo->name, "ll")
+             || streq (history[i].insn_mo->name, "lld"))
+           break;
+
+         if (streq (history[i].insn_mo->name, "sc")
+             || streq (history[i].insn_mo->name, "scd"))
+           {
+             unsigned long j;
+
+             for (j = i + 1; j < lookback; j++)
+               {
+                 if (streq (history[i].insn_mo->name, "ll")
+                     || streq (history[i].insn_mo->name, "lld"))
+                   break;
+
+                 if (delayed_branch_p (&history[j]))
+                   {
+                     if (streq (history[j].target, label_name))
+                       {
+                         add_fixed_insn (&sync_insn);
+                         insert_into_history (0, 1, &sync_insn);
+                         i = lookback;
+                         break;
+                       }
+                   }
+               }
+           }
+       }
+    }
+  /* If we find a sc, we look forward to look for an branch insn,
+     and see whether it jump back and out of ll/sc.  */
+  else if (streq(ip->insn_mo->name, "sc") || streq(ip->insn_mo->name, "scd"))
+    {
+      unsigned long lookback = ARRAY_SIZE (history) - 1;
+      unsigned long i;
+
+      for (i = 0; i < lookback; i++)
+       {
+         if (streq (history[i].insn_mo->name, "ll")
+             || streq (history[i].insn_mo->name, "lld"))
+           break;
+
+         if (delayed_branch_p (&history[i]))
+           {
+             unsigned long j;
+
+             for (j = i + 1; j < lookback; j++)
+               {
+                 if (streq (history[j].insn_mo->name, "ll")
+                     || streq (history[i].insn_mo->name, "lld"))
+                   break;
+               }
+
+             for (; j < lookback; j++)
+               {
+                 if (history[j].label[0] != '\0'
+                     && streq (history[j].label, history[i].target)
+                     && strcmp (history[j+1].insn_mo->name, "sync") != 0)
+                   {
+                     add_fixed_insn (&sync_insn);
+                     insert_into_history (++j, 1, &sync_insn);
+                   }
+               }
+           }
+       }
+    }
+
+  /* Skip if there is a sync before ll/lld.  */
+  if ((strcmp (ip->insn_mo->name, "ll") == 0
+       || strcmp (ip->insn_mo->name, "lld") == 0)
+      && (strcmp (history[0].insn_mo->name, "sync") != 0))
+    {
+      add_fixed_insn (&sync_insn);
+      insert_into_history (0, 1, &sync_insn);
+    }
+}
+
 /* IP is a branch that has a delay slot, and we need to fill it
    automatically.   Return true if we can do that by swapping IP
    with the previous instruction.
@@ -7316,6 +7440,15 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION)
     fix_loongson2f (ip);
 
+  ip->target[0] = '\0';
+  if (offset_expr.X_op == O_symbol)
+    strncpy (ip->target, S_GET_NAME (offset_expr.X_add_symbol), 15);
+  ip->label[0] = '\0';
+  if (seg_info (now_seg)->label_list)
+    strncpy (ip->label, S_GET_NAME (seg_info (now_seg)->label_list->label), 15);
+  if (mips_fix_loongson3_llsc && !HAVE_CODE_COMPRESSION)
+    fix_loongson3_llsc (ip);
+
   file_ase_mips16 |= mips_opts.mips16;
   file_ase_micromips |= mips_opts.micromips;
 
@@ -10361,7 +10494,7 @@ macro (struct mips_cl_insn *ip, char *str)
          break;
        }
       ++imm_expr.X_add_number;
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case M_BGE_I:
     case M_BGEL_I:
       if (mask == M_BGEL_I)
@@ -10381,7 +10514,7 @@ macro (struct mips_cl_insn *ip, char *str)
       if (imm_expr.X_add_number <= GPR_SMIN)
        {
        do_true:
-         /* result is always true */
+         /* Result is always true.  */
          as_warn (_("branch %s is always true"), ip->insn_mo->name);
          macro_build (&offset_expr, "b", "p");
          break;
@@ -10419,7 +10552,7 @@ macro (struct mips_cl_insn *ip, char *str)
              && imm_expr.X_add_number == -1))
        goto do_false;
       ++imm_expr.X_add_number;
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case M_BGEU_I:
     case M_BGEUL_I:
       if (mask == M_BGEUL_I)
@@ -10497,7 +10630,7 @@ macro (struct mips_cl_insn *ip, char *str)
       if (imm_expr.X_add_number >= GPR_SMAX)
        goto do_true;
       ++imm_expr.X_add_number;
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case M_BLT_I:
     case M_BLTL_I:
       if (mask == M_BLTL_I)
@@ -10542,7 +10675,7 @@ macro (struct mips_cl_insn *ip, char *str)
              && imm_expr.X_add_number == -1))
        goto do_true;
       ++imm_expr.X_add_number;
-      /* FALLTHROUGH */
+      /* Fall through.  */
     case M_BLTU_I:
     case M_BLTUL_I:
       if (mask == M_BLTUL_I)
@@ -12633,20 +12766,18 @@ macro (struct mips_cl_insn *ip, char *str)
          offset_reloc[2] = BFD_RELOC_UNUSED;
        }
       align = 8;
-      /* Fall through */
+      /* Fall through */
 
     case M_L_DAB:
-      /*
-       * The MIPS assembler seems to check for X_add_number not
-       * being double aligned and generating:
-       *       lui     at,%hi(foo+1)
-       *       addu    at,at,v1
-       *       addiu   at,at,%lo(foo+1)
-       *       lwc1    f2,0(at)
-       *       lwc1    f3,4(at)
-       * But, the resulting address is the same after relocation so why
-       * generate the extra instruction?
-       */
+      /* The MIPS assembler seems to check for X_add_number not
+         being double aligned and generating:
+               lui     at,%hi(foo+1)
+               addu    at,at,v1
+               addiu   at,at,%lo(foo+1)
+               lwc1    f2,0(at)
+               lwc1    f3,4(at)
+         But, the resulting address is the same after relocation so why
+         generate the extra instruction?  */
       /* Itbl support may require additional care here.  */
       coproc = 1;
       fmt = "T,o(b)";
@@ -13369,7 +13500,7 @@ macro (struct mips_cl_insn *ip, char *str)
       macro_build (&expr1, "xori", "t,r,i", op[0], op[0], BFD_RELOC_LO16);
       break;
 
-    case M_SGE_I:      /* X >= I  <==>  not (X < I) */
+    case M_SGE_I:      /* X >= I  <==>  not (X < I) */
     case M_SGEU_I:
       if (imm_expr.X_add_number >= -0x8000
          && imm_expr.X_add_number < 0x8000)
@@ -13385,7 +13516,7 @@ macro (struct mips_cl_insn *ip, char *str)
       macro_build (&expr1, "xori", "t,r,i", op[0], op[0], BFD_RELOC_LO16);
       break;
 
-    case M_SGT:                /* X > Y  <==>  Y < X */
+    case M_SGT:                /* X > Y  <==>  Y < X */
       s = "slt";
       goto sgt;
     case M_SGTU:
@@ -13394,7 +13525,7 @@ macro (struct mips_cl_insn *ip, char *str)
       macro_build (NULL, s, "d,v,t", op[0], op[2], op[1]);
       break;
 
-    case M_SGT_I:      /* X > I  <==>  I < X */
+    case M_SGT_I:      /* X > I  <==>  I < X */
       s = "slt";
       goto sgti;
     case M_SGTU_I:
@@ -13405,7 +13536,7 @@ macro (struct mips_cl_insn *ip, char *str)
       macro_build (NULL, s, "d,v,t", op[0], AT, op[1]);
       break;
 
-    case M_SLE:                /* X <= Y  <==>  Y >= X  <==>  not (Y < X) */
+    case M_SLE:                /* X <= Y  <==>  Y >= X  <==>  not (Y < X) */
       s = "slt";
       goto sle;
     case M_SLEU:
@@ -14731,6 +14862,14 @@ md_parse_option (int c, const char *arg)
       mips_fix_rm7000 = 0;
       break;
 
+    case OPTION_FIX_LOONGSON3_LLSC:
+      mips_fix_loongson3_llsc = TRUE;
+      break;
+
+    case OPTION_NO_FIX_LOONGSON3_LLSC:
+      mips_fix_loongson3_llsc = FALSE;
+      break;
+
     case OPTION_FIX_LOONGSON2F_JUMP:
       mips_fix_loongson2f_jump = TRUE;
       break;
@@ -14999,7 +15138,7 @@ mips_after_parse_args (void)
   const struct mips_cpu_info *arch_info = 0;
   const struct mips_cpu_info *tune_info = 0;
 
-  /* GP relative stuff not working for PE */
+  /* GP relative stuff not working for PE */
   if (strncmp (TARGET_OS, "pe", 2) == 0)
     {
       if (g_switch_seen && g_switch_value != 0)
@@ -15078,7 +15217,7 @@ mips_after_parse_args (void)
 void
 mips_init_after_args (void)
 {
-  /* initialize opcodes */
+  /* Initialize opcodes.  */
   bfd_mips_num_opcodes = bfd_mips_num_builtin_opcodes;
   mips_opcodes = (struct mips_opcode *) mips_builtin_opcodes;
 }
@@ -15087,6 +15226,7 @@ long
 md_pcrel_from (fixS *fixP)
 {
   valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
+
   switch (fixP->fx_r_type)
     {
     case BFD_RELOC_MICROMIPS_7_PCREL_S1:
@@ -19703,7 +19843,7 @@ s_mips_mask (int reg_type)
    gcc's mips_cpu_info_table[].  */
 static const struct mips_cpu_info mips_cpu_info_table[] =
 {
-  /* Entries for generic ISAs */
+  /* Entries for generic ISAs */
   { "mips1",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS1,    CPU_R3000 },
   { "mips2",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS2,    CPU_R6000 },
   { "mips3",          MIPS_CPU_IS_ISA, 0,      ISA_MIPS3,    CPU_R4000 },
@@ -19742,7 +19882,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "orion",          0, 0,                    ISA_MIPS3,    CPU_R4600 },
   { "r4650",          0, 0,                    ISA_MIPS3,    CPU_R4650 },
   { "r5900",          0, 0,                    ISA_MIPS3,    CPU_R5900 },
-  /* ST Microelectronics Loongson 2E and 2F cores */
+  /* ST Microelectronics Loongson 2E and 2F cores */
   { "loongson2e",     0, 0,                    ISA_MIPS3,    CPU_LOONGSON_2E },
   { "loongson2f",     0, ASE_LOONGSON_MMI,     ISA_MIPS3,    CPU_LOONGSON_2F },
 
@@ -19821,12 +19961,12 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "1004kf2_1",      0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   { "1004kf",         0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   { "1004kf1_1",      0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
-  /* interaptiv is the new name for 1004kf */
+  /* interaptiv is the new name for 1004kf */
   { "interaptiv",     0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   { "interaptiv-mr2", 0,
     ASE_DSP | ASE_EVA | ASE_MT | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
     ISA_MIPS32R3, CPU_INTERAPTIV_MR2 },
-  /* M5100 family */
+  /* M5100 family */
   { "m5100",          0, ASE_MCU,              ISA_MIPS32R5, CPU_MIPS32R5 },
   { "m5101",          0, ASE_MCU,              ISA_MIPS32R5, CPU_MIPS32R5 },
   /* P5600 with EVA and Virtualization ASEs, other ASEs are optional.  */
@@ -19838,14 +19978,14 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "20kc",           0, ASE_MIPS3D,           ISA_MIPS64,   CPU_MIPS64 },
   { "25kf",           0, ASE_MIPS3D,           ISA_MIPS64,   CPU_MIPS64 },
 
-  /* Broadcom SB-1 CPU core */
+  /* Broadcom SB-1 CPU core */
   { "sb1",            0, ASE_MIPS3D | ASE_MDMX,        ISA_MIPS64,   CPU_SB1 },
-  /* Broadcom SB-1A CPU core */
+  /* Broadcom SB-1A CPU core */
   { "sb1a",           0, ASE_MIPS3D | ASE_MDMX,        ISA_MIPS64,   CPU_SB1 },
 
-  /* MIPS 64 Release 2 */
-  /* Loongson CPU core */
-  /* -march=loongson3a is an alias of -march=gs464 for compatibility */
+  /* MIPS 64 Release 2 */
+  /* Loongson CPU core */
+  /* -march=loongson3a is an alias of -march=gs464 for compatibility */
   { "loongson3a",     0, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
      ISA_MIPS64R2,     CPU_GS464 },
   { "gs464",          0, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
@@ -19855,7 +19995,7 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "gs264e",         0, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
      | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64,        ISA_MIPS64R2,   CPU_GS264E },
 
-  /* Cavium Networks Octeon CPU core */
+  /* Cavium Networks Octeon CPU core */
   { "octeon",        0, 0,                     ISA_MIPS64R2, CPU_OCTEON },
   { "octeon+",       0, 0,                     ISA_MIPS64R2, CPU_OCTEONP },
   { "octeon2",       0, 0,                     ISA_MIPS64R2, CPU_OCTEON2 },
@@ -19869,11 +20009,11 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
      MIPS64R2 rather than MIPS64.  */
   { "xlp",           0, 0,                     ISA_MIPS64R2, CPU_XLR },
 
-  /* MIPS 64 Release 6 */
+  /* MIPS 64 Release 6 */
   { "i6400",         0, ASE_MSA,               ISA_MIPS64R6, CPU_MIPS64R6},
   { "p6600",         0, ASE_VIRT | ASE_MSA,    ISA_MIPS64R6, CPU_MIPS64R6},
 
-  /* End marker */
+  /* End marker */
   { NULL, 0, 0, 0, 0 }
 };
 
@@ -20140,9 +20280,20 @@ MIPS options:\n\
   fprintf (stream, _("\
 -minsn32               only generate 32-bit microMIPS instructions\n\
 -mno-insn32            generate all microMIPS instructions\n"));
+#if DEFAULT_MIPS_FIX_LOONGSON3_LLSC
+  fprintf (stream, _("\
+-mfix-loongson3-llsc   work around Loongson3 LL/SC errata, default\n\
+-mno-fix-loongson3-llsc        disable work around Loongson3 LL/SC errata\n"));
+#else
+  fprintf (stream, _("\
+-mfix-loongson3-llsc   work around Loongson3 LL/SC errata\n\
+-mno-fix-loongson3-llsc        disable work around Loongson3 LL/SC errata, default\n"));
+#endif
   fprintf (stream, _("\
 -mfix-loongson2f-jump  work around Loongson2F JUMP instructions\n\
 -mfix-loongson2f-nop   work around Loongson2F NOP errata\n\
+-mfix-loongson3-llsc   work around Loongson3 LL/SC errata\n\
+-mno-fix-loongson3-llsc        disable work around Loongson3 LL/SC errata\n\
 -mfix-vr4120           work around certain VR4120 errata\n\
 -mfix-vr4130           work around VR4130 mflo/mfhi errata\n\
 -mfix-24k              insert a nop after ERET and DERET instructions\n\
index 6f3307b46226a7d5d0dca8f068b6998a8100e0e6..1aafa6b31d7c8227c55d53db3974ad9b7e153343 100755 (executable)
@@ -808,6 +808,7 @@ enable_compressed_debug_sections
 enable_x86_relax_relocations
 enable_elf_stt_common
 enable_generate_build_notes
+enable_mips_fix_loongson3_llsc
 enable_x86_used_note
 enable_default_riscv_attribute
 enable_werror
@@ -1471,6 +1472,8 @@ Optional Features:
   --enable-generate-build-notes
                           generate GNU Build notes if none are provided by the
                           input
+  --enable-mips-fix-loongson3-llsc
+                          enable MIPS fix Loongson3 LLSC errata
   --enable-x86-used-note  generate GNU x86 used ISA and feature properties
   --enable-default-riscv-attribute
                           generate RISC-V arch attribute by default
@@ -11340,7 +11343,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11343 "configure"
+#line 11346 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -11446,7 +11449,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 11449 "configure"
+#line 11452 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12114,6 +12117,17 @@ if test "${enable_generate_build_notes+set}" = set; then :
 esac
 fi
 
+# Decide if the MIPS assembler should default to enable MIPS fix Loongson3
+# LLSC errata.
+ac_default_mips_fix_loongson3_llsc=unset
+# Provide a configuration option to override the default.
+# Check whether --enable-mips-fix-loongson3-llsc was given.
+if test "${enable_mips_fix_loongson3_llsc+set}" = set; then :
+  enableval=$enable_mips_fix_loongson3_llsc; case "${enableval}" in
+  yes)  ac_default_mips_fix_loongson3_llsc=1 ;;
+  no)   ac_default_mips_fix_loongson3_llsc=0 ;;
+esac
+fi
 
 # Decide if the x86 ELF assembler should default to generating GNU x86
 # used ISA and feature properties.
@@ -13131,6 +13145,15 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+if test ${ac_default_mips_fix_loongson3_llsc} = unset; then
+  ac_default_mips_fix_loongson3_llsc=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define DEFAULT_MIPS_FIX_LOONGSON3_LLSC $ac_default_mips_fix_loongson3_llsc
+_ACEOF
+
+
 if test x$ac_default_compressed_debug_sections = xyes ; then
 
 $as_echo "#define DEFAULT_FLAG_COMPRESS_DEBUG 1" >>confdefs.h
index cc4bae0957253c1a57f11da0c969855c68b5d86b..4b25b7ca36026b87724c97afb0d86e3d2f9807bd 100644 (file)
@@ -111,6 +111,17 @@ AC_ARG_ENABLE(generate_build_notes,
   no)   ac_default_generate_build_notes=0 ;;
 esac])dnl
 
+# Decide if the MIPS assembler should default to enable MIPS fix Loongson3
+# LLSC errata.
+ac_default_mips_fix_loongson3_llsc=unset
+# Provide a configuration option to override the default.
+AC_ARG_ENABLE(mips-fix-loongson3-llsc,
+             AS_HELP_STRING([--enable-mips-fix-loongson3-llsc],
+             [enable MIPS fix Loongson3 LLSC errata]),
+[case "${enableval}" in
+  yes)  ac_default_mips_fix_loongson3_llsc=1 ;;
+  no)   ac_default_mips_fix_loongson3_llsc=0 ;;
+esac])dnl
 
 # Decide if the x86 ELF assembler should default to generating GNU x86
 # used ISA and feature properties.
@@ -687,6 +698,13 @@ AC_DEFINE_UNQUOTED(DEFAULT_RISCV_ATTR,
   $ac_default_generate_riscv_attr,
   [Define to 1 if you want to generate RISC-V arch attribute by default.])
 
+if test ${ac_default_mips_fix_loongson3_llsc} = unset; then
+  ac_default_mips_fix_loongson3_llsc=0
+fi
+AC_DEFINE_UNQUOTED(DEFAULT_MIPS_FIX_LOONGSON3_LLSC,
+  $ac_default_mips_fix_loongson3_llsc,
+  [Define to 1 if you want to fix Loongson3 LLSC Errata by default.])
+
 if test x$ac_default_compressed_debug_sections = xyes ; then
   AC_DEFINE(DEFAULT_FLAG_COMPRESS_DEBUG, 1, [Define if you want compressed debug sections by default.])
 fi
index 812280301142592fda290d2b6a09c80493d2296a..1ef289a0f4974919a4a98a4953885004f6f5369d 100644 (file)
@@ -308,6 +308,13 @@ Replace nops by @code{or at,at,zero} to work around the Loongson2F
 deadlock.  The issue has been solved in later Loongson2F batches, but
 this fix has no side effect to them.
 
+@item -mfix-loongson3-llsc
+@itemx -mno-fix-loongson3-llsc
+Insert @samp{sync} before @samp{ll} and @samp{lld} to work around
+Loongson3 LLSC errata.  Without it, under extrame cases, the CPU might
+deadlock. The default can be controlled by the
+@option{--enable-mips-fix-loongson3-llsc=[yes|no]} configure option.
+
 @item -mfix-vr4120
 @itemx -mno-fix-vr4120
 Insert nops to work around certain VR4120 errata.  This option is