gdb: Convert language la_word_break_characters field to a method
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 6244d8ac091c562ddb5fdcf8611095d2790a343b..31acb77d78ad68a80a86638fd2a77b34b1d23084 100644 (file)
@@ -812,6 +812,9 @@ static int mips_debug = 0;
    fill a branch delay slot.  */
 static struct mips_cl_insn history[1 + MAX_NOPS + MAX_LLSC_RANGE];
 
+/* The maximum number of LABELS detect for the same address.  */
+#define MAX_LABELS_SAME 10
+
 /* Arrays of operands for each instruction.  */
 #define MAX_OPERANDS 6
 struct mips_operand_array
@@ -4775,7 +4778,7 @@ gpr_read_mask (const struct mips_cl_insn *ip)
   if (pinfo2 & INSN2_READ_SP)
     mask |= 1 << SP;
   if (pinfo2 & INSN2_READ_GPR_31)
-    mask |= 1 << 31;
+    mask |= 1u << 31;
   /* Don't include register 0.  */
   return mask & ~1;
 }
@@ -4794,7 +4797,7 @@ gpr_write_mask (const struct mips_cl_insn *ip)
   if (pinfo & INSN_WRITE_GPR_24)
     mask |= 1 << 24;
   if (pinfo & INSN_WRITE_GPR_31)
-    mask |= 1 << 31;
+    mask |= 1u << 31;
   if (pinfo & INSN_UDI)
     /* UDI instructions have traditionally been assumed to write to RD.  */
     mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RD, *ip);
@@ -6901,7 +6904,21 @@ fix_loongson2f (struct mips_cl_insn * ip)
     fix_loongson2f_jump (ip);
 }
 
-/* Fix loongson3 llsc errata: Insert sync before ll/lld. */
+static bfd_boolean
+has_label_name (const char *arr[], size_t len ,const char *s)
+{
+  unsigned long i;
+  for (i = 0; i < len; i++)
+    {
+      if (!arr[i])
+       return FALSE;
+      if (streq (arr[i], s))
+       return TRUE;
+    }
+  return FALSE;
+}
+
+/* Fix loongson3 llsc errata: Insert sync before ll/lld.  */
 
 static void
 fix_loongson3_llsc (struct mips_cl_insn * ip)
@@ -6915,10 +6932,30 @@ fix_loongson3_llsc (struct mips_cl_insn * ip)
       && 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;
+      valueT label_value;
+      const char *label_names[MAX_LABELS_SAME];
+      const char *label_name;
+
+      label_name = S_GET_NAME (seg_info (now_seg)->label_list->label);
+      label_names[0] = label_name;
+      struct insn_label_list *llist = seg_info (now_seg)->label_list;
+      label_value = S_GET_VALUE (llist->label);
 
+      for (i = 1; i < MAX_LABELS_SAME; i++)
+       {
+         llist = llist->next;
+         if (!llist)
+           break;
+         if (S_GET_VALUE (llist->label) == label_value)
+           label_names[i] = S_GET_NAME (llist->label);
+         else
+           break;
+       }
+      for (; i < MAX_LABELS_SAME; i++)
+       label_names[i] = NULL;
+
+      unsigned long lookback = ARRAY_SIZE (history);
       for (i = 0; i < lookback; i++)
        {
          if (streq (history[i].insn_mo->name, "ll")
@@ -6938,7 +6975,9 @@ fix_loongson3_llsc (struct mips_cl_insn * ip)
 
                  if (delayed_branch_p (&history[j]))
                    {
-                     if (streq (history[j].target, label_name))
+                     if (has_label_name (label_names,
+                                         MAX_LABELS_SAME,
+                                         history[j].target))
                        {
                          add_fixed_insn (&sync_insn);
                          insert_into_history (0, 1, &sync_insn);
@@ -6952,7 +6991,7 @@ fix_loongson3_llsc (struct mips_cl_insn * ip)
     }
   /* 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"))
+  else if (streq (ip->insn_mo->name, "sc") || streq (ip->insn_mo->name, "scd"))
     {
       unsigned long lookback = ARRAY_SIZE (history) - 1;
       unsigned long i;
@@ -16326,8 +16365,8 @@ s_change_sec (int sec)
 
     case 's':
       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
-      bfd_set_section_flags (seg,
-                            SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
+      bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_RELOC
+                                  | SEC_DATA | SEC_SMALL_DATA));
       if (strncmp (TARGET_OS, "elf", 3) != 0)
        record_alignment (seg, 4);
       demand_empty_rest_of_line ();
@@ -16335,7 +16374,7 @@ s_change_sec (int sec)
 
     case 'B':
       seg = subseg_new (".sbss", (subsegT) get_absolute_expression ());
-      bfd_set_section_flags (seg, SEC_ALLOC);
+      bfd_set_section_flags (seg, SEC_ALLOC | SEC_SMALL_DATA);
       if (strncmp (TARGET_OS, "elf", 3) != 0)
        record_alignment (seg, 4);
       demand_empty_rest_of_line ();
This page took 0.027503 seconds and 4 git commands to generate.