X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-aarch64.c;h=415663b5504bb2a6622f90107bb9f4d30a9baa50;hb=add39d2344036db9334bdeb1ec20a90beaa3ca49;hp=bb2f228553a2eba24bd6fb0dba38036bc24bb719;hpb=d6bf7ce6c26cd31fe744419269dea999a3faaf8c;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index bb2f228553..415663b550 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -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. @@ -4018,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 { @@ -4230,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) @@ -4635,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; @@ -4649,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: @@ -5643,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]); } @@ -6041,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); } @@ -6261,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; @@ -7137,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; @@ -7449,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; @@ -7480,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; } @@ -7506,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 (); @@ -7602,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; @@ -7646,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. */ @@ -7669,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. */ @@ -7711,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; }; @@ -7728,7 +7796,7 @@ static const struct aarch64_arch_option_table aarch64_archs[] = { /* ISA extensions. */ struct aarch64_option_cpu_value_table { - char *name; + const char *name; const aarch64_feature_set value; }; @@ -7740,23 +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 @@ -7764,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; @@ -7773,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) @@ -7843,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) @@ -7875,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) @@ -7909,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; }; @@ -7920,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); @@ -7955,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;