/* tc-aarch64.c -- Assemble for the AArch64 ISA
- Copyright (C) 2009-2016 Free Software Foundation, Inc.
+ Copyright (C) 2009-2018 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of GAS.
/* Which ABI to use. */
enum aarch64_abi_type
{
- AARCH64_ABI_LP64 = 0,
- AARCH64_ABI_ILP32 = 1
+ AARCH64_ABI_NONE = 0,
+ AARCH64_ABI_LP64 = 1,
+ AARCH64_ABI_ILP32 = 2
};
+#ifndef DEFAULT_ARCH
+#define DEFAULT_ARCH "aarch64"
+#endif
+
+/* DEFAULT_ARCH is initialized in gas/configure.tgt. */
+static const char *default_arch = DEFAULT_ARCH;
+
/* AArch64 ABI for the output file. */
-static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_LP64;
+static enum aarch64_abi_type aarch64_abi = AARCH64_ABI_NONE;
/* When non-zero, program to a 32-bit model, in which the C data types
int, long and all pointer types are 32-bit objects (ILP32); or to a
static bfd_boolean parse_operands (char *, const aarch64_opcode *);
static bfd_boolean programmer_friendly_fixup (aarch64_instruction *);
-/* Diagnostics inline function utilites.
+/* Diagnostics inline function utilities.
- These are lightweight utlities which should only be called by parse_operands
+ These are lightweight utilities which should only be called by parse_operands
and other parsers. GAS processes each assembly line by parsing it against
instruction template(s), in the case of multiple templates (for the same
mnemonic name), those templates are tried one by one until one succeeds or
the parsing; we don't want to slow down the whole parsing by recording
non-user errors in detail.
- Remember that the objective is to help GAS pick up the most approapriate
+ Remember that the objective is to help GAS pick up the most appropriate
error message in the case of multiple templates, e.g. FMOV which has 8
templates. */
BASIC_REG_TYPE(FP_S) /* s[0-31] */ \
BASIC_REG_TYPE(FP_D) /* d[0-31] */ \
BASIC_REG_TYPE(FP_Q) /* q[0-31] */ \
- BASIC_REG_TYPE(CN) /* c[0-7] */ \
BASIC_REG_TYPE(VN) /* v[0-31] */ \
BASIC_REG_TYPE(ZN) /* z[0-31] */ \
BASIC_REG_TYPE(PN) /* p[0-15] */ \
| REG_TYPE(Z_32) | REG_TYPE(Z_64) | REG_TYPE(VN) \
| REG_TYPE(FP_B) | REG_TYPE(FP_H) \
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q)) \
- /* Typecheck: as above, but also Zn and Pn. This should only be \
- used for SVE instructions, since Zn and Pn are valid symbols \
+ /* Typecheck: as above, but also Zn, Pn, and {W}SP. This should only \
+ be used for SVE instructions, since Zn and Pn are valid symbols \
in other contexts. */ \
- MULTI_REG_TYPE(R_Z_BHSDQ_VZP, REG_TYPE(R_32) | REG_TYPE(R_64) \
+ MULTI_REG_TYPE(R_Z_SP_BHSDQ_VZP, REG_TYPE(R_32) | REG_TYPE(R_64) \
+ | REG_TYPE(SP_32) | REG_TYPE(SP_64) \
| REG_TYPE(Z_32) | REG_TYPE(Z_64) | REG_TYPE(VN) \
| REG_TYPE(FP_B) | REG_TYPE(FP_H) \
| REG_TYPE(FP_S) | REG_TYPE(FP_D) | REG_TYPE(FP_Q) \
msg = N_("128-bit SIMD scalar or floating-point quad precision "
"register expected");
break;
- case REG_TYPE_CN:
- msg = N_("C0 - C15 expected");
- break;
case REG_TYPE_R_Z_BHSDQ_V:
- case REG_TYPE_R_Z_BHSDQ_VZP:
+ case REG_TYPE_R_Z_SP_BHSDQ_VZP:
msg = N_("register expected");
break;
case REG_TYPE_BHSDQ: /* any [BHSDQ]P FP */
set_syntax_error (error);
}
-/* Similiar to first_error, but this function accepts formatted error
+/* Similar to first_error, but this function accepts formatted error
message. */
static void
first_error_fmt (const char *format, ...)
succeeds; otherwise return FALSE.
Accept only one occurrence of:
- 8b 16b 2h 4h 8h 2s 4s 1d 2d
+ 4b 8b 16b 2h 4h 8h 2s 4s 1d 2d
b h s d q */
static bfd_boolean
parse_vector_type_for_operand (aarch64_reg_type reg_type,
element_size = 64;
break;
case 'q':
- if (width == 1)
+ if (reg_type == REG_TYPE_ZN || width == 1)
{
type = NT_q;
element_size = 128;
first_error (_("missing element size"));
return FALSE;
}
- if (width != 0 && width * element_size != 64 && width * element_size != 128
- && !(width == 2 && element_size == 16))
+ if (width != 0 && width * element_size != 64
+ && width * element_size != 128
+ && !(width == 2 && element_size == 16)
+ && !(width == 4 && element_size == 8))
{
first_error_fmt (_
("invalid element size %d and vector size combination %c"),
/* Expect index. In the new scheme we cannot have
Vn.[bhsdq] represent a scalar. Therefore any
Vn.[bhsdq] should have an index following it.
- Except in reglists ofcourse. */
+ Except in reglists of course. */
atype.defined |= NTA_HASINDEX;
else
atype.defined |= NTA_HASTYPE;
return PARSE_FAIL;
}
- if (in_reg_list == TRUE)
+ if (in_reg_list)
{
first_error (_("index not allowed inside register list"));
return PARSE_FAIL;
}
/* Can't use symbol_new here, so have to create a symbol and then at
- a later date assign it a value. Thats what these functions do. */
+ a later date assign it a value. That's what these functions do. */
static void
symbol_locate (symbolS * symbolP,
char *str = *ccp;
char *fpnum;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
- int found_fpchar = 0;
int64_t val = 0;
unsigned fpword = 0;
bfd_boolean hex_p = FALSE;
hex_p = TRUE;
}
- else
- {
- if (reg_name_p (str, reg_type))
- {
- set_recoverable_error (_("immediate operand required"));
- return FALSE;
- }
-
- /* We must not accidentally parse an integer as a floating-point number.
- Make sure that the value we parse is not an integer by checking for
- special characters '.' or 'e'. */
- for (; *fpnum != '\0' && *fpnum != ' ' && *fpnum != '\n'; fpnum++)
- if (*fpnum == '.' || *fpnum == 'e' || *fpnum == 'E')
- {
- found_fpchar = 1;
- break;
- }
-
- if (!found_fpchar)
- return FALSE;
+ else if (reg_name_p (str, reg_type))
+ {
+ set_recoverable_error (_("immediate operand required"));
+ return FALSE;
}
if (! hex_p)
return inst.reloc.type == BFD_RELOC_AARCH64_GAS_INTERNAL_FIXUP;
}
-/* Assign the immediate value to the relavant field in *OPERAND if
+/* Assign the immediate value to the relevant field in *OPERAND if
RELOC->EXP is a constant expression; otherwise, flag that *OPERAND
needs an internal fixup in a later stage.
ADDR_OFF_P determines whether it is the field ADDR.OFFSET.IMM or
0,
0},
+ /* Most significant bits 0-15 of signed/unsigned address/value: MOVZ */
+ {"prel_g0", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G0,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 0-15 of signed/unsigned address/value: MOVK */
+ {"prel_g0_nc", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G0_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 16-31 of signed/unsigned address/value: MOVZ */
+ {"prel_g1", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G1,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 16-31 of signed/unsigned address/value: MOVK */
+ {"prel_g1_nc", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G1_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 32-47 of signed/unsigned address/value: MOVZ */
+ {"prel_g2", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G2,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 32-47 of signed/unsigned address/value: MOVK */
+ {"prel_g2_nc", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G2_NC,
+ 0,
+ 0,
+ 0},
+
+ /* Most significant bits 48-63 of signed/unsigned address/value: MOVZ */
+ {"prel_g3", 1,
+ 0, /* adr_type */
+ 0,
+ BFD_RELOC_AARCH64_MOVW_PREL_G3,
+ 0,
+ 0,
+ 0},
+
/* Get to the page containing GOT entry for a symbol. */
{"got", 1,
0, /* adr_type */
0, /* adr_type */
0,
0,
- BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC,
+ BFD_RELOC_AARCH64_TLSDESC_ADD_LO12,
BFD_RELOC_AARCH64_TLSDESC_LD_LO12_NC,
0},
/* Get to the page containing GOT TLS entry for a symbol.
The same as GD, we allocate two consecutive GOT slots
for module index and module offset, the only difference
- with GD is the module offset should be intialized to
+ with GD is the module offset should be initialized to
zero without any outstanding runtime relocation. */
{"tlsldm", 0,
BFD_RELOC_AARCH64_TLSLD_ADR_PREL21, /* adr_type */
0,
0,
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12,
- 0,
+ BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12,
0},
/* Get tp offset for a symbol. */
0,
0,
BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC,
- 0,
+ BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC,
0},
/* Most significant bits 32-47 of address/value: MOVZ. */
switch (mode)
{
case SHIFTED_LOGIC_IMM:
- if (aarch64_extend_operator_p (kind) == TRUE)
+ if (aarch64_extend_operator_p (kind))
{
set_syntax_error (_("extending shift is not permitted"));
return FALSE;
operand->shifter.amount = 1;
else if (exp.X_op == O_absent)
{
- if (aarch64_extend_operator_p (kind) == FALSE || exp_has_prefix)
+ if (!aarch64_extend_operator_p (kind) || exp_has_prefix)
{
set_syntax_error (_("missing shift amount"));
return FALSE;
set_syntax_error (_("missing offset in the pre-indexed address"));
return FALSE;
}
+
operand->addr.preind = 1;
inst.reloc.exp.X_op = O_constant;
inst.reloc.exp.X_add_number = 0;
instruction->reloc.type = BFD_RELOC_UNUSED;
}
-/* Data strutures storing one user error in the assembly code related to
+/* Data structures storing one user error in the assembly code related to
operands. */
struct operand_error_record
const aarch64_opnd_qualifier_t *qualifiers = *qualifiers_list;
/* Most opcodes has much fewer patterns in the list. */
- if (empty_qualifier_sequence_p (qualifiers) == TRUE)
+ if (empty_qualifier_sequence_p (qualifiers))
{
DEBUG_TRACE_IF (i == 0, "empty list of qualifier sequence");
break;
return idx;
}
-/* Assign qualifiers in the qualifier seqence (headed by QUALIFIERS) to the
+/* Assign qualifiers in the qualifier sequence (headed by QUALIFIERS) to the
corresponding operands in *INSTR. */
static inline void
{
/* Most opcodes has much fewer patterns in the list.
First NIL qualifier indicates the end in the list. */
- if (empty_qualifier_sequence_p (*qualifiers_list) == TRUE)
+ if (empty_qualifier_sequence_p (*qualifiers_list))
break;
if (i != qlf_idx)
When this function is called, the operand error information had
been collected for an assembly line and there will be multiple
- errors in the case of mulitple instruction templates; output the
+ errors in the case of multiple instruction templates; output the
error message that most closely describes the problem. */
static void
}
/* Find the error kind of the highest severity. */
- DEBUG_TRACE ("multiple opcode entres with error kind");
+ DEBUG_TRACE ("multiple opcode entries with error kind");
kind = AARCH64_OPDE_NIL;
for (curr = head; curr != NULL; curr = curr->next)
{
= {1, 2, 4, 8, 16};
const unsigned int ele_base [5] =
{
- AARCH64_OPND_QLF_V_8B,
+ AARCH64_OPND_QLF_V_4B,
AARCH64_OPND_QLF_V_2H,
AARCH64_OPND_QLF_V_2S,
AARCH64_OPND_QLF_V_1D,
gas_assert (vectype->type >= NT_b && vectype->type <= NT_q);
if (vectype->defined & (NTA_HASINDEX | NTA_HASVARWIDTH))
- /* Vector element register. */
- return AARCH64_OPND_QLF_S_B + vectype->type;
+ {
+ /* Special case S_4B. */
+ if (vectype->type == NT_b && vectype->width == 4)
+ return AARCH64_OPND_QLF_S_4B;
+
+ /* Vector element register. */
+ return AARCH64_OPND_QLF_S_B + vectype->type;
+ }
else
{
/* Vector register. */
a vector-type dependent amount. */
shift = 0;
if (vectype->type == NT_b)
- shift = 4;
+ shift = 3;
else if (vectype->type == NT_h || vectype->type == NT_s)
shift = 2;
else if (vectype->type >= NT_d)
gas_assert (0);
offset = ele_base [vectype->type] + (vectype->width >> shift);
- gas_assert (AARCH64_OPND_QLF_V_8B <= offset
+ gas_assert (AARCH64_OPND_QLF_V_4B <= offset
&& offset <= AARCH64_OPND_QLF_V_1Q);
return offset;
}
case AARCH64_OPND_Sd:
case AARCH64_OPND_Sn:
case AARCH64_OPND_Sm:
+ case AARCH64_OPND_Va:
case AARCH64_OPND_Vd:
case AARCH64_OPND_Vn:
case AARCH64_OPND_Vm:
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
case AARCH64_OPND_Em:
+ case AARCH64_OPND_SM3_IMM2:
operand->reglane.regno = default_value;
break;
case AARCH64_OPND_UIMM3_OP1:
case AARCH64_OPND_UIMM3_OP2:
case AARCH64_OPND_IMM:
+ case AARCH64_OPND_IMM_2:
case AARCH64_OPND_WIDTH:
case AARCH64_OPND_UIMM7:
case AARCH64_OPND_NZCV:
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_MOVW_PREL_G0:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G2:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G3:
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_MOVW_G0_NC:
case BFD_RELOC_AARCH64_MOVW_G0_S:
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G0:
+ case BFD_RELOC_AARCH64_MOVW_PREL_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_MOVW_G1_NC:
case BFD_RELOC_AARCH64_MOVW_G1_S:
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
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_MOVW_G2:
case BFD_RELOC_AARCH64_MOVW_G2_NC:
case BFD_RELOC_AARCH64_MOVW_G2_S:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G2:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
if (is32)
shift = 32;
break;
case BFD_RELOC_AARCH64_MOVW_G3:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G3:
if (is32)
{
set_fatal_syntax_error
return TRUE;
}
-/* A primitive log caculator. */
+/* A primitive log calculator. */
static inline unsigned int
get_logsz (unsigned int size)
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[3][5] = {
+ const bfd_reloc_code_real_type reloc_ldst_lo12[5][5] = {
{
BFD_RELOC_AARCH64_LDST8_LO12,
BFD_RELOC_AARCH64_LDST16_LO12,
BFD_RELOC_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC,
BFD_RELOC_AARCH64_NONE
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12,
+ BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12,
+ BFD_RELOC_AARCH64_NONE
+ },
+ {
+ BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC,
+ BFD_RELOC_AARCH64_NONE
}
};
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));
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC));
gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
if (opd1_qlf == AARCH64_OPND_QLF_NIL)
logsz = get_logsz (aarch64_get_qualifier_esize (opd1_qlf));
if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
- || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12
+ || inst.reloc.type == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC)
gas_assert (logsz <= 3);
else
gas_assert (logsz <= 4);
/* In reloc.c, these pseudo relocation types should be defined in similar
- order as above reloc_ldst_lo12 array. Because the array index calcuation
+ order as above reloc_ldst_lo12 array. Because the array index calculation
below relies on this. */
return reloc_ldst_lo12[inst.reloc.type - BFD_RELOC_AARCH64_LDST_LO12][logsz];
}
skip_whitespace (str);
if (AARCH64_CPU_HAS_FEATURE (AARCH64_FEATURE_SVE, *opcode->avariant))
- imm_reg_type = REG_TYPE_R_Z_BHSDQ_VZP;
+ imm_reg_type = REG_TYPE_R_Z_SP_BHSDQ_VZP;
else
imm_reg_type = REG_TYPE_R_Z_BHSDQ_V;
backtrack_pos = str;
}
- /* Expect comma between operands; the backtrack mechanizm will take
+ /* Expect comma between operands; the backtrack mechanism will take
care of cases of omitted optional operand. */
if (i > 0 && ! skip_past_char (&str, ','))
{
reg_type = REG_TYPE_ZN;
goto vector_reg;
+ case AARCH64_OPND_Va:
case AARCH64_OPND_Vd:
case AARCH64_OPND_Vn:
case AARCH64_OPND_Vm:
info->qualifier = AARCH64_OPND_QLF_S_D;
break;
+ case AARCH64_OPND_SVE_Zm3_INDEX:
+ case AARCH64_OPND_SVE_Zm3_22_INDEX:
+ case AARCH64_OPND_SVE_Zm4_INDEX:
case AARCH64_OPND_SVE_Zn_INDEX:
reg_type = REG_TYPE_ZN;
goto vector_reg_index;
case AARCH64_OPND_Ed:
case AARCH64_OPND_En:
case AARCH64_OPND_Em:
+ case AARCH64_OPND_SM3_IMM2:
reg_type = REG_TYPE_VN;
vector_reg_index:
val = aarch64_reg_parse (&str, reg_type, NULL, &vectype);
goto failure;
break;
- case AARCH64_OPND_Cn:
- case AARCH64_OPND_Cm:
- po_reg_or_fail (REG_TYPE_CN);
- if (val > 15)
+ case AARCH64_OPND_CRn:
+ case AARCH64_OPND_CRm:
{
- set_fatal_syntax_error (_(get_reg_expected_msg (REG_TYPE_CN)));
- goto failure;
+ char prefix = *(str++);
+ if (prefix != 'c' && prefix != 'C')
+ goto failure;
+
+ po_imm_nc_or_fail ();
+ if (val > 15)
+ {
+ set_fatal_syntax_error (_(N_ ("C0 - C15 expected")));
+ goto failure;
+ }
+ info->qualifier = AARCH64_OPND_QLF_CR;
+ info->imm.value = val;
+ break;
}
- inst.base.operands[i].reg.regno = val;
- break;
case AARCH64_OPND_SHLL_IMM:
case AARCH64_OPND_IMM_VLSR:
case AARCH64_OPND_UIMM3_OP2:
case AARCH64_OPND_IMM_VLSL:
case AARCH64_OPND_IMM:
+ case AARCH64_OPND_IMM_2:
case AARCH64_OPND_WIDTH:
case AARCH64_OPND_SVE_INV_LIMM:
case AARCH64_OPND_SVE_LIMM:
case AARCH64_OPND_SVE_UIMM7:
case AARCH64_OPND_SVE_UIMM8:
case AARCH64_OPND_SVE_UIMM8_53:
+ case AARCH64_OPND_IMM_ROT1:
+ case AARCH64_OPND_IMM_ROT2:
+ case AARCH64_OPND_IMM_ROT3:
+ case AARCH64_OPND_SVE_IMM_ROT1:
+ case AARCH64_OPND_SVE_IMM_ROT2:
po_imm_nc_or_fail ();
info->imm.value = val;
break;
break;
case AARCH64_OPND_IDX:
+ case AARCH64_OPND_MASK:
case AARCH64_OPND_BIT_NUM:
case AARCH64_OPND_IMMR:
case AARCH64_OPND_IMMS:
break;
case AARCH64_OPND_ADDR_SIMM10:
+ case AARCH64_OPND_ADDR_OFFSET:
po_misc_or_fail (parse_address (&str, info));
if (info->addr.pcrel || info->addr.offset.is_reg
|| !info->addr.preind || info->addr.postind)
|| (inst.reloc.type
== BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12)
|| (inst.reloc.type
- == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC))
+ == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12)
+ || (inst.reloc.type
+ == BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC))
inst.reloc.type = ldst_lo12_determine_real_reloc_type ();
/* Leave qualifier to be determined by libopcodes. */
break;
/* No qualifier. */
break;
+ case AARCH64_OPND_SVE_ADDR_RI_S4x16:
case AARCH64_OPND_SVE_ADDR_RI_S4xVL:
case AARCH64_OPND_SVE_ADDR_RI_S4x2xVL:
case AARCH64_OPND_SVE_ADDR_RI_S4x3xVL:
info->addr.offset.imm = inst.reloc.exp.X_add_number;
break;
+ case AARCH64_OPND_SVE_ADDR_R:
+ /* [<Xn|SP>{, <R><m>}]
+ but recognizing SVE registers. */
+ po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
+ &offset_qualifier));
+ if (offset_qualifier == AARCH64_OPND_QLF_NIL)
+ {
+ offset_qualifier = AARCH64_OPND_QLF_X;
+ info->addr.offset.is_reg = 1;
+ info->addr.offset.regno = 31;
+ }
+ else if (base_qualifier != AARCH64_OPND_QLF_X
+ || offset_qualifier != AARCH64_OPND_QLF_X)
+ {
+ set_syntax_error (_("invalid addressing mode"));
+ goto failure;
+ }
+ goto regoff_addr;
+
case AARCH64_OPND_SVE_ADDR_RR:
case AARCH64_OPND_SVE_ADDR_RR_LSL1:
case AARCH64_OPND_SVE_ADDR_RR_LSL2:
also have mixed-case names. */
#define REGDEF(s,n,t) { #s, n, REG_TYPE_##t, TRUE }
+#define REGDEF_ALIAS(s, n, t) { #s, n, REG_TYPE_##t, FALSE}
#define REGNUM(p,n,t) REGDEF(p##n, n, t)
#define REGSET16(p,t) \
REGNUM(p, 0,t), REGNUM(p, 1,t), REGNUM(p, 2,t), REGNUM(p, 3,t), \
REGSET31 (x, R_64), REGSET31 (X, R_64),
REGSET31 (w, R_32), REGSET31 (W, R_32),
+ REGDEF_ALIAS (ip0, 16, R_64), REGDEF_ALIAS (IP0, 16, R_64),
+ REGDEF_ALIAS (ip1, 17, R_64), REGDEF_ALIAS (IP1, 17, R_64),
+ REGDEF_ALIAS (fp, 29, R_64), REGDEF_ALIAS (FP, 29, R_64),
+ REGDEF_ALIAS (lr, 30, R_64), REGDEF_ALIAS (LR, 30, R_64),
REGDEF (wsp, 31, SP_32), REGDEF (WSP, 31, SP_32),
REGDEF (sp, 31, SP_64), REGDEF (SP, 31, SP_64),
REGDEF (wzr, 31, Z_32), REGDEF (WZR, 31, Z_32),
REGDEF (xzr, 31, Z_64), REGDEF (XZR, 31, Z_64),
- /* Coprocessor register numbers. */
- REGSET (c, CN), REGSET (C, CN),
-
/* Floating-point single precision registers. */
REGSET (s, FP_S), REGSET (S, FP_S),
};
#undef REGDEF
+#undef REGDEF_ALIAS
#undef REGNUM
#undef REGSET16
#undef REGSET31
Note - despite the name this initialisation is not done when the frag
is created, but only when its type is assigned. A frag can be created
and used a long time before its type is set, so beware of assuming that
- this initialisationis performed first. */
+ this initialisation is performed first. */
#ifndef OBJ_ELF
void
if (!fragP->tc_frag_data.recorded)
fragP->tc_frag_data.recorded = 1;
+ /* PR 21809: Do not set a mapping state for debug sections
+ - it just confuses other tools. */
+ if (bfd_get_section_flags (NULL, now_seg) & SEC_DEBUGGING)
+ return;
+
switch (fragP->fr_type)
{
case rs_align_test:
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_MOVW_PREL_G0:
+ case BFD_RELOC_AARCH64_MOVW_PREL_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:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1_NC:
scale = 16;
goto movw_common;
case BFD_RELOC_AARCH64_TLSDESC_OFF_G0_NC:
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_PREL_G2:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G2_NC:
scale = 32;
goto movw_common;
case BFD_RELOC_AARCH64_MOVW_G3:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G3:
scale = 48;
movw_common:
if (fixP->fx_done || !seg->use_rela_p)
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_MOVW_PREL_G0:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G1:
+ case BFD_RELOC_AARCH64_MOVW_PREL_G2:
/* NOTE: We can only come here with movz or movn. */
if (signed_overflow (value, scale + 16))
as_bad_where (fixP->fx_file, fixP->fx_line,
case BFD_RELOC_AARCH64_TLSDESC_LD_LO12_NC:
fixP->fx_r_type = (ilp32_p
? BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC
- : BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC);
+ : BFD_RELOC_AARCH64_TLSDESC_LD64_LO12);
S_SET_THREAD_LOCAL (fixP->fx_addsy);
/* Should always be exported to object file, see
aarch64_force_relocation(). */
gas_assert (seg->use_rela_p);
break;
- case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
- case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
case BFD_RELOC_AARCH64_TLSDESC_LD_PREL19:
case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_LDST32_LO12:
case BFD_RELOC_AARCH64_LDST64_LO12:
case BFD_RELOC_AARCH64_LDST8_LO12:
- case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
case BFD_RELOC_AARCH64_TLSDESC_ADR_PREL21:
case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
- case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12:
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_TLSLD_MOVW_DTPREL_G1:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G1_NC:
case BFD_RELOC_AARCH64_TLSLD_MOVW_DTPREL_G2:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12:
+ case BFD_RELOC_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
#ifdef OBJ_ELF
+/* Implement md_after_parse_args. This is the earliest time we need to decide
+ ABI. If no -mabi specified, the ABI will be decided by target triplet. */
+
+void
+aarch64_after_parse_args (void)
+{
+ if (aarch64_abi != AARCH64_ABI_NONE)
+ return;
+
+ /* DEFAULT_ARCH will have ":32" extension if it's configured for ILP32. */
+ if (strlen (default_arch) > 7 && strcmp (default_arch + 7, ":32") == 0)
+ aarch64_abi = AARCH64_ABI_ILP32;
+ else
+ aarch64_abi = AARCH64_ABI_LP64;
+}
+
const char *
elf64_aarch64_target_format (void)
{
AARCH64_FEATURE_CRC), "Cortex-A72"},
{"cortex-a73", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC), "Cortex-A73"},
+ {"cortex-a55", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+ AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
+ "Cortex-A55"},
+ {"cortex-a75", AARCH64_FEATURE (AARCH64_ARCH_V8_2,
+ AARCH64_FEATURE_RCPC | AARCH64_FEATURE_F16 | AARCH64_FEATURE_DOTPROD),
+ "Cortex-A75"},
{"exynos-m1", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
"Samsung Exynos M1"},
{"falkor", AARCH64_FEATURE (AARCH64_ARCH_V8,
- AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
+ AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
+ | AARCH64_FEATURE_RDMA),
"Qualcomm Falkor"},
{"qdf24xx", AARCH64_FEATURE (AARCH64_ARCH_V8,
- AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
+ AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO
+ | AARCH64_FEATURE_RDMA),
"Qualcomm QDF24XX"},
+ {"saphira", AARCH64_FEATURE (AARCH64_ARCH_V8_3,
+ AARCH64_FEATURE_CRYPTO | AARCH64_FEATURE_PROFILE),
+ "Qualcomm Saphira"},
{"thunderx", AARCH64_FEATURE (AARCH64_ARCH_V8,
AARCH64_FEATURE_CRC | AARCH64_FEATURE_CRYPTO),
"Cavium ThunderX"},
{"armv8.1-a", AARCH64_ARCH_V8_1},
{"armv8.2-a", AARCH64_ARCH_V8_2},
{"armv8.3-a", AARCH64_ARCH_V8_3},
+ {"armv8.4-a", AARCH64_ARCH_V8_4},
{NULL, AARCH64_ARCH_NONE}
};
static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"crc", AARCH64_FEATURE (AARCH64_FEATURE_CRC, 0),
AARCH64_ARCH_NONE},
- {"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO, 0),
+ {"crypto", AARCH64_FEATURE (AARCH64_FEATURE_CRYPTO
+ | AARCH64_FEATURE_AES
+ | AARCH64_FEATURE_SHA2, 0),
AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
{"fp", AARCH64_FEATURE (AARCH64_FEATURE_FP, 0),
AARCH64_ARCH_NONE},
AARCH64_FEATURE (AARCH64_FEATURE_SIMD, 0)},
{"fp16", AARCH64_FEATURE (AARCH64_FEATURE_F16, 0),
AARCH64_FEATURE (AARCH64_FEATURE_FP, 0)},
+ {"fp16fml", AARCH64_FEATURE (AARCH64_FEATURE_F16_FML, 0),
+ AARCH64_FEATURE (AARCH64_FEATURE_FP
+ | AARCH64_FEATURE_F16, 0)},
{"profile", AARCH64_FEATURE (AARCH64_FEATURE_PROFILE, 0),
AARCH64_ARCH_NONE},
{"sve", AARCH64_FEATURE (AARCH64_FEATURE_SVE, 0),
- AARCH64_FEATURE (AARCH64_FEATURE_FP
+ AARCH64_FEATURE (AARCH64_FEATURE_F16
+ | AARCH64_FEATURE_SIMD
+ | AARCH64_FEATURE_COMPNUM, 0)},
+ {"compnum", AARCH64_FEATURE (AARCH64_FEATURE_COMPNUM, 0),
+ AARCH64_FEATURE (AARCH64_FEATURE_F16
| AARCH64_FEATURE_SIMD, 0)},
+ {"rcpc", AARCH64_FEATURE (AARCH64_FEATURE_RCPC, 0),
+ AARCH64_ARCH_NONE},
+ {"dotprod", AARCH64_FEATURE (AARCH64_FEATURE_DOTPROD, 0),
+ AARCH64_ARCH_NONE},
+ {"sha2", AARCH64_FEATURE (AARCH64_FEATURE_SHA2, 0),
+ AARCH64_ARCH_NONE},
+ {"aes", AARCH64_FEATURE (AARCH64_FEATURE_AES, 0),
+ AARCH64_ARCH_NONE},
+ {"sm4", AARCH64_FEATURE (AARCH64_FEATURE_SM4, 0),
+ AARCH64_ARCH_NONE},
+ {"sha3", AARCH64_FEATURE (AARCH64_FEATURE_SHA2
+ | AARCH64_FEATURE_SHA3, 0),
+ AARCH64_ARCH_NONE},
{NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
};