Fix overflow detection in the Z80 assembler.
[binutils-gdb.git] / gas / config / tc-ia64.c
index ed4636bbbd3d58e3a3c31a918f5ba4971aafd5b8..34482eb4f973963adb6b4d9587642c112df42bf3 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-ia64.c -- Assembler for the HP/Intel IA-64 architecture.
-   Copyright (C) 1998-2020 Free Software Foundation, Inc.
+   Copyright (C) 1998-2021 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
    This file is part of GAS, the GNU Assembler.
 #include "elf/ia64.h"
 #include "bfdver.h"
 #include <time.h>
-
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#endif
 
 #define NELEMS(a)      ((int) (sizeof (a)/sizeof ((a)[0])))
 
@@ -164,7 +161,7 @@ struct label_fix
 {
   struct label_fix *next;
   struct symbol *sym;
-  bfd_boolean dw2_mark_labels;
+  bool dw2_mark_labels;
 };
 
 #ifdef TE_VMS
@@ -947,7 +944,7 @@ ia64_flush_insns (void)
   segT saved_seg;
   subsegT saved_subseg;
   unw_rec_list *ptr;
-  bfd_boolean mark;
+  bool mark;
 
   if (!md.last_text_seg)
     return;
@@ -962,7 +959,7 @@ ia64_flush_insns (void)
 
   /* In case there are labels following the last instruction, resolve
      those now.  */
-  mark = FALSE;
+  mark = false;
   for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next)
     {
       symbol_set_value_now (lfix->sym);
@@ -3560,7 +3557,7 @@ start_unwind_section (const segT text_seg, int sec_index)
 
   sec_text_name = segment_name (text_seg);
   text_name = sec_text_name;
-  if (strncmp (text_name, "_info", 5) == 0)
+  if (startswith (text_name, "_info"))
     {
       as_bad (_("Illegal section name `%s' (causes unwind section name clash)"),
              text_name);
@@ -3573,8 +3570,7 @@ start_unwind_section (const segT text_seg, int sec_index)
   /* Build the unwind section name by appending the (possibly stripped)
      text section name to the unwind prefix.  */
   suffix = text_name;
-  if (strncmp (text_name, ".gnu.linkonce.t.",
-              sizeof (".gnu.linkonce.t.") - 1) == 0)
+  if (startswith (text_name, ".gnu.linkonce.t."))
     {
       prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
       suffix += sizeof (".gnu.linkonce.t.") - 1;
@@ -4684,7 +4680,12 @@ dot_rot (int type)
       drpp = &dr->next;
       base_reg += num_regs;
 
-      str_hash_insert (md.dynreg_hash, name, dr);
+      if (str_hash_insert (md.dynreg_hash, name, dr, 0) != NULL)
+       {
+         as_bad (_("Attempt to redefine register set `%s'"), name);
+         obstack_free (&notes, name);
+         goto err;
+       }
 
       if (*input_line_pointer != ',')
        break;
@@ -5171,7 +5172,8 @@ dot_entry (int dummy ATTRIBUTE_UNUSED)
       c = get_symbol_name (&name);
       symbolP = symbol_find_or_make (name);
 
-      str_hash_insert (md.entry_hash, S_GET_NAME (symbolP), (void *) symbolP);
+      if (str_hash_insert (md.entry_hash, S_GET_NAME (symbolP), symbolP, 0))
+       as_bad (_("duplicate entry hint %s"), name);
 
       *input_line_pointer = c;
       SKIP_WHITESPACE_AFTER_NAME ();
@@ -5374,7 +5376,8 @@ declare_register (const char *name, unsigned int regnum)
 
   sym = symbol_create (name, reg_section, &zero_address_frag, regnum);
 
-  str_hash_insert (md.reg_hash, S_GET_NAME (sym), (void *) sym);
+  if (str_hash_insert (md.reg_hash, S_GET_NAME (sym), sym, 0) != NULL)
+    as_fatal (_("duplicate %s"), name);
 
   return sym;
 }
@@ -6091,8 +6094,10 @@ parse_operands (struct ia64_opcode *idesc)
     {
       if (i < NELEMS (CURR_SLOT.opnd))
        {
-         sep = parse_operand_maybe_eval (CURR_SLOT.opnd + i, '=',
-                                         idesc->operands[i]);
+         enum ia64_opnd op = IA64_OPND_NIL;
+         if (i < NELEMS (idesc->operands))
+           op = idesc->operands[i];
+         sep = parse_operand_maybe_eval (CURR_SLOT.opnd + i, '=', op);
          if (CURR_SLOT.opnd[i].X_op == O_absent)
            break;
        }
@@ -6511,7 +6516,7 @@ emit_one_bundle (void)
   int n, i, j, first, curr, last_slot;
   bfd_vma t0 = 0, t1 = 0;
   struct label_fix *lfix;
-  bfd_boolean mark_label;
+  bool mark_label;
   struct insn_fix *ifix;
   char mnemonic[16];
   fixS *fix;
@@ -6838,7 +6843,7 @@ emit_one_bundle (void)
        continue;               /* Try next slot.  */
 
       /* Now is a good time to fix up the labels for this insn.  */
-      mark_label = FALSE;
+      mark_label = false;
       for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
        {
          S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
@@ -6882,8 +6887,17 @@ emit_one_bundle (void)
 
       for (j = 0; j < md.slot[curr].num_fixups; ++j)
        {
+         unsigned long where;
+
          ifix = md.slot[curr].fixup + j;
-         fix = fix_new_exp (frag_now, frag_now_fix () - 16 + i, 8,
+         where = frag_now_fix () - 16 + i;
+#ifdef TE_HPUX
+         /* Fix offset for PCREL60B relocation on HP-UX.  */
+         if (ifix->code == BFD_RELOC_IA64_PCREL60B)
+           ++where;
+#endif
+
+         fix = fix_new_exp (frag_now, where, 8,
                             &ifix->expr, ifix->is_pcrel, ifix->code);
          fix->tc_fix_data.opnd = ifix->opnd;
          fix->fx_file = md.slot[curr].src_file;
@@ -6995,7 +7009,7 @@ md_parse_option (int c, const char *arg)
          md.flags |= EF_IA_64_BE;
          default_big_endian = 1;
        }
-      else if (strncmp (arg, "unwind-check=", 13) == 0)
+      else if (startswith (arg, "unwind-check="))
        {
          arg += 13;
          if (strcmp (arg, "warning") == 0)
@@ -7005,7 +7019,7 @@ md_parse_option (int c, const char *arg)
          else
            return 0;
        }
-      else if (strncmp (arg, "hint.b=", 7) == 0)
+      else if (startswith (arg, "hint.b="))
        {
          arg += 7;
          if (strcmp (arg, "ok") == 0)
@@ -7017,7 +7031,7 @@ md_parse_option (int c, const char *arg)
          else
            return 0;
        }
-      else if (strncmp (arg, "tune=", 5) == 0)
+      else if (startswith (arg, "tune="))
        {
          arg += 5;
          if (strcmp (arg, "itanium1") == 0)
@@ -7065,7 +7079,7 @@ md_parse_option (int c, const char *arg)
                        exit:   branch out from the current context (default)
                        labels: all labels in context may be branch targets
        */
-      if (strncmp (arg, "indirect=", 9) != 0)
+      if (!startswith (arg, "indirect="))
         return 0;
       break;
 
@@ -7393,8 +7407,9 @@ md_begin (void)
 
   md.pseudo_hash = str_htab_create ();
   for (i = 0; i < NELEMS (pseudo_opcode); ++i)
-    str_hash_insert (md.pseudo_hash, pseudo_opcode[i].name,
-                    (void *) (pseudo_opcode + i));
+    if (str_hash_insert (md.pseudo_hash, pseudo_opcode[i].name,
+                        pseudo_opcode + i, 0) != NULL)
+      as_fatal (_("duplicate %s"), pseudo_opcode[i].name);
 
   md.reg_hash = str_htab_create ();
   md.dynreg_hash = str_htab_create ();
@@ -7452,8 +7467,8 @@ md_begin (void)
   declare_register ("psp", REG_PSP);
 
   for (i = 0; i < NELEMS (const_bits); ++i)
-    str_hash_insert (md.const_hash, const_bits[i].name,
-                    (void *) (const_bits + i));
+    if (str_hash_insert (md.const_hash, const_bits[i].name, const_bits + i, 0))
+      as_fatal (_("duplicate %s"), const_bits[i].name);
 
   /* Set the architecture and machine depending on defaults and command line
      options.  */
@@ -7745,7 +7760,7 @@ ia64_frob_label (struct symbol *sym)
       fix = XOBNEW (&notes, struct label_fix);
       fix->sym = sym;
       fix->next = CURR_SLOT.tag_fixups;
-      fix->dw2_mark_labels = FALSE;
+      fix->dw2_mark_labels = false;
       CURR_SLOT.tag_fixups = fix;
 
       return;
@@ -8096,7 +8111,7 @@ static int
 is_taken_branch (struct ia64_opcode *idesc)
 {
   return ((is_conditional_branch (idesc) && CURR_SLOT.qp_regno == 0)
-         || strncmp (idesc->name, "br.ia", 5) == 0);
+         || startswith (idesc->name, "br.ia"));
 }
 
 /* Return whether the given opcode is an interruption or rfi.  If there's any
@@ -9488,7 +9503,7 @@ dep->name, idesc->name, (rsrc_write?"write":"read"), note)
       /* FIXME we can identify some individual RSE written resources, but RSE
         read resources have not yet been completely identified, so for now
         treat RSE as a single resource */
-      if (strncmp (idesc->name, "mov", 3) == 0)
+      if (startswith (idesc->name, "mov"))
        {
          if (rsrc_write)
            {
@@ -9854,8 +9869,8 @@ note_register_values (struct ia64_opcode *idesc)
     }
   /* After a call, all register values are undefined, except those marked
      as "safe".  */
-  else if (strncmp (idesc->name, "br.call", 6) == 0
-          || strncmp (idesc->name, "brl.call", 7) == 0)
+  else if (startswith (idesc->name, "br.call")
+          || startswith (idesc->name, "brl.call"))
     {
       /* FIXME keep GR values which are marked as "safe_across_calls"  */
       clear_register_values ();
@@ -11812,8 +11827,8 @@ dot_alias (int section)
   h->file = as_where (&h->line);
   h->name = name;
 
-  str_hash_insert (ahash, alias, (void *) h);
-  str_hash_insert (nhash, name, (void *) alias);
+  str_hash_insert (ahash, alias, h, 0);
+  str_hash_insert (nhash, name, alias, 0);
 
 out:
   demand_empty_rest_of_line ();
@@ -11833,7 +11848,7 @@ do_alias (void **slot, void *arg ATTRIBUTE_UNUSED)
       /* Uses .alias extensively to alias CRTL functions to same with
         decc$ prefix. Sometimes function gets optimized away and a
         warning results, which should be suppressed.  */
-      if (strncmp (tuple->key, "decc$", 5) != 0)
+      if (!startswith (tuple->key, "decc$"))
 #endif
        as_warn_where (h->file, h->line,
                       _("symbol `%s' aliased to `%s' is not used"),