/* 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.
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:
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)
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"),
nlen = strlen (newname);
#endif
- nbuf = alloca (nlen + 1);
+ nbuf = xmalloc (nlen + 1);
memcpy (nbuf, newname, nlen);
nbuf[nlen] = '\0';
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++)
insert_reg_alias (nbuf, old->number, old->type);
}
+ free (nbuf);
return TRUE;
}
}
#ifdef OBJ_ELF
+/* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction. */
+
+static void
+s_tlsdescadd (int ignored ATTRIBUTE_UNUSED)
+{
+ expressionS exp;
+
+ expression (&exp);
+ frag_grow (4);
+ fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 4, &exp, 0,
+ BFD_RELOC_AARCH64_TLSDESC_ADD);
+
+ demand_empty_rest_of_line ();
+}
+
/* Emit BFD_RELOC_AARCH64_TLSDESC_CALL on the next BLR instruction. */
static void
demand_empty_rest_of_line ();
}
+
+/* Emit BFD_RELOC_AARCH64_TLSDESC_LDR on the next LDR instruction. */
+
+static void
+s_tlsdescldr (int ignored ATTRIBUTE_UNUSED)
+{
+ expressionS exp;
+
+ expression (&exp);
+ frag_grow (4);
+ fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 4, &exp, 0,
+ BFD_RELOC_AARCH64_TLSDESC_LDR);
+
+ demand_empty_rest_of_line ();
+}
#endif /* OBJ_ELF */
static void s_aarch64_arch (int);
{"arch_extension", s_aarch64_arch_extension, 0},
{"inst", s_aarch64_inst, 0},
#ifdef OBJ_ELF
+ {"tlsdescadd", s_tlsdescadd, 0},
{"tlsdesccall", s_tlsdesccall, 0},
+ {"tlsdescldr", s_tlsdescldr, 0},
{"word", s_aarch64_elf_cons, 4},
{"long", s_aarch64_elf_cons, 4},
{"xword", s_aarch64_elf_cons, 8},
BFD_RELOC_AARCH64_LD_GOT_LO12_NC,
0},
+ /* 0-15 bits of address/value: MOVk, no check. */
+ {"gotoff_g0_nc", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 16-31 of address/value: MOVZ. */
+ {"gotoff_g1", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_GOTOFF_G1,
+ 0,
+ 0,
+ 0},
+
/* 15 bit offset into the page containing GOT entry for that symbol. */
{"gotoff_lo15", 0,
0, /* adr_type */
BFD_RELOC_AARCH64_LD64_GOTOFF_LO15,
0},
+ /* Get to the page containing GOT TLS entry for a symbol */
+ {"gottprel_g0_nc", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Get to the page containing GOT TLS entry for a symbol */
+ {"gottprel_g1", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1,
+ 0,
+ 0,
+ 0},
+
/* Get to the page containing GOT TLS entry for a symbol */
{"tlsgd", 0,
BFD_RELOC_AARCH64_TLSGD_ADR_PREL21, /* adr_type */
0,
0},
+ /* Lower 16 bits address/value: MOVk. */
+ {"tlsgd_g0_nc", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 16-31 of address/value: MOVZ. */
+ {"tlsgd_g1", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSGD_MOVW_G1,
+ 0,
+ 0,
+ 0},
+
/* Get to the page containing GOT TLS entry for a symbol */
{"tlsdesc", 0,
BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21, /* adr_type */
0,
0,
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12,
- 0,
+ BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12,
0},
/* Same as dtprel_lo12, no overflow check. */
0,
0,
BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC,
- 0,
+ BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC,
0},
/* bits[23:12] of offset to the module TLS base address. */
0,
0},
+ /* Lower 16 bit offset into GOT entry for a symbol */
+ {"tlsdesc_off_g0_nc", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Higher 16 bit offset into GOT entry for a symbol */
+ {"tlsdesc_off_g1", 0,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_TLSDESC_OFF_G1,
+ 0,
+ 0,
+ 0},
+
/* Get to the page containing GOT TLS entry for a symbol */
{"gottprel", 0,
0, /* adr_type */
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);
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;
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.
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;
}
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)
/* 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;
/* 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:
case BFD_RELOC_AARCH64_MOVW_G0_S:
case BFD_RELOC_AARCH64_MOVW_G1_S:
case BFD_RELOC_AARCH64_MOVW_G2_S:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
case BFD_RELOC_AARCH64_MOVW_G0:
case BFD_RELOC_AARCH64_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G0_S:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
case BFD_RELOC_AARCH64_MOVW_G1:
case BFD_RELOC_AARCH64_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G1_S:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
static inline bfd_reloc_code_real_type
ldst_lo12_determine_real_reloc_type (void)
{
- int logsz;
+ unsigned logsz;
enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
enum aarch64_opnd_qualifier opd1_qlf = inst.base.operands[1].qualifier;
- const bfd_reloc_code_real_type reloc_ldst_lo12[5] = {
- BFD_RELOC_AARCH64_LDST8_LO12, BFD_RELOC_AARCH64_LDST16_LO12,
- BFD_RELOC_AARCH64_LDST32_LO12, BFD_RELOC_AARCH64_LDST64_LO12,
+ const bfd_reloc_code_real_type reloc_ldst_lo12[3][5] = {
+ {
+ BFD_RELOC_AARCH64_LDST8_LO12,
+ BFD_RELOC_AARCH64_LDST16_LO12,
+ BFD_RELOC_AARCH64_LDST32_LO12,
+ BFD_RELOC_AARCH64_LDST64_LO12,
BFD_RELOC_AARCH64_LDST128_LO12
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12,
+ BFD_RELOC_AARCH64_NONE
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
+ BFD_RELOC_AARCH64_NONE
+ }
};
- gas_assert (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12);
+ gas_assert (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC));
gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
if (opd1_qlf == AARCH64_OPND_QLF_NIL)
gas_assert (opd1_qlf != AARCH64_OPND_QLF_NIL);
logsz = get_logsz (aarch64_get_qualifier_esize (opd1_qlf));
- gas_assert (logsz >= 0 && logsz <= 4);
+ if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ gas_assert (logsz <= 3);
+ else
+ gas_assert (logsz <= 4);
- return reloc_ldst_lo12[logsz];
+ /* In reloc.c, these pseudo relocation types should be defined in similar
+ order as above reloc_ldst_lo12 array. Because the array index calcuation
+ below relies on this. */
+ return reloc_ldst_lo12[inst.reloc.type - BFD_RELOC_AARCH64_LDST_LO12][logsz];
}
/* Check whether a register list REGINFO is valid. The registers must be
}
if (inst.reloc.type == BFD_RELOC_UNUSED)
aarch64_set_gas_internal_fixup (&inst.reloc, info, 1);
- else if (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12)
+ else if (inst.reloc.type == BFD_RELOC_AARCH64_LDST_LO12
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC))
inst.reloc.type = ldst_lo12_determine_real_reloc_type ();
/* Leave qualifier to be determined by libopcodes. */
break;
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]);
}
case BFD_RELOC_AARCH64_MOVW_G0:
case BFD_RELOC_AARCH64_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G0_S:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
scale = 0;
goto movw_common;
case BFD_RELOC_AARCH64_MOVW_G1:
case BFD_RELOC_AARCH64_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G1_S:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
scale = 16;
goto movw_common;
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ scale = 0;
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ /* Should always be exported to object file, see
+ aarch64_force_relocation(). */
+ gas_assert (!fixP->fx_done);
+ gas_assert (seg->use_rela_p);
+ goto movw_common;
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
+ scale = 16;
+ S_SET_THREAD_LOCAL (fixP->fx_addsy);
+ /* Should always be exported to object file, see
+ aarch64_force_relocation(). */
+ gas_assert (!fixP->fx_done);
+ gas_assert (seg->use_rela_p);
+ goto movw_common;
case BFD_RELOC_AARCH64_MOVW_G2:
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G2_S:
case BFD_RELOC_AARCH64_MOVW_G1:
case BFD_RELOC_AARCH64_MOVW_G2:
case BFD_RELOC_AARCH64_MOVW_G3:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
if (unsigned_overflow (value, scale + 16))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("unsigned value out of range"));
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+ case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_OFF_G1:
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSGD_ADR_PREL21:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G0_NC:
+ case BFD_RELOC_AARCH64_TLSGD_MOVW_G1:
case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
- case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+ case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_HI12:
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12:
case BFD_RELOC_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSLD_ADR_PREL21:
+ case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
const char *
elf64_aarch64_target_format (void)
{
+ if (strcmp (TARGET_OS, "cloudabi") == 0)
+ {
+ /* FIXME: What to do for ilp32_p ? */
+ return target_big_endian ? "elf64-bigaarch64-cloudabi" : "elf64-littleaarch64-cloudabi";
+ }
if (target_big_endian)
return ilp32_p ? "elf32-bigaarch64" : "elf64-bigaarch64";
else
|| (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 ();
aarch64_pstatefields[i].name,
(void *) (aarch64_pstatefields + i));
- for (i = 0; aarch64_sys_regs_ic[i].template != NULL; i++)
+ for (i = 0; aarch64_sys_regs_ic[i].name != NULL; i++)
checked_hash_insert (aarch64_sys_regs_ic_hsh,
- aarch64_sys_regs_ic[i].template,
+ aarch64_sys_regs_ic[i].name,
(void *) (aarch64_sys_regs_ic + i));
- for (i = 0; aarch64_sys_regs_dc[i].template != NULL; i++)
+ for (i = 0; aarch64_sys_regs_dc[i].name != NULL; i++)
checked_hash_insert (aarch64_sys_regs_dc_hsh,
- aarch64_sys_regs_dc[i].template,
+ aarch64_sys_regs_dc[i].name,
(void *) (aarch64_sys_regs_dc + i));
- for (i = 0; aarch64_sys_regs_at[i].template != NULL; i++)
+ for (i = 0; aarch64_sys_regs_at[i].name != NULL; i++)
checked_hash_insert (aarch64_sys_regs_at_hsh,
- aarch64_sys_regs_at[i].template,
+ aarch64_sys_regs_at[i].name,
(void *) (aarch64_sys_regs_at + i));
- for (i = 0; aarch64_sys_regs_tlbi[i].template != NULL; i++)
+ for (i = 0; aarch64_sys_regs_tlbi[i].name != NULL; i++)
checked_hash_insert (aarch64_sys_regs_tlbi_hsh,
- aarch64_sys_regs_tlbi[i].template,
+ aarch64_sys_regs_tlbi[i].name,
(void *) (aarch64_sys_regs_tlbi + i));
for (i = 0; i < ARRAY_SIZE (reg_names); i++)
(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;
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. */
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. */
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,
{"exynos-m1", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
"Samsung Exynos M1"},
+ {"qdf24xx", AARCH64_FEATURE (AARCH64_ARCH_V8,
+ AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
+ "Qualcomm QDF24XX"},
{"thunderx", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
"Cavium ThunderX"},
struct aarch64_arch_option_table
{
- char *name;
+ const char *name;
const aarch64_feature_set value;
};
{"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;
};
{"lor", AARCH64_FEATURE (AARCH64_FEATURE_LOR, 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
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)
}
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)
}
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)
/* ABIs. */
struct aarch64_option_abi_value_table
{
- char *name;
+ const char *name;
enum aarch64_abi_type value;
};
};
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);
};
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;