gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index b7b4b6989a12d3091a02de7155fbea3adbf1c9d7..31acb77d78ad68a80a86638fd2a77b34b1d23084 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-mips.c -- assemble code for a MIPS chip.
-   Copyright (C) 1993-2019 Free Software Foundation, Inc.
+   Copyright (C) 1993-2020 Free Software Foundation, Inc.
    Contributed by the OSF and Ralph Campbell.
    Written by Keith Knowles and Ralph Campbell, working independently.
    Modified for ECOFF and R4000 support by Ian Lance Taylor of Cygnus
@@ -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
@@ -3859,9 +3862,9 @@ md_begin (void)
   if (strncmp (TARGET_OS, "elf", 3) != 0
       && strncmp (TARGET_OS, "vxworks", 7) != 0)
     {
-      (void) bfd_set_section_alignment (stdoutput, text_section, 4);
-      (void) bfd_set_section_alignment (stdoutput, data_section, 4);
-      (void) bfd_set_section_alignment (stdoutput, bss_section, 4);
+      bfd_set_section_alignment (text_section, 4);
+      bfd_set_section_alignment (data_section, 4);
+      bfd_set_section_alignment (bss_section, 4);
     }
 
   /* Create a .reginfo section for register masks and a .mdebug
@@ -3886,8 +3889,8 @@ md_begin (void)
       {
        sec = subseg_new (".reginfo", (subsegT) 0);
 
-       bfd_set_section_flags (stdoutput, sec, flags);
-       bfd_set_section_alignment (stdoutput, sec, HAVE_NEWABI ? 3 : 2);
+       bfd_set_section_flags (sec, flags);
+       bfd_set_section_alignment (sec, HAVE_NEWABI ? 3 : 2);
 
        mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));
       }
@@ -3896,8 +3899,8 @@ md_begin (void)
        /* The 64-bit ABI uses a .MIPS.options section rather than
           .reginfo section.  */
        sec = subseg_new (".MIPS.options", (subsegT) 0);
-       bfd_set_section_flags (stdoutput, sec, flags);
-       bfd_set_section_alignment (stdoutput, sec, 3);
+       bfd_set_section_flags (sec, flags);
+       bfd_set_section_alignment (sec, 3);
 
        /* Set up the option header.  */
        {
@@ -3918,25 +3921,23 @@ md_begin (void)
       }
 
     sec = subseg_new (".MIPS.abiflags", (subsegT) 0);
-    bfd_set_section_flags (stdoutput, sec,
+    bfd_set_section_flags (sec,
                           SEC_READONLY | SEC_DATA | SEC_ALLOC | SEC_LOAD);
-    bfd_set_section_alignment (stdoutput, sec, 3);
+    bfd_set_section_alignment (sec, 3);
     mips_flags_frag = frag_more (sizeof (Elf_External_ABIFlags_v0));
 
     if (ECOFF_DEBUGGING)
       {
        sec = subseg_new (".mdebug", (subsegT) 0);
-       (void) bfd_set_section_flags (stdoutput, sec,
-                                     SEC_HAS_CONTENTS | SEC_READONLY);
-       (void) bfd_set_section_alignment (stdoutput, sec, 2);
+       bfd_set_section_flags (sec, SEC_HAS_CONTENTS | SEC_READONLY);
+       bfd_set_section_alignment (sec, 2);
       }
     else if (mips_flag_pdr)
       {
        pdr_seg = subseg_new (".pdr", (subsegT) 0);
-       (void) bfd_set_section_flags (stdoutput, pdr_seg,
-                                     SEC_READONLY | SEC_RELOC
-                                     | SEC_DEBUGGING);
-       (void) bfd_set_section_alignment (stdoutput, pdr_seg, 2);
+       bfd_set_section_flags (pdr_seg,
+                              SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
+       bfd_set_section_alignment (pdr_seg, 2);
       }
 
     subseg_set (seg, subseg);
@@ -4441,9 +4442,10 @@ mips_move_labels (struct insn_label_list *labels, bfd_boolean text_p)
       gas_assert (S_GET_SEGMENT (l->label) == now_seg);
       symbol_set_frag (l->label, frag_now);
       val = (valueT) frag_now_fix ();
-      /* MIPS16/microMIPS text labels are stored as odd.  */
+      /* MIPS16/microMIPS text labels are stored as odd.
+        We just carry the ISA mode bit forward.  */
       if (text_p && HAVE_CODE_COMPRESSION)
-       ++val;
+       val |= (S_GET_VALUE (l->label) & 0x1);
       S_SET_VALUE (l->label, val);
     }
 }
@@ -4467,7 +4469,7 @@ s_is_linkonce (symbolS *sym, segT from_seg)
 
   if (symseg != from_seg && !S_IS_LOCAL (sym))
     {
-      if ((bfd_get_section_flags (stdoutput, symseg) & SEC_LINK_ONCE))
+      if ((bfd_section_flags (symseg) & SEC_LINK_ONCE))
        linkonce = TRUE;
       /* The GNU toolchain uses an extension for ELF: a section
         beginning with the magic string .gnu.linkonce is a
@@ -4776,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;
 }
@@ -4795,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);
@@ -6179,7 +6181,7 @@ match_float_constant (struct mips_arg_info *arg, expressionS *imm,
     }
 
   new_seg = subseg_new (newname, (subsegT) 0);
-  bfd_set_section_flags (stdoutput, new_seg,
+  bfd_set_section_flags (new_seg,
                         SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA);
   frag_align (length == 4 ? 2 : 3, 0, 0);
   if (strncmp (TARGET_OS, "elf", 3) != 0)
@@ -6902,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)
@@ -6916,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")
@@ -6939,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);
@@ -6953,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;
@@ -15742,6 +15780,24 @@ fix_bad_misaligned_branch_p (fixS *fixP)
   return (val & 0x3) != isa_bit;
 }
 
+/* Calculate the relocation target by masking off ISA mode bit before
+   combining symbol and addend.  */
+
+static valueT
+fix_bad_misaligned_address (fixS *fixP)
+{
+  valueT val;
+  valueT off;
+  unsigned isa_mode;
+  gas_assert (fixP != NULL && fixP->fx_addsy != NULL);
+  val = S_GET_VALUE (fixP->fx_addsy);
+  off = fixP->fx_offset;
+  isa_mode = (ELF_ST_IS_COMPRESSED (S_GET_OTHER (fixP->fx_addsy))
+             ? 1 : 0);
+
+  return ((val & ~isa_mode) + off);
+}
+
 /* Make the necessary checks on a regular MIPS branch pointed to by FIXP
    and its calculated value VAL.  */
 
@@ -15758,7 +15814,7 @@ fix_validate_branch (fixS *fixP, valueT val)
   else if (fix_bad_misaligned_branch_p (fixP))
     as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("branch to misaligned address (0x%lx)"),
-                 (long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
+                 (long) fix_bad_misaligned_address (fixP));
   else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x3) != 0)
     as_bad_where (fixP->fx_file, fixP->fx_line,
                  _("cannot encode misaligned addend "
@@ -15897,8 +15953,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
        else if (fix_bad_misaligned_jump_p (fixP, shift))
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("jump to misaligned address (0x%lx)"),
-                       (long) (S_GET_VALUE (fixP->fx_addsy)
-                               + fixP->fx_offset));
+                       (long) fix_bad_misaligned_address (fixP));
        else if (HAVE_IN_PLACE_ADDENDS
                 && (fixP->fx_offset & ((1 << shift) - 1)) != 0)
          as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -16110,7 +16165,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
               && fixP->fx_done
               && fixP->fx_frag->fr_address >= text_section->vma
               && (fixP->fx_frag->fr_address
-                  < text_section->vma + bfd_get_section_size (text_section))
+                  < text_section->vma + bfd_section_size (text_section))
               && ((insn & 0xffff0000) == 0x10000000     /* beq $0,$0 */
                   || (insn & 0xffff0000) == 0x04010000  /* bgez $0 */
                   || (insn & 0xffff0000) == 0x04110000)) /* bgezal $0 */
@@ -16152,7 +16207,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
               && (fixP->fx_offset & 0x1) != 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("branch to misaligned address (0x%lx)"),
-                     (long) (S_GET_VALUE (fixP->fx_addsy) + fixP->fx_offset));
+                     (long) fix_bad_misaligned_address (fixP));
       else if (HAVE_IN_PLACE_ADDENDS && (fixP->fx_offset & 0x1) != 0)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("cannot encode misaligned addend "
@@ -16218,7 +16273,7 @@ mips_align (int to, int *fill, struct insn_label_list *labels)
   else
     frag_align (to, fill ? *fill : 0, 0);
   record_alignment (now_seg, to);
-  mips_move_labels (labels, FALSE);
+  mips_move_labels (labels, subseg_text_p (now_seg));
 }
 
 /* Align to a given power of two.  .align 0 turns off the automatic
@@ -16301,9 +16356,8 @@ s_change_sec (int sec)
     case 'r':
       seg = subseg_new (RDATA_SECTION_NAME,
                        (subsegT) get_absolute_expression ());
-      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD
-                                             | SEC_READONLY | SEC_RELOC
-                                             | SEC_DATA));
+      bfd_set_section_flags (seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY
+                                  | SEC_RELOC | SEC_DATA));
       if (strncmp (TARGET_OS, "elf", 3) != 0)
        record_alignment (seg, 4);
       demand_empty_rest_of_line ();
@@ -16311,8 +16365,8 @@ s_change_sec (int sec)
 
     case 's':
       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
-      bfd_set_section_flags (stdoutput, 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 ();
@@ -16320,7 +16374,7 @@ s_change_sec (int sec)
 
     case 'B':
       seg = subseg_new (".sbss", (subsegT) get_absolute_expression ());
-      bfd_set_section_flags (stdoutput, 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 ();
@@ -16403,7 +16457,7 @@ s_change_section (int ignore ATTRIBUTE_UNUSED)
   if (section_type == SHT_MIPS_DWARF)
     section_type = SHT_PROGBITS;
 
-  obj_elf_change_section (section_name, section_type, 0, section_flag,
+  obj_elf_change_section (section_name, section_type, section_flag,
                          section_entry_size, 0, 0, 0);
 
   if (now_seg->name != section_name)
@@ -17585,7 +17639,7 @@ tc_get_register (int frame)
 valueT
 md_section_align (asection *seg, valueT addr)
 {
-  int align = bfd_get_section_alignment (stdoutput, seg);
+  int align = bfd_section_alignment (seg);
 
   /* We don't need to align ELF sections to the full alignment.
      However, Irix 5 may prefer that we align them at least to a 16
@@ -18999,7 +19053,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
              else if ((fragp->fr_offset & 0x1) != 0)
                as_bad_where (fragp->fr_file, fragp->fr_line,
                              _("branch to misaligned address (0x%lx)"),
-                             (long) val);
+                             (long) (resolve_symbol_value (fragp->fr_symbol)
+                                     + (fragp->fr_offset & ~1)));
            }
 
          val = mips16_pcrel_val (fragp, pcrel_op, val, 0);
@@ -19741,7 +19796,7 @@ s_mips_end (int x ATTRIBUTE_UNUSED)
   else
     p = NULL;
 
-  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
+  if ((bfd_section_flags (now_seg) & SEC_CODE) == 0)
     as_warn (_(".end not in text section"));
 
   if (!cur_proc_ptr)
@@ -19831,7 +19886,7 @@ s_mips_ent (int aent)
       || *input_line_pointer == '-')
     get_number ();
 
-  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) == 0)
+  if ((bfd_section_flags (now_seg) & SEC_CODE) == 0)
     as_warn (_(".ent or .aent not in text section"));
 
   if (!aent && cur_proc_ptr)
This page took 0.033592 seconds and 4 git commands to generate.