use XNEW and related macros more
[deliverable/binutils-gdb.git] / gas / config / tc-aarch64.c
index b45aac8f4bff58846dbd9f11e05ba99e5ab52a4f..415663b5504bb2a6622f90107bb9f4d30a9baa50 100644 (file)
@@ -1,6 +1,6 @@
 /* tc-aarch64.c -- Assemble for the AArch64 ISA
 
-   Copyright (C) 2009-2015 Free Software Foundation, Inc.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
    Contributed by ARM Ltd.
 
    This file is part of GAS.
@@ -406,6 +406,7 @@ static struct hash_control *aarch64_reg_hsh;
 static struct hash_control *aarch64_barrier_opt_hsh;
 static struct hash_control *aarch64_nzcv_hsh;
 static struct hash_control *aarch64_pldop_hsh;
+static struct hash_control *aarch64_hint_opt_hsh;
 
 /* Stuff needed to resolve the label ambiguity
    As:
@@ -572,7 +573,7 @@ my_get_expression (expressionS * ep, char **str, int prefix_mode,
    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)
 {
   return ieee_md_atof (type, litP, sizeP, target_big_endian);
@@ -743,7 +744,7 @@ aarch64_reg_parse_32_64 (char **ccp, int reject_sp, int reject_rz,
    otherwise return FALSE.
 
    Accept only one occurrence of:
-   8b 16b 4h 8h 2s 4s 1d 2d
+   8b 16b 2h 4h 8h 2s 4s 1d 2d
    b h s d q  */
 static bfd_boolean
 parse_neon_type_for_operand (struct neon_type_el *parsed_type, char **str)
@@ -802,7 +803,8 @@ elt_size:
        first_error (_("missing element size"));
       return FALSE;
     }
-  if (width != 0 && width * element_size != 64 && width * element_size != 128)
+  if (width != 0 && width * element_size != 64 && width * element_size != 128
+      && !(width == 2 && element_size == 16))
     {
       first_error_fmt (_
                       ("invalid element size %d and vector size combination %c"),
@@ -1185,7 +1187,7 @@ insert_reg_alias (char *str, int number, aarch64_reg_type type)
     }
 
   name = xstrdup (str);
-  new = xmalloc (sizeof (reg_entry));
+  new = XNEW (reg_entry);
 
   new->name = name;
   new->number = number;
@@ -1239,9 +1241,7 @@ create_register_alias (char *newname, char *p)
   nlen = strlen (newname);
 #endif
 
-  nbuf = alloca (nlen + 1);
-  memcpy (nbuf, newname, nlen);
-  nbuf[nlen] = '\0';
+  nbuf = xmemdup0 (newname, nlen);
 
   /* Create aliases under the new name as stated; an all-lowercase
      version of the new name; and an all-uppercase version of the new
@@ -1263,7 +1263,10 @@ create_register_alias (char *newname, char *p)
             the artificial FOO alias because it has already been created by the
             first .req.  */
          if (insert_reg_alias (nbuf, old->number, old->type) == NULL)
-           return TRUE;
+           {
+             free (nbuf);
+             return TRUE;
+           }
        }
 
       for (p = nbuf; *p; p++)
@@ -1273,6 +1276,7 @@ create_register_alias (char *newname, char *p)
        insert_reg_alias (nbuf, old->number, old->type);
     }
 
+  free (nbuf);
   return TRUE;
 }
 
@@ -1571,7 +1575,7 @@ find_or_make_literal_pool (int size)
   if (pool == NULL)
     {
       /* Create a new pool.  */
-      pool = xmalloc (sizeof (*pool));
+      pool = XNEW (literal_pool);
       if (!pool)
        return NULL;
 
@@ -1648,7 +1652,8 @@ add_to_lit_pool (expressionS *exp, int size)
        {
          /* PR 16688: Bignums are held in a single global array.  We must
             copy and preserve that value now, before it is overwritten.  */
-         pool->literals[entry].bignum = xmalloc (CHARS_PER_LITTLENUM * exp->X_add_number);
+         pool->literals[entry].bignum = XNEWVEC (LITTLENUM_TYPE,
+                                                 exp->X_add_number);
          memcpy (pool->literals[entry].bignum, generic_bignum,
                  CHARS_PER_LITTLENUM * exp->X_add_number);
        }
@@ -3471,10 +3476,8 @@ parse_address_reloc (char **str, aarch64_opnd_info *operand)
 static bfd_boolean
 parse_half (char **str, int *internal_fixup_p)
 {
-  char *p, *saved;
-  int dummy;
+  char *p = *str;
 
-  p = *str;
   skip_past_char (&p, '#');
 
   gas_assert (internal_fixup_p);
@@ -3504,12 +3507,6 @@ parse_half (char **str, int *internal_fixup_p)
   else
     *internal_fixup_p = 1;
 
-  /* Avoid parsing a register as a general symbol.  */
-  saved = p;
-  if (aarch64_reg_parse_32_64 (&p, 0, 0, &dummy, &dummy) != PARSE_FAIL)
-    return FALSE;
-  p = saved;
-
   if (! my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX, 1))
     return FALSE;
 
@@ -3604,6 +3601,41 @@ parse_barrier (char **str)
   return o->value;
 }
 
+/* Parse an operand for a PSB barrier.  Set *HINT_OPT to the hint-option record
+   return 0 if successful.  Otherwise return PARSE_FAIL.  */
+
+static int
+parse_barrier_psb (char **str,
+                  const struct aarch64_name_value_pair ** hint_opt)
+{
+  char *p, *q;
+  const struct aarch64_name_value_pair *o;
+
+  p = q = *str;
+  while (ISALPHA (*q))
+    q++;
+
+  o = hash_find_n (aarch64_hint_opt_hsh, p, q - p);
+  if (!o)
+    {
+      set_fatal_syntax_error
+       ( _("unknown or missing option to PSB"));
+      return PARSE_FAIL;
+    }
+
+  if (o->value != 0x11)
+    {
+      /* PSB only accepts option name 'CSYNC'.  */
+      set_syntax_error
+       (_("the specified option is not accepted for PSB"));
+      return PARSE_FAIL;
+    }
+
+  *str = q;
+  *hint_opt = o;
+  return 0;
+}
+
 /* Parse a system register or a PSTATE field name for an MSR/MRS instruction.
    Returns the encoding for the option, or PARSE_FAIL.
 
@@ -3687,6 +3719,10 @@ parse_sys_ins_reg (char **str, struct hash_control *sys_ins_regs)
   if (!o)
     return NULL;
 
+  if (!aarch64_sys_ins_reg_supported_p (cpu_variant, o))
+    as_bad (_("selected processor does not support system register "
+             "name '%s'"), buf);
+
   *str = q;
   return o;
 }
@@ -4014,9 +4050,7 @@ add_operand_error_record (const operand_error_record* new_record)
       /* Get one empty record.  */
       if (free_opnd_error_record_nodes == NULL)
        {
-         record = xmalloc (sizeof (operand_error_record));
-         if (record == NULL)
-           abort ();
+         record = XNEW (operand_error_record);
        }
       else
        {
@@ -4226,11 +4260,11 @@ print_operands (char *buf, const aarch64_opcode *opcode,
 static void
 output_info (const char *format, ...)
 {
-  char *file;
+  const char *file;
   unsigned int line;
   va_list args;
 
-  as_where (&file, &line);
+  file = as_where (&line);
   if (file)
     {
       if (line != 0)
@@ -4631,6 +4665,14 @@ vectype_to_qualifier (const struct neon_type_el *vectype)
   /* Element size in bytes indexed by neon_el_type.  */
   const unsigned char ele_size[5]
     = {1, 2, 4, 8, 16};
+  const unsigned int ele_base [5] =
+    {
+      AARCH64_OPND_QLF_V_8B,
+      AARCH64_OPND_QLF_V_2H,
+      AARCH64_OPND_QLF_V_2S,
+      AARCH64_OPND_QLF_V_1D,
+      AARCH64_OPND_QLF_V_1Q
+  };
 
   if (!vectype->defined || vectype->type == NT_invtype)
     goto vectype_conversion_fail;
@@ -4645,14 +4687,28 @@ vectype_to_qualifier (const struct neon_type_el *vectype)
       /* Vector register.  */
       int reg_size = ele_size[vectype->type] * vectype->width;
       unsigned offset;
-      if (reg_size != 16 && reg_size != 8)
+      unsigned shift;
+      if (reg_size != 16 && reg_size != 8 && reg_size != 4)
        goto vectype_conversion_fail;
-      /* The conversion is calculated based on the relation of the order of
-        qualifiers to the vector element size and vector register size.  */
-      offset = (vectype->type == NT_q)
-       ? 8 : (vectype->type << 1) + (reg_size >> 4);
-      gas_assert (offset <= 8);
-      return AARCH64_OPND_QLF_V_8B + offset;
+
+      /* The conversion is by calculating the offset from the base operand
+        qualifier for the vector type.  The operand qualifiers are regular
+        enough that the offset can established by shifting the vector width by
+        a vector-type dependent amount.  */
+      shift = 0;
+      if (vectype->type == NT_b)
+       shift = 4;
+      else if (vectype->type == NT_h || vectype->type == NT_s)
+       shift = 2;
+      else if (vectype->type >= NT_d)
+       shift = 1;
+      else
+       gas_assert (0);
+
+      offset = ele_base [vectype->type] + (vectype->width >> shift);
+      gas_assert (AARCH64_OPND_QLF_V_8B <= offset
+                 && offset <= AARCH64_OPND_QLF_V_1Q);
+      return offset;
     }
 
 vectype_conversion_fail:
@@ -5639,6 +5695,12 @@ sys_reg_ins:
          inst.base.operands[i].prfop = aarch64_prfops + val;
          break;
 
+       case AARCH64_OPND_BARRIER_PSB:
+         val = parse_barrier_psb (&str, &(info->hint_option));
+         if (val == PARSE_FAIL)
+           goto failure;
+         break;
+
        default:
          as_fatal (_("unhandled operand code %d"), operands[i]);
        }
@@ -6037,8 +6099,7 @@ md_assemble (char *str)
                 store the instruction information for the future fix-up.  */
              struct aarch64_inst *copy;
              gas_assert (inst.reloc.type != BFD_RELOC_UNUSED);
-             if ((copy = xmalloc (sizeof (struct aarch64_inst))) == NULL)
-               abort ();
+             copy = XNEW (struct aarch64_inst);
              memcpy (copy, &inst.base, sizeof (struct aarch64_inst));
              output_inst (copy);
            }
@@ -6257,7 +6318,7 @@ aarch64_handle_align (fragS * fragP)
 {
   /* NOP = d503201f */
   /* AArch64 instructions are always little-endian.  */
-  static char const aarch64_noop[4] = { 0x1f, 0x20, 0x03, 0xd5 };
+  static unsigned char const aarch64_noop[4] = { 0x1f, 0x20, 0x03, 0xd5 };
 
   int bytes, fix, noop_size;
   char *p;
@@ -7133,9 +7194,9 @@ tc_gen_reloc (asection * section, fixS * fixp)
   arelent *reloc;
   bfd_reloc_code_real_type code;
 
-  reloc = xmalloc (sizeof (arelent));
+  reloc = XNEW (arelent);
 
-  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+  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;
 
@@ -7445,7 +7506,7 @@ fill_instruction_hash_table (void)
       templates *templ, *new_templ;
       templ = hash_find (aarch64_ops_hsh, opcode->name);
 
-      new_templ = (templates *) xmalloc (sizeof (templates));
+      new_templ = XNEW (templates);
       new_templ->opcode = opcode;
       new_templ->next = NULL;
 
@@ -7476,8 +7537,7 @@ get_upper_str (const char *str)
 {
   char *ret;
   size_t len = strlen (str);
-  if ((ret = xmalloc (len + 1)) == NULL)
-    abort ();
+  ret = XNEWVEC (char, len + 1);
   convert_to_upper (ret, str, len);
   return ret;
 }
@@ -7502,7 +7562,8 @@ md_begin (void)
       || (aarch64_reg_hsh = hash_new ()) == NULL
       || (aarch64_barrier_opt_hsh = hash_new ()) == NULL
       || (aarch64_nzcv_hsh = hash_new ()) == NULL
-      || (aarch64_pldop_hsh = hash_new ()) == NULL)
+      || (aarch64_pldop_hsh = hash_new ()) == NULL
+      || (aarch64_hint_opt_hsh = hash_new ()) == NULL)
     as_fatal (_("virtual memory exhausted"));
 
   fill_instruction_hash_table ();
@@ -7598,6 +7659,17 @@ md_begin (void)
                           (void *) (aarch64_prfops + i));
     }
 
+  for (i = 0; aarch64_hint_options[i].name != NULL; i++)
+    {
+      const char* name = aarch64_hint_options[i].name;
+
+      checked_hash_insert (aarch64_hint_opt_hsh, name,
+                          (void *) (aarch64_hint_options + i));
+      /* Also hash the name in the upper case.  */
+      checked_hash_insert (aarch64_pldop_hsh, get_upper_str (name),
+                          (void *) (aarch64_hint_options + i));
+    }
+
   /* Set the cpu variant based on the command-line options.  */
   if (!mcpu_cpu_opt)
     mcpu_cpu_opt = march_cpu_opt;
@@ -7642,8 +7714,8 @@ size_t md_longopts_size = sizeof (md_longopts);
 
 struct aarch64_option_table
 {
-  char *option;                        /* Option name to match.  */
-  char *help;                  /* Help information.  */
+  const char *option;                  /* Option name to match.  */
+  const char *help;                    /* Help information.  */
   int *var;                    /* Variable to change.  */
   int value;                   /* What to change it to.  */
   char *deprecated;            /* If non-null, print this message.  */
@@ -7665,7 +7737,7 @@ static struct aarch64_option_table aarch64_opts[] = {
 
 struct aarch64_cpu_option_table
 {
-  char *name;
+  const char *name;
   const aarch64_feature_set value;
   /* The canonical name of the CPU, or NULL to use NAME converted to upper
      case.  */
@@ -7676,6 +7748,8 @@ struct aarch64_cpu_option_table
    recognized by GCC.  */
 static const struct aarch64_cpu_option_table aarch64_cpus[] = {
   {"all", AARCH64_ANY, NULL},
+  {"cortex-a35", AARCH64_FEATURE (AARCH64_ARCH_V8,
+                                 AARCH64_FEATURE_CRC), "Cortex-A35"},
   {"cortex-a53", AARCH64_FEATURE (AARCH64_ARCH_V8,
                                  AARCH64_FEATURE_CRC), "Cortex-A53"},
   {"cortex-a57", AARCH64_FEATURE (AARCH64_ARCH_V8,
@@ -7705,7 +7779,7 @@ static const struct aarch64_cpu_option_table aarch64_cpus[] = {
 
 struct aarch64_arch_option_table
 {
-  char *name;
+  const char *name;
   const aarch64_feature_set value;
 };
 
@@ -7715,13 +7789,14 @@ static const struct aarch64_arch_option_table aarch64_archs[] = {
   {"all", AARCH64_ANY},
   {"armv8-a", AARCH64_ARCH_V8},
   {"armv8.1-a", AARCH64_ARCH_V8_1},
+  {"armv8.2-a", AARCH64_ARCH_V8_2},
   {NULL, AARCH64_ARCH_NONE}
 };
 
 /* ISA extensions.  */
 struct aarch64_option_cpu_value_table
 {
-  char *name;
+  const char *name;
   const aarch64_feature_set value;
 };
 
@@ -7733,21 +7808,25 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
   {"simd",             AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
   {"pan",              AARCH64_FEATURE (AARCH64_FEATURE_PAN, 0)},
   {"lor",              AARCH64_FEATURE (AARCH64_FEATURE_LOR, 0)},
+  {"ras",              AARCH64_FEATURE (AARCH64_FEATURE_RAS, 0)},
   {"rdma",             AARCH64_FEATURE (AARCH64_FEATURE_SIMD
                                         | AARCH64_FEATURE_RDMA, 0)},
+  {"fp16",             AARCH64_FEATURE (AARCH64_FEATURE_F16
+                                        | AARCH64_FEATURE_FP, 0)},
+  {"profile",          AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0)},
   {NULL,               AARCH64_ARCH_NONE}
 };
 
 struct aarch64_long_option_table
 {
-  char *option;                        /* Substring to match.  */
-  char *help;                  /* Help information.  */
-  int (*func) (char *subopt);  /* Function to decode sub-option.  */
+  const char *option;                  /* Substring to match.  */
+  const char *help;                    /* Help information.  */
+  int (*func) (const char *subopt);    /* Function to decode sub-option.  */
   char *deprecated;            /* If non-null, print this message.  */
 };
 
 static int
-aarch64_parse_features (char *str, const aarch64_feature_set **opt_p,
+aarch64_parse_features (const char *str, const aarch64_feature_set **opt_p,
                        bfd_boolean ext_only)
 {
   /* We insist on extensions being added before being removed.  We achieve
@@ -7755,7 +7834,7 @@ aarch64_parse_features (char *str, const aarch64_feature_set **opt_p,
      adding an extension (1) or removing it (0) and only allowing it to
      change in the order -1 -> 1 -> 0.  */
   int adding_value = -1;
-  aarch64_feature_set *ext_set = xmalloc (sizeof (aarch64_feature_set));
+  aarch64_feature_set *ext_set = XNEW (aarch64_feature_set);
 
   /* Copy the feature set, so that we can modify it.  */
   *ext_set = **opt_p;
@@ -7764,7 +7843,7 @@ aarch64_parse_features (char *str, const aarch64_feature_set **opt_p,
   while (str != NULL && *str != 0)
     {
       const struct aarch64_option_cpu_value_table *opt;
-      char *ext = NULL;
+      const char *ext = NULL;
       int optlen;
 
       if (!ext_only)
@@ -7834,10 +7913,10 @@ aarch64_parse_features (char *str, const aarch64_feature_set **opt_p,
 }
 
 static int
-aarch64_parse_cpu (char *str)
+aarch64_parse_cpu (const char *str)
 {
   const struct aarch64_cpu_option_table *opt;
-  char *ext = strchr (str, '+');
+  const char *ext = strchr (str, '+');
   size_t optlen;
 
   if (ext != NULL)
@@ -7866,10 +7945,10 @@ aarch64_parse_cpu (char *str)
 }
 
 static int
-aarch64_parse_arch (char *str)
+aarch64_parse_arch (const char *str)
 {
   const struct aarch64_arch_option_table *opt;
-  char *ext = strchr (str, '+');
+  const char *ext = strchr (str, '+');
   size_t optlen;
 
   if (ext != NULL)
@@ -7900,7 +7979,7 @@ aarch64_parse_arch (char *str)
 /* ABIs.  */
 struct aarch64_option_abi_value_table
 {
-  char *name;
+  const char *name;
   enum aarch64_abi_type value;
 };
 
@@ -7911,7 +7990,7 @@ static const struct aarch64_option_abi_value_table aarch64_abis[] = {
 };
 
 static int
-aarch64_parse_abi (char *str)
+aarch64_parse_abi (const char *str)
 {
   const struct aarch64_option_abi_value_table *opt;
   size_t optlen = strlen (str);
@@ -7946,7 +8025,7 @@ static struct aarch64_long_option_table aarch64_long_opts[] = {
 };
 
 int
-md_parse_option (int c, char *arg)
+md_parse_option (int c, const char *arg)
 {
   struct aarch64_option_table *opt;
   struct aarch64_long_option_table *lopt;
This page took 0.031168 seconds and 4 git commands to generate.