Rearrange symbol_create parameters
[deliverable/binutils-gdb.git] / gas / config / tc-nios2.c
index 4488a4748bf7f2808961cbd3258bdd546f448415..a8bbe5bf1b626357d8e6c3fdc5b587e9e253495e 100644 (file)
@@ -1,5 +1,5 @@
 /* Altera Nios II assembler.
-   Copyright (C) 2012-2015 Free Software Foundation, Inc.
+   Copyright (C) 2012-2020 Free Software Foundation, Inc.
    Contributed by Nigel Gray (ngray@altera.com).
    Contributed by Mentor Graphics, Inc.
 
@@ -25,7 +25,6 @@
 #include "elf/nios2.h"
 #include "tc-nios2.h"
 #include "bfd.h"
-#include "libbfd.h"
 #include "dwarf2dbg.h"
 #include "subsegs.h"
 #include "safe-ctype.h"
@@ -98,7 +97,7 @@ typedef enum
 } relax_optionT;
 
 /* Struct contains all assembler options set with .set.  */
-struct
+static struct
 {
   /* .set noat -> noat = 1 allows assembly code to use at without warning
      and macro expansions generate a warning.
@@ -106,7 +105,7 @@ struct
      do not generate warnings.  */
   bfd_boolean noat;
 
-  /* .set nobreak -> nobreak = 1 allows assembly code to use ba,bt without 
+  /* .set nobreak -> nobreak = 1 allows assembly code to use ba,bt without
                                 warning.
      .set break -> nobreak = 0, assembly code using ba,bt warns.  */
   bfd_boolean nobreak;
@@ -145,7 +144,7 @@ typedef struct nios2_insn_info
 
   /* Constant bits masked into insn_code for self-check mode.  */
   unsigned long constant_bits;
-  
+
   /* Pointer to the relevant bit of the opcode table.  */
   const struct nios2_opcode *insn_nios2_opcode;
   /* After parsing ptrs to the tokens in the instruction fill this array
@@ -185,20 +184,20 @@ typedef struct nios2_ps_insn_info
 } nios2_ps_insn_infoS;
 
 /* Opcode hash table.  */
-static struct hash_control *nios2_opcode_hash = NULL;
+static htab_t nios2_opcode_hash = NULL;
 #define nios2_opcode_lookup(NAME) \
-  ((struct nios2_opcode *) hash_find (nios2_opcode_hash, (NAME)))
+  ((struct nios2_opcode *) str_hash_find (nios2_opcode_hash, (NAME)))
 
 /* Register hash table.  */
-static struct hash_control *nios2_reg_hash = NULL;
+static htab_t nios2_reg_hash = NULL;
 #define nios2_reg_lookup(NAME) \
-  ((struct nios2_reg *) hash_find (nios2_reg_hash, (NAME)))
+  ((struct nios2_reg *) str_hash_find (nios2_reg_hash, (NAME)))
 
 
 /* Pseudo-op hash table.  */
-static struct hash_control *nios2_ps_hash = NULL;
+static htab_t nios2_ps_hash = NULL;
 #define nios2_ps_lookup(NAME) \
-  ((nios2_ps_insn_infoS *) hash_find (nios2_ps_hash, (NAME)))
+  ((nios2_ps_insn_infoS *) str_hash_find (nios2_ps_hash, (NAME)))
 
 /* The known current alignment of the current section.  */
 static int nios2_current_align;
@@ -207,7 +206,7 @@ static segT nios2_current_align_seg;
 static int nios2_auto_align_on = 1;
 
 /* The last seen label in the current section.  This is used to auto-align
-   labels preceeding instructions.  */
+   labels preceding instructions.  */
 static symbolS *nios2_last_label;
 
 /* If we saw a 16-bit CDX instruction, we can align on 2-byte boundaries
@@ -264,7 +263,7 @@ md_number_to_chars (char *buf, valueT val, int n)
    of type TYPE, and store the appropriate bytes in *LITP.  The number
    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
    returned, or NULL on OK.  */
-char *
+const char *
 md_atof (int type, char *litP, int *sizeP)
 {
   int prec;
@@ -566,21 +565,23 @@ s_nios2_sdata (int ignore ATTRIBUTE_UNUSED)
 static void
 s_nios2_set (int equiv)
 {
-  char *directive = input_line_pointer;
-  char delim = get_symbol_end ();
+  char *save = input_line_pointer;
+  char *directive;
+  char delim = get_symbol_name (&directive);
   char *endline = input_line_pointer;
-  *endline = delim;
+
+  (void) restore_line_pointer (delim);
 
   /* We only want to handle ".set XXX" if the
      user has tried ".set XXX, YYY" they are not
      trying a directive.  This prevents
      us from polluting the name space.  */
   SKIP_WHITESPACE ();
-  if (is_end_of_line[(unsigned char) *input_line_pointer]) 
+  if (is_end_of_line[(unsigned char) *input_line_pointer])
     {
       bfd_boolean done = TRUE;
       *endline = 0;
-      
+
       if (!strcmp (directive, "noat"))
          nios2_as_options.noat = TRUE;
       else if (!strcmp (directive, "at"))
@@ -597,7 +598,7 @@ s_nios2_set (int equiv)
          nios2_as_options.relax = relax_all;
       else
        done = FALSE;
-       
+
       if (done)
        {
          *endline = delim;
@@ -607,10 +608,9 @@ s_nios2_set (int equiv)
     }
 
   /* If we fall through to here, either we have ".set XXX, YYY"
-     or we have ".set XXX" where XXX is unknown or we have 
+     or we have ".set XXX" where XXX is unknown or we have
      a syntax error.  */
-  input_line_pointer = directive;
-  *endline = delim;
+  input_line_pointer = save;
   s_set (equiv);
 }
 
@@ -652,7 +652,7 @@ const pseudo_typeS md_pseudo_table[] = {
    Nios II PC-relative branch instructions only support 16-bit offsets.
    And, there's no good way to add a 32-bit constant to the PC without
    using two registers.
-  
+
    To deal with this, for the pc-relative relaxation mode we convert
      br label
    into a series of 16-bit adds, like:
@@ -691,7 +691,7 @@ const pseudo_typeS md_pseudo_table[] = {
 
    16-bit CDX branch instructions are relaxed first into equivalent
    32-bit branches and then the above transformations are applied
-   if necessary.  
+   if necessary.
 
 */
 
@@ -727,8 +727,8 @@ const pseudo_typeS md_pseudo_table[] = {
 #define CDX_CBRANCH_SUBTYPE(N) (CDXBRANCH | CBRANCH | (N))
 #define SUBTYPE_ADDIS(SUBTYPE) ((SUBTYPE) & 0xffff)
 
-/* For the -relax-section mode, unconditional branches require 2 extra i
-   nstructions besides the addis, conditional branches require 3.  */
+/* For the -relax-section mode, unconditional branches require 2 extra
+   instructions besides the addis, conditional branches require 3.  */
 #define UBRANCH_ADDIS_TO_SIZE(N) (((N) + 2) * 4)
 #define CBRANCH_ADDIS_TO_SIZE(N) (((N) + 3) * 4)
 
@@ -1020,7 +1020,7 @@ md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED,
       md_number_to_chars (buffer, op, 4);
       fragp->fr_fix += 4;
       buffer += 4;
-  
+
       /* We need to know whether the offset is positive or negative.  */
       target += S_GET_VALUE (symbolp);
       offset = target - fragp->fr_address - fragp->fr_fix;
@@ -1127,7 +1127,7 @@ nios2_check_overflow (valueT fixup, reloc_howto_type *howto)
       if ((fixup & 0x80000000) > 0)
        {
          /* Check for negative overflow.  */
-         if ((signed) fixup < ((signed) ~0 << (howto->bitsize-1)))
+         if ((signed) fixup < (signed) (~0U << (howto->bitsize - 1)))
            return TRUE;
        }
       else
@@ -1183,7 +1183,7 @@ nios2_diagnose_overflow (valueT fixup, reloc_howto_type *howto,
            = ((fixP->fx_frag->fr_address + fixP->fx_where) & 0xf0000000);
          range_max = range_min + 0x0fffffff;
          address = fixup | range_min;
-         
+
          as_bad_where (fixP->fx_file, fixP->fx_line,
                        _("call target address 0x%08x out of range 0x%08x to 0x%08x"),
                        address, range_min, range_max);
@@ -1304,7 +1304,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
   if (fixP->fx_r_type == BFD_RELOC_64)
     {
       /* We may reach here due to .8byte directives, but we never output
-        BFD_RELOC_64; it must be resolved.  */      
+        BFD_RELOC_64; it must be resolved.  */
       if (fixP->fx_addsy != NULL)
        as_bad_where (fixP->fx_file, fixP->fx_line,
                      _("cannot create 64-bit relocation"));
@@ -1384,7 +1384,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
            nios2_diagnose_overflow (fixup, howto, fixP, value);
 
          /* Apply the right shift.  */
-         fixup = ((signed)fixup) >> howto->rightshift;
+         fixup = (offsetT) fixup >> howto->rightshift;
 
          /* Truncate the fixup to right size.  */
          switch (fixP->fx_r_type)
@@ -1396,13 +1396,11 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
              fixup = fixup & 0xFFFF;
              break;
            case BFD_RELOC_NIOS2_HIADJ16:
-             fixup = ((((fixup >> 16) & 0xFFFF) + ((fixup >> 15) & 0x01))
-                      & 0xFFFF);
+             fixup = ((fixup + 0x8000) >> 16) & 0xFFFF;
              break;
            default:
              {
-               int n = sizeof (fixup) * 8 - howto->bitsize;
-               fixup = (fixup << n) >> n;
+               fixup &= ((valueT) 1 << howto->bitsize) - 1;
                break;
              }
            }
@@ -1481,7 +1479,7 @@ static nios2_insn_relocS *
 nios2_insn_reloc_new (bfd_reloc_code_real_type reloc_type, unsigned int pcrel)
 {
   nios2_insn_relocS *retval;
-  retval = (nios2_insn_relocS *) malloc (sizeof (nios2_insn_relocS));
+  retval = XNEW (nios2_insn_relocS);
   if (retval == NULL)
     {
       as_bad (_("can't create relocation"));
@@ -1749,7 +1747,7 @@ nios2_parse_base_register (char *str, int *direction, int *writeback, int *ret)
 /* The various nios2_assemble_* functions call this
    function to generate an expression from a string representing an expression.
    It then tries to evaluate the expression, and if it can, returns its value.
-   If not, it creates a new nios2_insn_relocS and stores the expression and 
+   If not, it creates a new nios2_insn_relocS and stores the expression and
    reloc_type for future use.  */
 static unsigned long
 nios2_assemble_expression (const char *exprstr,
@@ -1774,7 +1772,7 @@ nios2_assemble_expression (const char *exprstr,
       {
        reloc_type = nios2_special_reloc[i].reloc_type;
        exprstr += strlen (nios2_special_reloc[i].string) + 1;
-       
+
        /* %lo and %hiadj have different meanings for PC-relative
           expressions.  */
        if (pcrel)
@@ -1784,7 +1782,7 @@ nios2_assemble_expression (const char *exprstr,
            if (reloc_type == BFD_RELOC_NIOS2_HIADJ16)
              reloc_type = BFD_RELOC_NIOS2_PCREL_HA;
          }
-       
+
        break;
       }
 
@@ -1851,7 +1849,7 @@ nios2_assemble_reg3 (const char *token)
 
 
 /* Control register index.  */
-static void 
+static void
 nios2_assemble_arg_c (const char *token, nios2_insn_infoS *insn)
 {
   struct nios2_reg *reg = nios2_parse_reg (token, REG_CONTROL);
@@ -1874,7 +1872,7 @@ nios2_assemble_arg_c (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Destination register.  */
-static void 
+static void
 nios2_assemble_arg_d (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -1919,7 +1917,7 @@ nios2_assemble_arg_d (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Source register 1.  */
-static void 
+static void
 nios2_assemble_arg_s (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -1996,7 +1994,7 @@ nios2_assemble_arg_s (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Source register 2.  */
-static void 
+static void
 nios2_assemble_arg_t (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2062,12 +2060,12 @@ nios2_assemble_arg_t (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Destination register w/3-bit encoding.  */
-static void 
+static void
 nios2_assemble_arg_D (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
   int reg = nios2_assemble_reg3 (token);
-  
+
   switch (op->format)
     {
     case iw_T1I7_type:
@@ -2097,12 +2095,12 @@ nios2_assemble_arg_D (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Source register w/3-bit encoding.  */
-static void 
+static void
 nios2_assemble_arg_S (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
   int reg = nios2_assemble_reg3 (token);
-  
+
   switch (op->format)
     {
     case iw_T1I7_type:
@@ -2142,12 +2140,12 @@ nios2_assemble_arg_S (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Source register 2 w/3-bit encoding.  */
-static void 
+static void
 nios2_assemble_arg_T (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
   int reg = nios2_assemble_reg3 (token);
-  
+
   switch (op->format)
     {
     case iw_T2I4_type:
@@ -2165,7 +2163,7 @@ nios2_assemble_arg_T (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 16-bit signed immediate.  */
-static void 
+static void
 nios2_assemble_arg_i (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2189,7 +2187,7 @@ nios2_assemble_arg_i (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 12-bit signed immediate.  */
-static void 
+static void
 nios2_assemble_arg_I (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2213,7 +2211,7 @@ nios2_assemble_arg_I (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 16-bit unsigned immediate.  */
-static void 
+static void
 nios2_assemble_arg_u (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2237,7 +2235,7 @@ nios2_assemble_arg_u (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 7-bit unsigned immediate with 2-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_U (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2261,7 +2259,7 @@ nios2_assemble_arg_U (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 5-bit unsigned immediate with 2-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_V (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2280,7 +2278,7 @@ nios2_assemble_arg_V (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 4-bit unsigned immediate with 2-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_W (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2294,7 +2292,7 @@ nios2_assemble_arg_W (const char *token, nios2_insn_infoS *insn)
       insn->constant_bits |= SET_IW_T2I4_IMM4 (val >> 2);
       break;
     case iw_L5I4X1_type:
-      /* This argument is optional for push.n/pop.n, and defaults to 
+      /* This argument is optional for push.n/pop.n, and defaults to
         zero if unspecified.  */
       if (token == NULL)
        return;
@@ -2309,7 +2307,7 @@ nios2_assemble_arg_W (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 4-bit unsigned immediate with 1-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_X (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2328,7 +2326,7 @@ nios2_assemble_arg_X (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 4-bit unsigned immediate without shift.  */
-static void 
+static void
 nios2_assemble_arg_Y (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2348,7 +2346,7 @@ nios2_assemble_arg_Y (const char *token, nios2_insn_infoS *insn)
 
 
 /* 16-bit signed immediate address offset.  */
-static void 
+static void
 nios2_assemble_arg_o (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2372,7 +2370,7 @@ nios2_assemble_arg_o (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 10-bit signed address offset with 1-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_O (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2391,7 +2389,7 @@ nios2_assemble_arg_O (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 7-bit signed address offset with 1-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_P (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2410,7 +2408,7 @@ nios2_assemble_arg_P (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 5-bit unsigned immediate.  */
-static void 
+static void
 nios2_assemble_arg_j (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2458,7 +2456,7 @@ nios2_assemble_arg_j (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Second 5-bit unsigned immediate field.  */
-static void 
+static void
 nios2_assemble_arg_k (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2483,7 +2481,7 @@ nios2_assemble_arg_k (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 8-bit unsigned immediate.  */
-static void 
+static void
 nios2_assemble_arg_l (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2507,7 +2505,7 @@ nios2_assemble_arg_l (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 26-bit unsigned immediate.  */
-static void 
+static void
 nios2_assemble_arg_m (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2537,7 +2535,7 @@ nios2_assemble_arg_m (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 6-bit unsigned immediate with no shifting.  */
-static void 
+static void
 nios2_assemble_arg_M (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2556,7 +2554,7 @@ nios2_assemble_arg_M (const char *token, nios2_insn_infoS *insn)
 }
 
 /* 6-bit unsigned immediate with 2-bit shift.  */
-static void 
+static void
 nios2_assemble_arg_N (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2576,7 +2574,7 @@ nios2_assemble_arg_N (const char *token, nios2_insn_infoS *insn)
 
 
 /* Encoded enumeration for addi.n/subi.n.  */
-static void 
+static void
 nios2_assemble_arg_e (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2603,7 +2601,7 @@ nios2_assemble_arg_e (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Encoded enumeration for slli.n/srli.n.  */
-static void 
+static void
 nios2_assemble_arg_f (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2630,7 +2628,7 @@ nios2_assemble_arg_f (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Encoded enumeration for andi.n.  */
-static void 
+static void
 nios2_assemble_arg_g (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2657,7 +2655,7 @@ nios2_assemble_arg_g (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Encoded enumeration for movi.n.  */
-static void 
+static void
 nios2_assemble_arg_h (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2688,7 +2686,7 @@ nios2_assemble_arg_h (const char *token, nios2_insn_infoS *insn)
 }
 
 /* Encoded REGMASK for ldwm/stwm or push.n/pop.n.  */
-static void 
+static void
 nios2_assemble_arg_R (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2712,7 +2710,7 @@ nios2_assemble_arg_R (const char *token, nios2_insn_infoS *insn)
          mask = (reglist & 0x00ffc000) >> 14;
          if (reglist & (1 << 28))
            mask |= 1 << 10;
-         if (reglist & (1 << 31))
+         if (reglist & (1u << 31))
            mask |= 1 << 11;
        }
       insn->insn_code |= SET_IW_F1X4L17_REGMASK (mask);
@@ -2739,14 +2737,14 @@ nios2_assemble_arg_R (const char *token, nios2_insn_infoS *insn)
          insn->insn_code |= SET_IW_L5I4X1_CS (1);
        }
       break;
-       
+
     default:
       bad_opcode (op);
     }
 }
 
 /* Base register for ldwm/stwm.  */
-static void 
+static void
 nios2_assemble_arg_B (const char *token, nios2_insn_infoS *insn)
 {
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
@@ -2762,7 +2760,7 @@ nios2_assemble_arg_B (const char *token, nios2_insn_infoS *insn)
   switch (op->format)
     {
     case iw_F1X4L17_type:
-      /* For ldwm, check to see if the base register is already inside the 
+      /* For ldwm, check to see if the base register is already inside the
         register list.  */
       if (op->match == MATCH_R2_LDWM
          && (nios2_reglist_mask & (1 << reg->index)))
@@ -2828,71 +2826,71 @@ nios2_assemble_args (nios2_insn_infoS *insn)
       case 'c':
        nios2_assemble_arg_c (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'd':
        nios2_assemble_arg_d (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 's':
        nios2_assemble_arg_s (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 't':
        nios2_assemble_arg_t (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'D':
        nios2_assemble_arg_D (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'S':
        nios2_assemble_arg_S (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'T':
        nios2_assemble_arg_T (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'i':
        nios2_assemble_arg_i (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'I':
        nios2_assemble_arg_I (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'u':
        nios2_assemble_arg_u (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'U':
        nios2_assemble_arg_U (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'V':
        nios2_assemble_arg_V (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'W':
        nios2_assemble_arg_W (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'X':
        nios2_assemble_arg_X (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'Y':
        nios2_assemble_arg_Y (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'o':
        nios2_assemble_arg_o (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'O':
        nios2_assemble_arg_O (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'P':
        nios2_assemble_arg_P (insn->insn_tokens[tokidx++], insn);
        break;
@@ -2900,15 +2898,15 @@ nios2_assemble_args (nios2_insn_infoS *insn)
       case 'j':
        nios2_assemble_arg_j (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'k':
        nios2_assemble_arg_k (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'l':
        nios2_assemble_arg_l (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'm':
        nios2_assemble_arg_m (insn->insn_tokens[tokidx++], insn);
        break;
@@ -2924,19 +2922,19 @@ nios2_assemble_args (nios2_insn_infoS *insn)
       case 'e':
        nios2_assemble_arg_e (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'f':
        nios2_assemble_arg_f (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'g':
        nios2_assemble_arg_g (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'h':
        nios2_assemble_arg_h (insn->insn_tokens[tokidx++], insn);
        break;
-       
+
       case 'R':
        nios2_assemble_arg_R (insn->insn_tokens[tokidx++], insn);
        break;
@@ -2950,7 +2948,7 @@ nios2_assemble_args (nios2_insn_infoS *insn)
        break;
       }
 
-  /* Perform argument checking.  */  
+  /* Perform argument checking.  */
   nios2_check_assembly (insn->insn_code | insn->constant_bits,
                        insn->insn_tokens[tokidx]);
 }
@@ -2966,7 +2964,7 @@ static char *
 nios2_consume_arg (char *argstr, const char *parsestr)
 {
   char *temp;
-  
+
   switch (*parsestr)
     {
     case 'c':
@@ -3015,7 +3013,7 @@ nios2_consume_arg (char *argstr, const char *parsestr)
     case 'h':
     case 'M':
     case 'N':
-      
+
       /* We can't have %hi, %lo or %hiadj here.  */
       if (*argstr == '%')
        as_bad (_("badly formed expression near %s"), argstr);
@@ -3102,7 +3100,7 @@ nios2_parse_args (nios2_insn_infoS *insn, char *argstr,
   p = argstr;
   i = 0;
   bfd_boolean terminate = FALSE;
-  
+
   /* This rest of this function is it too fragile and it mostly works,
      therefore special case this one.  */
   if (*parsestr == 0 && argstr != 0)
@@ -3111,7 +3109,7 @@ nios2_parse_args (nios2_insn_infoS *insn, char *argstr,
       parsed_args[0] = NULL;
       return;
     }
-  
+
   while (p != NULL && !terminate && i < NIOS2_MAX_INSN_TOKENS)
     {
       parsed_args[i] = nios2_consume_arg (p, parsestr);
@@ -3158,10 +3156,7 @@ nios2_modify_arg (char **parsed_args, const char *modifier,
 {
   char *tmp = parsed_args[ndx];
 
-  parsed_args[ndx]
-    = (char *) malloc (strlen (parsed_args[ndx]) + strlen (modifier) + 1);
-  strcpy (parsed_args[ndx], tmp);
-  strcat (parsed_args[ndx], modifier);
+  parsed_args[ndx] = concat (tmp, modifier, (char *) NULL);
 }
 
 /* Modify parsed_args[ndx] by negating that argument.  */
@@ -3171,13 +3166,7 @@ nios2_negate_arg (char **parsed_args, const char *modifier ATTRIBUTE_UNUSED,
 {
   char *tmp = parsed_args[ndx];
 
-  parsed_args[ndx]
-    = (char *) malloc (strlen ("~(") + strlen (parsed_args[ndx]) +
-                      strlen (")+1") + 1);
-
-  strcpy (parsed_args[ndx], "~(");
-  strcat (parsed_args[ndx], tmp);
-  strcat (parsed_args[ndx], ")+1");
+  parsed_args[ndx] = concat ("~(", tmp, ")+1", (char *) NULL);
 }
 
 /* The function nios2_swap_args swaps the pointers at indices index_1 and
@@ -3219,7 +3208,7 @@ nios2_append_arg (char **parsed_args, const char *appnd, int num,
   parsed_args[i + 1] = NULL;
 }
 
-/* This function inserts the string insert num times in the array 
+/* This function inserts the string insert num times in the array
    parsed_args, starting at the index start.  */
 static void
 nios2_insert_arg (char **parsed_args, const char *insert, int num,
@@ -3241,11 +3230,8 @@ nios2_insert_arg (char **parsed_args, const char *insert, int num,
 static void
 nios2_free_arg (char **parsed_args, int num ATTRIBUTE_UNUSED, int start)
 {
-  if (parsed_args[start])
-    {
-      free (parsed_args[start]);
-      parsed_args[start] = NULL;
-    }
+  free (parsed_args[start]);
+  parsed_args[start] = NULL;
 }
 
 /* This function swaps the pseudo-op for a real op.  */
@@ -3253,16 +3239,29 @@ static nios2_ps_insn_infoS*
 nios2_translate_pseudo_insn (nios2_insn_infoS *insn)
 {
 
+  const struct nios2_opcode *op = insn->insn_nios2_opcode;
   nios2_ps_insn_infoS *ps_insn;
+  unsigned int tokidx, ntok;
 
-  /* Find which real insn the pseudo-op transates to and
+  /* Find which real insn the pseudo-op translates to and
      switch the insn_info ptr to point to it.  */
-  ps_insn = nios2_ps_lookup (insn->insn_nios2_opcode->name);
+  ps_insn = nios2_ps_lookup (op->name);
 
   if (ps_insn != NULL)
     {
       insn->insn_nios2_opcode = nios2_opcode_lookup (ps_insn->insn);
       insn->insn_tokens[0] = insn->insn_nios2_opcode->name;
+      
+      /* Make sure there are enough arguments.  */
+      ntok = ((op->pinfo & NIOS2_INSN_OPTARG)
+             ? op->num_args - 1 : op->num_args);
+      for (tokidx = 1; tokidx <= ntok; tokidx++)
+       if (insn->insn_tokens[tokidx] == NULL)
+         {
+           as_bad ("missing argument");
+           return NULL;
+         }
+
       /* Modify the args so they work with the real insn.  */
       ps_insn->arg_modifer_func ((char **) insn->insn_tokens,
                                 ps_insn->arg_modifier, ps_insn->num,
@@ -3323,7 +3322,7 @@ static void
 output_insn (nios2_insn_infoS *insn)
 {
   char *f;
-  nios2_insn_relocS *reloc; 
+  nios2_insn_relocS *reloc;
   f = frag_more (insn->insn_nios2_opcode->size);
   /* This allocates enough space for the instruction
      and puts it in the current frag.  */
@@ -3470,7 +3469,7 @@ output_movia (nios2_insn_infoS *insn)
      and puts it in the current frag.  */
   char *f = frag_more (8);
   nios2_insn_relocS *reloc = insn->insn_reloc;
-  unsigned long reg, code;
+  unsigned long reg, code = 0;
   const struct nios2_opcode *op = insn->insn_nios2_opcode;
 
   /* If the reloc is NULL, there was an error assembling the movia.  */
@@ -3539,7 +3538,7 @@ nios2_use_arch (const char *arch)
 /* The following functions are called by machine-independent parts of
    the assembler. */
 int
-md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
+md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
 {
   switch (c)
     {
@@ -3604,7 +3603,6 @@ void
 md_begin (void)
 {
   int i;
-  const char *inserted;
 
   switch (nios2_architecture)
     {
@@ -3619,54 +3617,23 @@ md_begin (void)
       break;
     }
 
-  /* Create and fill a hashtable for the Nios II opcodes, registers and 
+  /* Create and fill a hashtable for the Nios II opcodes, registers and
      arguments.  */
-  nios2_opcode_hash = hash_new ();
-  nios2_reg_hash = hash_new ();
-  nios2_ps_hash = hash_new ();
+  nios2_opcode_hash = str_htab_create ();
+  nios2_reg_hash = str_htab_create ();
+  nios2_ps_hash = str_htab_create ();
 
   for (i = 0; i < nios2_num_opcodes; ++i)
-    {
-      inserted
-       = hash_insert (nios2_opcode_hash, nios2_opcodes[i].name,
-                      (PTR) & nios2_opcodes[i]);
-      if (inserted != NULL)
-       {
-         fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
-                  nios2_opcodes[i].name, inserted);
-         /* Probably a memory allocation problem?  Give up now.  */
-         as_fatal (_("Broken assembler.  No assembly attempted."));
-       }
-    }
+    str_hash_insert (nios2_opcode_hash, nios2_opcodes[i].name,
+                    (PTR) & nios2_opcodes[i]);
 
   for (i = 0; i < nios2_num_regs; ++i)
-    {
-      inserted
-       = hash_insert (nios2_reg_hash, nios2_regs[i].name,
-                      (PTR) & nios2_regs[i]);
-      if (inserted != NULL)
-       {
-         fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
-                  nios2_regs[i].name, inserted);
-         /* Probably a memory allocation problem?  Give up now.  */
-         as_fatal (_("Broken assembler.  No assembly attempted."));
-       }
-
-    }
+    str_hash_insert (nios2_reg_hash, nios2_regs[i].name,
+                    (PTR) & nios2_regs[i]);
 
   for (i = 0; i < nios2_num_ps_insn_info_structs; ++i)
-    {
-      inserted
-       = hash_insert (nios2_ps_hash, nios2_ps_insn_info_structs[i].pseudo_insn,
-                      (PTR) & nios2_ps_insn_info_structs[i]);
-      if (inserted != NULL)
-       {
-         fprintf (stderr, _("internal error: can't hash `%s': %s\n"),
-                  nios2_ps_insn_info_structs[i].pseudo_insn, inserted);
-         /* Probably a memory allocation problem?  Give up now.  */
-         as_fatal (_("Broken assembler.  No assembly attempted."));
-       }
-    }
+    str_hash_insert (nios2_ps_hash, nios2_ps_insn_info_structs[i].pseudo_insn,
+                    (PTR) & nios2_ps_insn_info_structs[i]);
 
   /* Assembler option defaults.  */
   nios2_as_options.noat = FALSE;
@@ -3688,11 +3655,12 @@ md_begin (void)
 void
 md_assemble (char *op_str)
 {
-  char *argstr; 
+  char *argstr;
   char *op_strdup = NULL;
   unsigned long saved_pinfo = 0;
   nios2_insn_infoS thisinsn;
   nios2_insn_infoS *insn = &thisinsn;
+  bfd_boolean ps_error = FALSE;
 
   /* Make sure we are aligned on an appropriate boundary.  */
   if (nios2_current_align < nios2_min_align)
@@ -3731,43 +3699,53 @@ md_assemble (char *op_str)
        nios2_parse_args (insn, argstr, insn->insn_nios2_opcode->args_test,
                          (char **) &insn->insn_tokens[1]);
 
-      /* We need to preserve the MOVIA macro as this is clobbered by 
+      /* We need to preserve the MOVIA macro as this is clobbered by
         translate_pseudo_insn.  */
       if (insn->insn_nios2_opcode->pinfo == NIOS2_INSN_MACRO_MOVIA)
        saved_pinfo = NIOS2_INSN_MACRO_MOVIA;
-      /* If the instruction is an pseudo-instruction, we want to replace it 
+      /* If the instruction is an pseudo-instruction, we want to replace it
         with its real equivalent, and then continue.  */
       if ((insn->insn_nios2_opcode->pinfo & NIOS2_INSN_MACRO)
          == NIOS2_INSN_MACRO)
-       ps_insn = nios2_translate_pseudo_insn (insn);
-
-      /* Assemble the parsed arguments into the instruction word.  */
-      nios2_assemble_args (insn);
-
-      /* Handle relaxation and other transformations.  */
-      if (nios2_as_options.relax != relax_none
-         && !nios2_as_options.noat
-         && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_UBRANCH)
-       output_ubranch (insn);
-      else if (nios2_as_options.relax != relax_none
-              && !nios2_as_options.noat
-              && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CBRANCH)
-       output_cbranch (insn);
-      else if (nios2_as_options.relax == relax_all
-              && !nios2_as_options.noat
-              && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CALL
-              && insn->insn_reloc
-              && ((insn->insn_reloc->reloc_type
-                   == BFD_RELOC_NIOS2_CALL26)
-                  || (insn->insn_reloc->reloc_type
-                      == BFD_RELOC_NIOS2_CALL26_NOAT)))
-       output_call (insn);
-      else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
-       output_movia (insn);
-      else
-       output_insn (insn);
-      if (ps_insn)
-       nios2_cleanup_pseudo_insn (insn, ps_insn);
+       {
+         ps_insn = nios2_translate_pseudo_insn (insn);
+         if (!ps_insn)
+           ps_error = TRUE;
+       }
+
+      /* If we found invalid pseudo-instruction syntax, the error's already
+        been diagnosed in nios2_translate_pseudo_insn, so skip
+        remaining processing.  */
+      if (!ps_error)
+       {
+         /* Assemble the parsed arguments into the instruction word.  */
+         nios2_assemble_args (insn);
+
+         /* Handle relaxation and other transformations.  */
+         if (nios2_as_options.relax != relax_none
+             && !nios2_as_options.noat
+             && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_UBRANCH)
+           output_ubranch (insn);
+         else if (nios2_as_options.relax != relax_none
+                  && !nios2_as_options.noat
+                  && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CBRANCH)
+           output_cbranch (insn);
+         else if (nios2_as_options.relax == relax_all
+                  && !nios2_as_options.noat
+                  && insn->insn_nios2_opcode->pinfo & NIOS2_INSN_CALL
+                  && insn->insn_reloc
+                  && ((insn->insn_reloc->reloc_type
+                       == BFD_RELOC_NIOS2_CALL26)
+                      || (insn->insn_reloc->reloc_type
+                          == BFD_RELOC_NIOS2_CALL26_NOAT)))
+           output_call (insn);
+         else if (saved_pinfo == NIOS2_INSN_MACRO_MOVIA)
+           output_movia (insn);
+         else
+           output_insn (insn);
+         if (ps_insn)
+           nios2_cleanup_pseudo_insn (insn, ps_insn);
+       }
     }
   else
     /* Unrecognised instruction - error.  */
@@ -3862,8 +3840,8 @@ nios2_frob_symbol (symbolS *symp)
 arelent *
 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
 {
-  arelent *reloc = (arelent *) xmalloc (sizeof (arelent));
-  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  arelent *reloc = XNEW (arelent);
+  reloc->sym_ptr_ptr = XNEW (asymbol *);
   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
 
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
@@ -3909,7 +3887,7 @@ md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
 
 /* Called just before the assembler exits.  */
 void
-md_end ()
+md_end (void)
 {
   /* FIXME - not yet implemented */
 }
@@ -3929,7 +3907,7 @@ md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
            as_bad ("GOT already in the symbol table");
 
          GOT_symbol = symbol_new (name, undefined_section,
-                                  (valueT) 0, &zero_address_frag);
+                                  &zero_address_frag, 0);
        }
 
       return GOT_symbol;
@@ -3979,7 +3957,7 @@ nios2_cons_align (int size)
 /* Map 's' to SHF_NIOS2_GPREL.  */
 /* This is from the Alpha code tc-alpha.c.  */
 int
-nios2_elf_section_letter (int letter, char **ptr_msg)
+nios2_elf_section_letter (int letter, const char **ptr_msg)
 {
   if (letter == 's')
     return SHF_NIOS2_GPREL;
@@ -3998,31 +3976,48 @@ nios2_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
   return flags;
 }
 
-/* Implement TC_PARSE_CONS_EXPRESSION to handle %tls_ldo(...) */
+/* Implement TC_PARSE_CONS_EXPRESSION to handle %tls_ldo(...) and
+   %gotoff(...).  */
 bfd_reloc_code_real_type
 nios2_cons (expressionS *exp, int size)
 {
-  bfd_reloc_code_real_type nios2_tls_ldo_reloc = BFD_RELOC_NONE;
+  bfd_reloc_code_real_type explicit_reloc = BFD_RELOC_NONE;
+  const char *reloc_name = NULL;
 
   SKIP_WHITESPACE ();
   if (input_line_pointer[0] == '%')
     {
       if (strprefix (input_line_pointer + 1, "tls_ldo"))
        {
+         reloc_name = "%tls_ldo";
          if (size != 4)
            as_bad (_("Illegal operands: %%tls_ldo in %d-byte data field"),
                    size);
          else
            {
              input_line_pointer += 8;
-             nios2_tls_ldo_reloc = BFD_RELOC_NIOS2_TLS_DTPREL;
+             explicit_reloc = BFD_RELOC_NIOS2_TLS_DTPREL;
+           }
+       }
+      else if (strprefix (input_line_pointer + 1, "gotoff"))
+       {
+         reloc_name = "%gotoff";
+         if (size != 4)
+           as_bad (_("Illegal operands: %%gotoff in %d-byte data field"),
+                   size);
+         else
+           {
+             input_line_pointer += 7;
+             explicit_reloc = BFD_RELOC_NIOS2_GOTOFF;
            }
        }
-      if (nios2_tls_ldo_reloc != BFD_RELOC_NONE)
+
+      if (explicit_reloc != BFD_RELOC_NONE)
        {
          SKIP_WHITESPACE ();
          if (input_line_pointer[0] != '(')
-           as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+           as_bad (_("Illegal operands: %s requires arguments in ()"),
+                   reloc_name);
          else
            {
              int c;
@@ -4040,29 +4035,32 @@ nios2_cons (expressionS *exp, int size)
                  }
 
              if (c != ')')
-               as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+               as_bad (_("Illegal operands: %s requires arguments in ()"),
+                       reloc_name);
              else
                {
                  *end = '\0';
                  expression (exp);
                  *end = c;
                  if (input_line_pointer != end)
-                   as_bad (_("Illegal operands: %%tls_ldo requires arguments in ()"));
+                   as_bad (_("Illegal operands: %s requires arguments in ()"),
+                           reloc_name);
                  else
                    {
                      input_line_pointer++;
                      SKIP_WHITESPACE ();
                      c = *input_line_pointer;
                      if (! is_end_of_line[c] && c != ',')
-                       as_bad (_("Illegal operands: garbage after %%tls_ldo()"));
+                       as_bad (_("Illegal operands: garbage after %s()"),
+                               reloc_name);
                    }
                }
            }
        }
     }
-  if (nios2_tls_ldo_reloc == BFD_RELOC_NONE)
+  if (explicit_reloc == BFD_RELOC_NONE)
     expression (exp);
-  return nios2_tls_ldo_reloc;
+  return explicit_reloc;
 }
 
 /* Implement HANDLE_ALIGN.  */
This page took 0.044578 seconds and 4 git commands to generate.