Rearrange symbol_create parameters
[deliverable/binutils-gdb.git] / gas / config / tc-mips.c
index 70c6548283e63941beb5b030b2bc46a2e953c3c4..ebcc633dd81aaf0cc573570c8d252718e0b0f6d5 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
@@ -675,13 +675,13 @@ static int g_switch_seen = 0;
 static int nopic_need_relax (symbolS *, int);
 
 /* Handle of the OPCODE hash table.  */
-static struct hash_control *op_hash = NULL;
+static htab_t op_hash = NULL;
 
 /* The opcode hash table we use for the mips16.  */
-static struct hash_control *mips16_op_hash = NULL;
+static htab_t mips16_op_hash = NULL;
 
 /* The opcode hash table we use for the microMIPS ASE.  */
-static struct hash_control *micromips_op_hash = NULL;
+static htab_t 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.  */
@@ -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
@@ -886,11 +889,6 @@ struct mips_hi_fixup
 
 static struct mips_hi_fixup *mips_hi_fixup_list;
 
-/* The frag containing the last explicit relocation operator.
-   Null if explicit relocations have not been used.  */
-
-static fragS *prev_reloc_op_frag;
-
 /* Map mips16 register numbers to normal MIPS register numbers.  */
 
 static const unsigned int mips16_to_32_reg_map[] =
@@ -2227,7 +2225,7 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
 
   /* Clear combination ASE flags, which need to be recalculated based on
      updated regular ASE settings.  */
-  opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT);
+  opts->ase &= ~(ASE_MIPS16E2_MT | ASE_XPA_VIRT | ASE_EVA_R6);
 
   if (enabled_p)
     opts->ase |= ase->flags;
@@ -2246,6 +2244,15 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
       mask |= ASE_MIPS16E2_MT;
     }
 
+  /* The EVA Extension has instructions which are only valid when the R6 ISA
+     is enabled.  This sets the ASE_EVA_R6 flag when both EVA and R6 ISA are
+     present.  */
+  if (((opts->ase & ASE_EVA) != 0) && ISA_IS_R6 (opts->isa))
+    {
+      opts->ase |= ASE_EVA_R6;
+      mask |= ASE_EVA_R6;
+    }
+
   return mask;
 }
 
@@ -3661,7 +3668,6 @@ validate_micromips_insn (const struct mips_opcode *opc,
 void
 md_begin (void)
 {
-  const char *retval = NULL;
   int i = 0;
   int broken = 0;
 
@@ -3681,21 +3687,14 @@ md_begin (void)
   if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_opts.arch))
     as_warn (_("could not set architecture and machine"));
 
-  op_hash = hash_new ();
+  op_hash = str_htab_create ();
 
   mips_operands = XCNEWVEC (struct mips_operand_array, NUMOPCODES);
   for (i = 0; i < NUMOPCODES;)
     {
       const char *name = mips_opcodes[i].name;
 
-      retval = hash_insert (op_hash, name, (void *) &mips_opcodes[i]);
-      if (retval != NULL)
-       {
-         fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
-                  mips_opcodes[i].name, retval);
-         /* Probably a memory allocation problem?  Give up now.  */
-         as_fatal (_("broken assembler, no assembly attempted"));
-       }
+      str_hash_insert (op_hash, name, (void *) &mips_opcodes[i]);
       do
        {
          if (!validate_mips_insn (&mips_opcodes[i], 0xffffffff,
@@ -3718,7 +3717,7 @@ md_begin (void)
       while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name));
     }
 
-  mips16_op_hash = hash_new ();
+  mips16_op_hash = str_htab_create ();
   mips16_operands = XCNEWVEC (struct mips_operand_array,
                              bfd_mips16_num_opcodes);
 
@@ -3727,10 +3726,7 @@ md_begin (void)
     {
       const char *name = mips16_opcodes[i].name;
 
-      retval = hash_insert (mips16_op_hash, name, (void *) &mips16_opcodes[i]);
-      if (retval != NULL)
-       as_fatal (_("internal: can't hash `%s': %s"),
-                 mips16_opcodes[i].name, retval);
+      str_hash_insert (mips16_op_hash, name, (void *) &mips16_opcodes[i]);
       do
        {
          if (!validate_mips16_insn (&mips16_opcodes[i], &mips16_operands[i]))
@@ -3746,7 +3742,7 @@ md_begin (void)
             && strcmp (mips16_opcodes[i].name, name) == 0);
     }
 
-  micromips_op_hash = hash_new ();
+  micromips_op_hash = str_htab_create ();
   micromips_operands = XCNEWVEC (struct mips_operand_array,
                                 bfd_micromips_num_opcodes);
 
@@ -3755,11 +3751,8 @@ md_begin (void)
     {
       const char *name = micromips_opcodes[i].name;
 
-      retval = hash_insert (micromips_op_hash, name,
+      str_hash_insert (micromips_op_hash, name,
                            (void *) &micromips_opcodes[i]);
-      if (retval != NULL)
-       as_fatal (_("internal: can't hash `%s': %s"),
-                 micromips_opcodes[i].name, retval);
       do
        {
          struct mips_cl_insn *micromips_nop_insn;
@@ -3796,18 +3789,18 @@ md_begin (void)
      helps us detect invalid uses of them.  */
   for (i = 0; reg_names[i].name; i++)
     symbol_table_insert (symbol_new (reg_names[i].name, reg_section,
-                                    reg_names[i].num, /* & RNUM_MASK, */
-                                    &zero_address_frag));
+                                    &zero_address_frag,
+                                    reg_names[i].num));
   if (HAVE_NEWABI)
     for (i = 0; reg_names_n32n64[i].name; i++)
       symbol_table_insert (symbol_new (reg_names_n32n64[i].name, reg_section,
-                                      reg_names_n32n64[i].num, /* & RNUM_MASK, */
-                                      &zero_address_frag));
+                                      &zero_address_frag,
+                                      reg_names_n32n64[i].num));
   else
     for (i = 0; reg_names_o32[i].name; i++)
       symbol_table_insert (symbol_new (reg_names_o32[i].name, reg_section,
-                                      reg_names_o32[i].num, /* & RNUM_MASK, */
-                                      &zero_address_frag));
+                                      &zero_address_frag,
+                                      reg_names_o32[i].num));
 
   for (i = 0; i < 32; i++)
     {
@@ -3816,17 +3809,17 @@ md_begin (void)
       /* R5900 VU0 floating-point register.  */
       sprintf (regname, "$vf%d", i);
       symbol_table_insert (symbol_new (regname, reg_section,
-                                      RTYPE_VF | i, &zero_address_frag));
+                                      &zero_address_frag, RTYPE_VF | i));
 
       /* R5900 VU0 integer register.  */
       sprintf (regname, "$vi%d", i);
       symbol_table_insert (symbol_new (regname, reg_section,
-                                      RTYPE_VI | i, &zero_address_frag));
+                                      &zero_address_frag, RTYPE_VI | i));
 
       /* MSA register.  */
       sprintf (regname, "$w%d", i);
       symbol_table_insert (symbol_new (regname, reg_section,
-                                      RTYPE_MSA | i, &zero_address_frag));
+                                      &zero_address_frag, RTYPE_MSA | i));
     }
 
   obstack_init (&mips_operand_tokens);
@@ -3850,9 +3843,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
@@ -3877,8 +3870,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));
       }
@@ -3887,8 +3880,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.  */
        {
@@ -3909,25 +3902,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);
@@ -4432,9 +4423,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);
     }
 }
@@ -4458,7 +4450,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
@@ -4767,7 +4759,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;
 }
@@ -4786,7 +4778,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);
@@ -6014,7 +6006,10 @@ match_non_zero_reg_operand (struct mips_arg_info *arg,
     return FALSE;
 
   if (regno == 0)
-    return FALSE;
+    {
+      set_insn_error (arg->argnum, _("the source register must not be $0"));
+      return FALSE;
+    }
 
   arg->last_regno = regno;
   insn_insert_operand (arg->insn, operand, regno);
@@ -6167,7 +6162,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)
@@ -6890,7 +6885,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)
@@ -6904,10 +6913,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")
@@ -6927,7 +6956,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);
@@ -6941,7 +6972,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;
@@ -8977,7 +9008,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
   bfd_reloc_code_real_type r[3];
   const struct mips_opcode *amo;
   const struct mips_operand *operand;
-  struct hash_control *hash;
+  htab_t hash;
   struct mips_cl_insn insn;
   va_list args;
   unsigned int uval;
@@ -8995,7 +9026,7 @@ macro_build (expressionS *ep, const char *name, const char *fmt, ...)
   r[1] = BFD_RELOC_UNUSED;
   r[2] = BFD_RELOC_UNUSED;
   hash = mips_opts.micromips ? micromips_op_hash : op_hash;
-  amo = (struct mips_opcode *) hash_find (hash, name);
+  amo = (struct mips_opcode *) str_hash_find (hash, name);
   gas_assert (amo);
   gas_assert (strcmp (name, amo->name) == 0);
 
@@ -9153,7 +9184,7 @@ mips16_macro_build (expressionS *ep, const char *name, const char *fmt,
   bfd_reloc_code_real_type r[3]
     = {BFD_RELOC_UNUSED, BFD_RELOC_UNUSED, BFD_RELOC_UNUSED};
 
-  mo = (struct mips_opcode *) hash_find (mips16_op_hash, name);
+  mo = (struct mips_opcode *) str_hash_find (mips16_op_hash, name);
   gas_assert (mo);
   gas_assert (strcmp (name, mo->name) == 0);
 
@@ -10276,6 +10307,7 @@ macro (struct mips_cl_insn *ip, char *str)
   int imm = 0;
   int ust = 0;
   int lp = 0;
+  int ll_sc_paired = 0;
   bfd_boolean large_offset;
   int off;
   int hold_mips_optimize;
@@ -10337,7 +10369,10 @@ macro (struct mips_cl_insn *ip, char *str)
     case M_ADD_I:
       s = "addi";
       s2 = "add";
-      goto do_addi;
+      if (ISA_IS_R6 (mips_opts.isa))
+       goto do_addi_i;
+      else
+       goto do_addi;
     case M_ADDU_I:
       s = "addiu";
       s2 = "addu";
@@ -10346,10 +10381,11 @@ macro (struct mips_cl_insn *ip, char *str)
       dbl = 1;
       s = "daddi";
       s2 = "dadd";
-      if (!mips_opts.micromips)
+      if (!mips_opts.micromips && !ISA_IS_R6 (mips_opts.isa))
        goto do_addi;
       if (imm_expr.X_add_number >= -0x200
-         && imm_expr.X_add_number < 0x200)
+         && imm_expr.X_add_number < 0x200
+         && !ISA_IS_R6 (mips_opts.isa))
        {
          macro_build (NULL, s, "t,r,.", op[0], op[1],
                       (int) imm_expr.X_add_number);
@@ -12011,6 +12047,14 @@ macro (struct mips_cl_insn *ip, char *str)
       offbits = 12;
       lp = 1;
       goto ld;
+    case M_LLDP_AB:
+    case M_LLWP_AB:
+    case M_LLWPE_AB:
+      s = ip->insn_mo->name;
+      fmt = "t,d,s";
+      ll_sc_paired = 1;
+      offbits = 0;
+      goto ld;
     case M_LWM_AB:
       gas_assert (mips_opts.micromips);
       s = "lwm";
@@ -12025,11 +12069,26 @@ macro (struct mips_cl_insn *ip, char *str)
       goto ld_st;
 
     ld:
-      /* We don't want to use $0 as tempreg.  */
-      if (op[2] == op[0] + lp || op[0] + lp == ZERO)
-       goto ld_st;
+      /* Try to use one the the load registers to compute the base address.
+        We don't want to use $0 as tempreg.  */
+      if (ll_sc_paired)
+       {
+         if ((op[0] == ZERO && op[3] == op[1])
+             || (op[1] == ZERO && op[3] == op[0])
+             || (op[0] == ZERO && op[1] == ZERO))
+           goto ld_st;
+         else if (op[0] != op[3] && op[0] != ZERO)
+           tempreg = op[0];
+         else
+           tempreg = op[1];
+       }
       else
-       tempreg = op[0] + lp;
+        {
+         if (op[2] == op[0] + lp || op[0] + lp == ZERO)
+           goto ld_st;
+         else
+           tempreg = op[0] + lp;
+       }
       goto ld_noat;
 
     case M_SB_AB:
@@ -12097,6 +12156,14 @@ macro (struct mips_cl_insn *ip, char *str)
                 : ISA_IS_R6 (mips_opts.isa) ? 9
                 : 16);
       goto ld_st;
+    case M_SCDP_AB:
+    case M_SCWP_AB:
+    case M_SCWPE_AB:
+      s = ip->insn_mo->name;
+      fmt = "t,d,s";
+      ll_sc_paired = 1;
+      offbits = 0;
+      goto ld_st;
     case M_CACHE_AB:
       s = "cache";
       fmt = (mips_opts.micromips ? "k,~(b)"
@@ -12190,7 +12257,7 @@ macro (struct mips_cl_insn *ip, char *str)
     ld_st:
       tempreg = AT;
     ld_noat:
-      breg = op[2];
+      breg = ll_sc_paired ? op[3] : op[2];
       if (small_offset_p (0, align, 16))
        {
          /* The first case exists for M_LD_AB and M_SD_AB, which are
@@ -12202,7 +12269,12 @@ macro (struct mips_cl_insn *ip, char *str)
          else if (small_offset_p (0, align, offbits))
            {
              if (offbits == 0)
-               macro_build (NULL, s, fmt, op[0], breg);
+               {
+                 if (ll_sc_paired)
+                  macro_build (NULL, s, fmt, op[0], op[1], breg);
+                 else
+                  macro_build (NULL, s, fmt, op[0], breg);
+               }
              else
                macro_build (NULL, s, fmt, op[0],
                             (int) offset_expr.X_add_number, breg);
@@ -12215,7 +12287,12 @@ macro (struct mips_cl_insn *ip, char *str)
                           tempreg, breg, -1, offset_reloc[0],
                           offset_reloc[1], offset_reloc[2]);
              if (offbits == 0)
-               macro_build (NULL, s, fmt, op[0], tempreg);
+               {
+                 if (ll_sc_paired)
+                   macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+                 else
+                   macro_build (NULL, s, fmt, op[0], tempreg);
+               }
              else
                macro_build (NULL, s, fmt, op[0], 0, tempreg);
            }
@@ -12258,7 +12335,10 @@ macro (struct mips_cl_insn *ip, char *str)
              if (offset_expr.X_add_number != 0)
                macro_build (&offset_expr, ADDRESS_ADDI_INSN,
                             "t,r,j", tempreg, tempreg, BFD_RELOC_LO16);
-             macro_build (NULL, s, fmt, op[0], tempreg);
+             if (ll_sc_paired)
+               macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+             else
+               macro_build (NULL, s, fmt, op[0], tempreg);
            }
          else if (offbits == 16)
            macro_build (&offset_expr, s, fmt, op[0], BFD_RELOC_LO16, tempreg);
@@ -12276,7 +12356,12 @@ macro (struct mips_cl_insn *ip, char *str)
            macro_build (NULL, ADDRESS_ADD_INSN, "d,v,t",
                         tempreg, tempreg, breg);
          if (offbits == 0)
-           macro_build (NULL, s, fmt, op[0], tempreg);
+           {
+             if (ll_sc_paired)
+               macro_build (NULL, s, fmt, op[0], op[1], tempreg);
+             else
+               macro_build (NULL, s, fmt, op[0], tempreg);
+           }
          else
            macro_build (NULL, s, fmt, op[0], 0, tempreg);
        }
@@ -12714,20 +12799,28 @@ macro (struct mips_cl_insn *ip, char *str)
          OFFSET_EXPR.  */
       if (imm_expr.X_op == O_constant)
        {
-         used_at = 1;
-         load_register (AT, &imm_expr, FPR_SIZE == 64);
+         tempreg = ZERO;
+         if (((FPR_SIZE == 64 && GPR_SIZE == 64)
+              || !ISA_HAS_MXHC1 (mips_opts.isa))
+             && imm_expr.X_add_number != 0)
+           {
+             used_at = 1;
+             tempreg = AT;
+             load_register (AT, &imm_expr, FPR_SIZE == 64);
+           }
          if (FPR_SIZE == 64 && GPR_SIZE == 64)
-           macro_build (NULL, "dmtc1", "t,S", AT, op[0]);
+           macro_build (NULL, "dmtc1", "t,S", tempreg, op[0]);
          else
            {
-             if (ISA_HAS_MXHC1 (mips_opts.isa))
-               macro_build (NULL, "mthc1", "t,G", AT, op[0]);
-             else if (FPR_SIZE != 32)
-               as_bad (_("Unable to generate `%s' compliant code "
-                         "without mthc1"),
-                       (FPR_SIZE == 64) ? "fp64" : "fpxx");
-             else
-               macro_build (NULL, "mtc1", "t,G", AT, op[0] + 1);
+             if (!ISA_HAS_MXHC1 (mips_opts.isa))
+               {
+                 if (FPR_SIZE != 32)
+                   as_bad (_("Unable to generate `%s' compliant code "
+                             "without mthc1"),
+                           (FPR_SIZE == 64) ? "fp64" : "fpxx");
+                 else
+                   macro_build (NULL, "mtc1", "t,G", tempreg, op[0] + 1);
+               }
              if (offset_expr.X_op == O_absent)
                macro_build (NULL, "mtc1", "t,G", 0, op[0]);
              else
@@ -12736,6 +12829,16 @@ macro (struct mips_cl_insn *ip, char *str)
                  load_register (AT, &offset_expr, 0);
                  macro_build (NULL, "mtc1", "t,G", AT, op[0]);
                }
+             if (ISA_HAS_MXHC1 (mips_opts.isa))
+               {
+                 if (imm_expr.X_add_number != 0)
+                   {
+                     used_at = 1;
+                     tempreg = AT;
+                     load_register (AT, &imm_expr, 0);
+                   }
+                 macro_build (NULL, "mthc1", "t,G", tempreg, op[0]);
+               }
            }
          break;
        }
@@ -13654,7 +13757,10 @@ macro (struct mips_cl_insn *ip, char *str)
     case M_SUB_I:
       s = "addi";
       s2 = "sub";
-      goto do_subi;
+      if (ISA_IS_R6 (mips_opts.isa))
+       goto do_subi_i;
+      else
+       goto do_subi;
     case M_SUBU_I:
       s = "addiu";
       s2 = "subu";
@@ -13663,10 +13769,11 @@ macro (struct mips_cl_insn *ip, char *str)
       dbl = 1;
       s = "daddi";
       s2 = "dsub";
-      if (!mips_opts.micromips)
+      if (!mips_opts.micromips && !ISA_IS_R6 (mips_opts.isa))
        goto do_subi;
       if (imm_expr.X_add_number > -0x200
-         && imm_expr.X_add_number <= 0x200)
+         && imm_expr.X_add_number <= 0x200
+         && !ISA_IS_R6 (mips_opts.isa))
        {
          macro_build (NULL, s, "t,r,.", op[0], op[1],
                       (int) -imm_expr.X_add_number);
@@ -14137,7 +14244,7 @@ mips16_macro (struct mips_cl_insn *ip)
    opcode bits in *OPCODE_EXTRA.  */
 
 static struct mips_opcode *
-mips_lookup_insn (struct hash_control *hash, const char *start,
+mips_lookup_insn (htab_t hash, const char *start,
                  ssize_t length, unsigned int *opcode_extra)
 {
   char *name, *dot, *p;
@@ -14149,7 +14256,7 @@ mips_lookup_insn (struct hash_control *hash, const char *start,
   name = xstrndup (start, length);
 
   /* Look up the instruction as-is.  */
-  insn = (struct mips_opcode *) hash_find (hash, name);
+  insn = (struct mips_opcode *) str_hash_find (hash, name);
   if (insn)
     goto end;
 
@@ -14161,7 +14268,7 @@ mips_lookup_insn (struct hash_control *hash, const char *start,
       if (*p == 0 && mask != 0)
        {
          *dot = 0;
-         insn = (struct mips_opcode *) hash_find (hash, name);
+         insn = (struct mips_opcode *) str_hash_find (hash, name);
          *dot = '.';
          if (insn && (insn->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX) != 0)
            {
@@ -14180,14 +14287,14 @@ mips_lookup_insn (struct hash_control *hash, const char *start,
       opend = dot != NULL ? dot - name : length;
       if (opend >= 3 && name[opend - 2] == '1' && name[opend - 1] == '6')
        suffix = 2;
-      else if (name[opend - 2] == '3' && name[opend - 1] == '2')
+      else if (opend >= 2 && name[opend - 2] == '3' && name[opend - 1] == '2')
        suffix = 4;
       else
        suffix = 0;
       if (suffix)
        {
          memmove (name + opend - 2, name + opend, length - opend + 1);
-         insn = (struct mips_opcode *) hash_find (hash, name);
+         insn = (struct mips_opcode *) str_hash_find (hash, name);
          if (insn)
            {
              forced_insn_length = suffix;
@@ -14212,7 +14319,7 @@ static void
 mips_ip (char *str, struct mips_cl_insn *insn)
 {
   const struct mips_opcode *first, *past;
-  struct hash_control *hash;
+  htab_t hash;
   char format;
   size_t end;
   struct mips_operand_token *tokens;
@@ -14308,7 +14415,7 @@ mips16_ip (char *str, struct mips_cl_insn *insn)
   forced_insn_length = l;
 
   *end = 0;
-  first = (struct mips_opcode *) hash_find (mips16_op_hash, str);
+  first = (struct mips_opcode *) str_hash_find (mips16_op_hash, str);
   *end = c;
 
   if (!first)
@@ -14594,12 +14701,8 @@ my_getSmallExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
 
   expr_end = str;
 
-  if (reloc_index != 0)
-    {
-      prev_reloc_op_frag = frag_now;
-      for (i = 0; i < reloc_index; i++)
-       reloc[i] = reversed_reloc[reloc_index - 1 - i];
-    }
+  for (i = 0; i < reloc_index; i++)
+    reloc[i] = reversed_reloc[reloc_index - 1 - i];
 
   return reloc_index;
 }
@@ -15195,6 +15298,12 @@ mips_after_parse_args (void)
   file_mips_opts.isa = arch_info->isa;
   file_mips_opts.init_ase = arch_info->ase;
 
+  /* The EVA Extension has instructions which are only valid when the R6 ISA
+     is enabled.  This sets the ASE_EVA_R6 flag when both EVA and R6 ISA are
+     present.  */
+  if (((file_mips_opts.ase & ASE_EVA) != 0) && ISA_IS_R6 (file_mips_opts.isa))
+    file_mips_opts.ase |= ASE_EVA_R6;
+
   /* Set up initial mips_opts state.  */
   mips_opts = file_mips_opts;
 
@@ -15648,6 +15757,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.  */
 
@@ -15664,7 +15791,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 "
@@ -15803,8 +15930,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,
@@ -16016,7 +16142,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 */
@@ -16058,7 +16184,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 "
@@ -16124,7 +16250,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
@@ -16207,9 +16333,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 ();
@@ -16217,8 +16342,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 ();
@@ -16226,7 +16351,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 ();
@@ -16309,7 +16434,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)
@@ -16367,7 +16492,6 @@ s_mips_globl (int x ATTRIBUTE_UNUSED)
   char *name;
   int c;
   symbolS *symbolP;
-  flagword flag;
 
   do
     {
@@ -16378,10 +16502,6 @@ s_mips_globl (int x ATTRIBUTE_UNUSED)
       *input_line_pointer = c;
       SKIP_WHITESPACE_AFTER_NAME ();
 
-      /* On Irix 5, every global symbol that is not explicitly labelled as
-         being a function is apparently labelled as being an object.  */
-      flag = BSF_OBJECT;
-
       if (!is_end_of_line[(unsigned char) *input_line_pointer]
          && (*input_line_pointer != ','))
        {
@@ -16395,11 +16515,9 @@ s_mips_globl (int x ATTRIBUTE_UNUSED)
          (void) restore_line_pointer (c);
 
          if (sec != NULL && (sec->flags & SEC_CODE) != 0)
-           flag = BSF_FUNCTION;
+           symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
        }
 
-      symbol_get_bfdsym (symbolP)->flags |= flag;
-
       c = *input_line_pointer;
       if (c == ',')
        {
@@ -16414,6 +16532,23 @@ s_mips_globl (int x ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
 }
 
+#ifdef TE_IRIX
+/* The Irix 5 and 6 assemblers set the type of any common symbol and
+   any undefined non-function symbol to STT_OBJECT.  We try to be
+   compatible, since newer Irix 5 and 6 linkers care.  */
+
+void
+mips_frob_symbol (symbolS *symp ATTRIBUTE_UNUSED)
+{
+  /* This late in assembly we can set BSF_OBJECT indiscriminately
+     and let elf.c:swap_out_syms sort out the symbol type.  */
+  flagword *flags = &symbol_get_bfdsym (symp)->flags;
+  if ((*flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+      || !S_IS_DEFINED (symp))
+    *flags |= BSF_OBJECT;
+}
+#endif
+
 static void
 s_option (int x ATTRIBUTE_UNUSED)
 {
@@ -17481,7 +17616,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
@@ -18741,7 +18876,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
            }
 
          /* Make a label at the end for use with the branch.  */
-         l = symbol_new (micromips_label_name (), asec, fragp->fr_fix, fragp);
+         l = symbol_new (micromips_label_name (), asec, fragp, fragp->fr_fix);
          micromips_label_inc ();
          S_SET_OTHER (l, ELF_ST_SET_MICROMIPS (S_GET_OTHER (l)));
 
@@ -18895,7 +19030,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);
@@ -19099,7 +19235,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
         sequence instead.  */
       while (fixp
             && fixp->fx_frag == fragp
-            && (valueT) fixp->fx_where + second < fragp->fr_fix)
+            && fixp->fx_where + second < fragp->fr_fix)
        {
          if (subtype & RELAX_USE_SECOND)
            fixp->fx_done = 1;
@@ -19637,7 +19773,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)
@@ -19727,7 +19863,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.053309 seconds and 4 git commands to generate.