aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-aarch64.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/tc-aarch64.c')
-rw-r--r--gas/config/tc-aarch64.c353
1 files changed, 233 insertions, 120 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index e071ad1..96bfe74 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -907,7 +907,7 @@ parse_reg (char **ccp)
p++;
while (ISALPHA (*p) || ISDIGIT (*p) || *p == '_');
- reg = (reg_entry *) str_hash_find_n (aarch64_reg_hsh, start, p - start);
+ reg = str_hash_find_n (aarch64_reg_hsh, start, p - start);
if (!reg)
return NULL;
@@ -2351,6 +2351,14 @@ s_aarch64_cfi_b_key_frame (int ignored ATTRIBUTE_UNUSED)
fde->pauth_key = AARCH64_PAUTH_KEY_B;
}
+static void
+s_aarch64_mte_tagged_frame (int ignored ATTRIBUTE_UNUSED)
+{
+ demand_empty_rest_of_line ();
+ struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
+ fde->memtag_frame_p = true;
+}
+
#ifdef OBJ_ELF
/* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction. */
@@ -2476,6 +2484,7 @@ const pseudo_typeS md_pseudo_table[] = {
{"arch_extension", s_aarch64_arch_extension, 0},
{"inst", s_aarch64_inst, 0},
{"cfi_b_key_frame", s_aarch64_cfi_b_key_frame, 0},
+ {"cfi_mte_tagged_frame", s_aarch64_mte_tagged_frame, 0},
#ifdef OBJ_ELF
{"tlsdescadd", s_tlsdescadd, 0},
{"tlsdesccall", s_tlsdesccall, 0},
@@ -4607,7 +4616,9 @@ parse_hint_opt (const char *name, char **str,
&& o->value != HINT_OPD_CSYNC)
|| ((strcmp ("bti", name) == 0)
&& (o->value != HINT_OPD_C && o->value != HINT_OPD_J
- && o->value != HINT_OPD_JC)))
+ && o->value != HINT_OPD_JC))
+ || ((strcmp ("stshh", name) == 0)
+ && (o->value != HINT_OPD_KEEP && o->value != HINT_OPD_STRM)))
return false;
*str = q;
@@ -4954,6 +4965,10 @@ parse_sme_sm_za (char **str)
return TOLOWER (p[0]);
}
+/* By default, system register accesses are unguarded (apart from the
+ requirement of +d128 for mrrs/msrr). */
+static int sysreg_checking_p = 0;
+
/* Parse a system register or a PSTATE field name for an MSR/MRS instruction.
Returns the encoding for the option, or PARSE_FAIL.
@@ -5008,10 +5023,11 @@ parse_sys_reg (char **str, htab_t sys_regs,
}
else
{
- if (pstatefield_p && !aarch64_pstatefield_supported_p (cpu_variant, o))
+ if (pstatefield_p && sysreg_checking_p
+ && !aarch64_pstatefield_supported_p (cpu_variant, o))
as_bad (_("selected processor does not support PSTATE field "
"name '%s'"), buf);
- if (!pstatefield_p
+ if (!pstatefield_p && sysreg_checking_p
&& !aarch64_sys_ins_reg_supported_p (cpu_variant, o->name,
o->flags, &o->features))
as_bad (_("selected processor does not support system register "
@@ -5092,12 +5108,14 @@ parse_sys_ins_reg (char **str, htab_t sys_ins_regs, bool sysreg128_p)
} while (0)
#define po_imm_nc_or_fail() do { \
- if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
+ aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
+ if (! parse_constant_immediate (&str, &val, invalid_types)) \
goto failure; \
} while (0)
#define po_imm_or_fail(min, max) do { \
- if (! parse_constant_immediate (&str, &val, imm_reg_type)) \
+ aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
+ if (! parse_constant_immediate (&str, &val, invalid_types)) \
goto failure; \
if (val < min || val > max) \
{ \
@@ -5108,8 +5126,9 @@ parse_sys_ins_reg (char **str, htab_t sys_ins_regs, bool sysreg128_p)
} while (0)
#define po_enum_or_fail(array) do { \
+ aarch64_reg_type invalid_types = imm_invalid_reg_types (opcode->flags); \
if (!parse_enum_string (&str, &val, array, \
- ARRAY_SIZE (array), imm_reg_type)) \
+ ARRAY_SIZE (array), invalid_types)) \
goto failure; \
} while (0)
@@ -5175,6 +5194,13 @@ encode_branch_ofs_26 (uint32_t ofs)
return ofs & ((1 << 26) - 1);
}
+/* encode the 9-bit offset of FEAT_CMPBR compare and branch */
+static inline uint32_t
+encode_cond_branch_ofs_9 (uint32_t ofs)
+{
+ return (ofs & ((1 << 9) - 1)) << 5;
+}
+
/* encode the 19-bit offset of conditional branch and compare & branch */
static inline uint32_t
encode_cond_branch_ofs_19 (uint32_t ofs)
@@ -5615,7 +5641,7 @@ static const char *aarch64_apply_style
{
int res;
char *ptr;
- struct obstack *stack = (struct obstack *) styler->state;
+ struct obstack *stack = styler->state;
va_list ap;
/* Calculate the required space. */
@@ -5625,7 +5651,7 @@ static const char *aarch64_apply_style
gas_assert (res >= 0);
/* Allocate space on the obstack and format the result. */
- ptr = (char *) obstack_alloc (stack, res + 1);
+ ptr = obstack_alloc (stack, res + 1);
res = vsnprintf (ptr, (res + 1), fmt, args);
gas_assert (res >= 0);
@@ -5644,7 +5670,7 @@ print_operands (char *buf, const aarch64_opcode *opcode,
obstack_init (&content);
styler.apply_style = aarch64_apply_style;
- styler.state = (void *) &content;
+ styler.state = &content;
for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
{
@@ -6254,10 +6280,7 @@ typedef struct templates templates;
static templates *
lookup_mnemonic (const char *start, int len)
{
- templates *templ = NULL;
-
- templ = str_hash_find_n (aarch64_ops_hsh, start, len);
- return templ;
+ return str_hash_find_n (aarch64_ops_hsh, start, len);
}
/* Subroutine of md_assemble, responsible for looking up the primary
@@ -6388,6 +6411,8 @@ process_omitted_operand (enum aarch64_opnd type, const aarch64_opcode *opcode,
case AARCH64_OPND_UIMM3_OP2:
case AARCH64_OPND_IMM:
case AARCH64_OPND_IMM_2:
+ case AARCH64_OPND_IMMP1_2:
+ case AARCH64_OPND_IMMS1_2:
case AARCH64_OPND_WIDTH:
case AARCH64_OPND_UIMM7:
case AARCH64_OPND_NZCV:
@@ -6649,6 +6674,28 @@ reg_list_valid_p (uint32_t reginfo, struct aarch64_reglist *list,
return true;
}
+static aarch64_reg_type
+imm_invalid_reg_types (uint64_t flags)
+{
+ switch (flags & F_INVALID_IMM_SYMS)
+ {
+ case F_INVALID_IMM_SYMS_1:
+ return REG_TYPE_R_ZR_BHSDQ_V;
+
+ case F_INVALID_IMM_SYMS_2:
+ return REG_TYPE_R_ZR_SP_BHSDQ_VZP;
+
+ case F_INVALID_IMM_SYMS_3:
+ return REG_TYPE_R_ZR_SP_BHSDQ_VZP_PN;
+
+ default:
+ /* All instructions with immediate operands require an explicit flag -
+ this ensures that the flags will not be forgotten when adding new
+ instructions. */
+ gas_assert (0);
+ }
+}
+
/* Generic instruction operand parser. This does no encoding and no
semantic validation; it merely squirrels values away in the inst
structure. Returns TRUE or FALSE depending on whether the
@@ -6661,19 +6708,10 @@ parse_operands (char *str, const aarch64_opcode *opcode)
char *backtrack_pos = 0;
const enum aarch64_opnd *operands = opcode->operands;
const uint64_t flags = opcode->flags;
- aarch64_reg_type imm_reg_type;
clear_error ();
skip_whitespace (str);
- if (AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SME2))
- imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP_PN;
- else if (AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SVE)
- || AARCH64_CPU_HAS_FEATURE (*opcode->avariant, SVE2))
- imm_reg_type = REG_TYPE_R_ZR_SP_BHSDQ_VZP;
- else
- imm_reg_type = REG_TYPE_R_ZR_BHSDQ_V;
-
for (i = 0; operands[i] != AARCH64_OPND_NIL; i++)
{
int64_t val;
@@ -6823,6 +6861,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SVE_Zn:
case AARCH64_OPND_SVE_Zt:
case AARCH64_OPND_SME_Zm:
+ case AARCH64_OPND_SME_Zm_17:
reg_type = REG_TYPE_Z;
goto vector_reg;
@@ -6910,6 +6949,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SME_Zn_INDEX1_16:
case AARCH64_OPND_SME_Zn_INDEX2_15:
case AARCH64_OPND_SME_Zn_INDEX2_16:
+ case AARCH64_OPND_SME_Zn_INDEX2_19:
case AARCH64_OPND_SME_Zn_INDEX3_14:
case AARCH64_OPND_SME_Zn_INDEX3_15:
case AARCH64_OPND_SME_Zn_INDEX4_14:
@@ -7154,6 +7194,16 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->imm.value = val;
break;
+ case AARCH64_OPND_IMMP1_2:
+ po_imm_or_fail (1, 64);
+ info->imm.value = val - 1;
+ break;
+
+ case AARCH64_OPND_IMMS1_2:
+ po_imm_or_fail (-1, 62);
+ info->imm.value = val + 1;
+ break;
+
case AARCH64_OPND_SVE_AIMM:
case AARCH64_OPND_SVE_ASIMM:
po_imm_nc_or_fail ();
@@ -7217,13 +7267,15 @@ parse_operands (char *str, const aarch64_opcode *opcode)
{
int qfloat;
bool res1 = false, res2 = false;
+ aarch64_reg_type invalid_types
+ = imm_invalid_reg_types (opcode->flags);
/* N.B. -0.0 will be rejected; although -0.0 shouldn't be rejected,
it is probably not worth the effort to support it. */
if (!(res1 = parse_aarch64_imm_float (&str, &qfloat, false,
- imm_reg_type))
+ invalid_types))
&& (error_p ()
|| !(res2 = parse_constant_immediate (&str, &val,
- imm_reg_type))))
+ invalid_types))))
goto failure;
if ((res1 && qfloat == 0) || (res2 && val == 0))
{
@@ -7257,7 +7309,8 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SIMD_IMM:
case AARCH64_OPND_SIMD_IMM_SFT:
- if (! parse_big_immediate (&str, &val, imm_reg_type))
+ if (! parse_big_immediate (&str, &val,
+ imm_invalid_reg_types (opcode->flags)))
goto failure;
assign_imm_if_const_or_fixup_later (&inst.reloc, info,
/* addr_off_p */ 0,
@@ -7285,11 +7338,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SIMD_FPIMM:
case AARCH64_OPND_SVE_FPIMM8:
{
+ aarch64_reg_type invalid_types
+ = imm_invalid_reg_types (opcode->flags);
int qfloat;
bool dp_p;
dp_p = double_precision_operand_p (&inst.base.operands[0]);
- if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type)
+ if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, invalid_types)
|| !aarch64_imm_float_p (qfloat))
{
if (!error_p ())
@@ -7306,11 +7361,13 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_SVE_I1_HALF_TWO:
case AARCH64_OPND_SVE_I1_ZERO_ONE:
{
+ aarch64_reg_type invalid_types
+ = imm_invalid_reg_types (opcode->flags);
int qfloat;
bool dp_p;
dp_p = double_precision_operand_p (&inst.base.operands[0]);
- if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, imm_reg_type))
+ if (!parse_aarch64_imm_float (&str, &qfloat, dp_p, invalid_types))
{
if (!error_p ())
set_fatal_syntax_error (_("invalid floating-point"
@@ -7399,13 +7456,17 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_EXCEPTION:
case AARCH64_OPND_UNDEFINED:
- po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
- imm_reg_type));
- assign_imm_if_const_or_fixup_later (&inst.reloc, info,
- /* addr_off_p */ 0,
- /* need_libopcodes_p */ 0,
- /* skip_p */ 1);
- break;
+ {
+ aarch64_reg_type invalid_types
+ = imm_invalid_reg_types (opcode->flags);
+ po_misc_or_fail (parse_immediate_expression (&str, &inst.reloc.exp,
+ invalid_types));
+ assign_imm_if_const_or_fixup_later (&inst.reloc, info,
+ /* addr_off_p */ 0,
+ /* need_libopcodes_p */ 0,
+ /* skip_p */ 1);
+ break;
+ }
case AARCH64_OPND_NZCV:
{
@@ -7450,6 +7511,7 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->imm.value = 0;
break;
+ case AARCH64_OPND_ADDR_PCREL9:
case AARCH64_OPND_ADDR_PCREL14:
case AARCH64_OPND_ADDR_PCREL19:
case AARCH64_OPND_ADDR_PCREL21:
@@ -7487,8 +7549,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case compbranch:
case condbranch:
/* e.g. CBZ or B.COND */
- gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL19);
- inst.reloc.type = BFD_RELOC_AARCH64_BRANCH19;
+ gas_assert (operands[i] == AARCH64_OPND_ADDR_PCREL9
+ || operands[i] == AARCH64_OPND_ADDR_PCREL19);
+ inst.reloc.type = (operands[i] == AARCH64_OPND_ADDR_PCREL9)
+ ? BFD_RELOC_AARCH64_BRANCH9
+ : BFD_RELOC_AARCH64_BRANCH19;
break;
case testbranch:
/* e.g. TBZ */
@@ -7806,8 +7871,12 @@ parse_operands (char *str, const aarch64_opcode *opcode)
info->addr.offset.imm = inst.reloc.exp.X_add_number;
break;
- case AARCH64_OPND_SVE_ADDR_R:
- /* [<Xn|SP>{, <R><m>}]
+ case AARCH64_OPND_SVE_ADDR_RR:
+ case AARCH64_OPND_SVE_ADDR_RR_LSL1:
+ case AARCH64_OPND_SVE_ADDR_RR_LSL2:
+ case AARCH64_OPND_SVE_ADDR_RR_LSL3:
+ case AARCH64_OPND_SVE_ADDR_RR_LSL4:
+ /* [<Xn|SP>{, <R><m>{, lsl #<amount>}}]
but recognizing SVE registers. */
po_misc_or_fail (parse_sve_address (&str, info, &base_qualifier,
&offset_qualifier));
@@ -7816,8 +7885,21 @@ parse_operands (char *str, const aarch64_opcode *opcode)
offset_qualifier = AARCH64_OPND_QLF_X;
info->addr.offset.is_reg = 1;
info->addr.offset.regno = 31;
+
+ /* We set the shifter amount here, but let regoff_addr assign the
+ shifter kind. */
+ if (operands[i] == AARCH64_OPND_SVE_ADDR_RR)
+ info->shifter.amount = 0;
+ else if (operands[i] == AARCH64_OPND_SVE_ADDR_RR_LSL1)
+ info->shifter.amount = 1;
+ else if (operands[i] == AARCH64_OPND_SVE_ADDR_RR_LSL2)
+ info->shifter.amount = 2;
+ else if (operands[i] == AARCH64_OPND_SVE_ADDR_RR_LSL3)
+ info->shifter.amount = 3;
+ else
+ info->shifter.amount = 4;
}
- else if (base_qualifier != AARCH64_OPND_QLF_X
+ if (base_qualifier != AARCH64_OPND_QLF_X
|| offset_qualifier != AARCH64_OPND_QLF_X)
{
set_syntax_error (_("invalid addressing mode"));
@@ -7825,11 +7907,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
}
goto regoff_addr;
- case AARCH64_OPND_SVE_ADDR_RR:
- case AARCH64_OPND_SVE_ADDR_RR_LSL1:
- case AARCH64_OPND_SVE_ADDR_RR_LSL2:
- case AARCH64_OPND_SVE_ADDR_RR_LSL3:
- case AARCH64_OPND_SVE_ADDR_RR_LSL4:
+ case AARCH64_OPND_SVE_ADDR_RM:
+ case AARCH64_OPND_SVE_ADDR_RM_LSL1:
+ case AARCH64_OPND_SVE_ADDR_RM_LSL2:
+ case AARCH64_OPND_SVE_ADDR_RM_LSL3:
+ case AARCH64_OPND_SVE_ADDR_RM_LSL4:
case AARCH64_OPND_SVE_ADDR_RX:
case AARCH64_OPND_SVE_ADDR_RX_LSL1:
case AARCH64_OPND_SVE_ADDR_RX_LSL2:
@@ -8053,7 +8135,9 @@ parse_operands (char *str, const aarch64_opcode *opcode)
{
/* DSB nXS barrier variant accept 5-bit unsigned immediate, with
possible values 16, 20, 24 or 28 , encoded as val<3:2>. */
- if (! parse_constant_immediate (&str, &val, imm_reg_type))
+ aarch64_reg_type invalid_types
+ = imm_invalid_reg_types (opcode->flags);
+ if (! parse_constant_immediate (&str, &val, invalid_types))
goto failure;
if (!(val == 16 || val == 20 || val == 24 || val == 28))
{
@@ -8068,9 +8152,18 @@ parse_operands (char *str, const aarch64_opcode *opcode)
case AARCH64_OPND_PRFOP:
val = parse_pldop (&str);
+
+ if (opcode->iclass != ldst_pos && val == 0x18)
+ {
+ set_syntax_error (_("invalid prefetch operation (IR is not valid for"
+ " this instruction variant)"));
+ goto failure;
+ }
+
/* This is an extension to accept a 0..31 immediate. */
if (val == PARSE_FAIL)
po_imm_or_fail (0, 31);
+
inst.base.operands[i].prfop = aarch64_prfops + val;
break;
@@ -8150,6 +8243,11 @@ parse_operands (char *str, const aarch64_opcode *opcode)
goto failure;
break;
+ case AARCH64_OPND_STSHH_POLICY:
+ if (!parse_hint_opt (opcode->name, &str, &(info->hint_option)))
+ goto failure;
+ break;
+
case AARCH64_OPND_SME_ZAda_1b:
case AARCH64_OPND_SME_ZAda_2b:
case AARCH64_OPND_SME_ZAda_3b:
@@ -8624,7 +8722,7 @@ md_assemble (char *str)
if (last_label_seen != NULL)
{
symbol_set_frag (last_label_seen, frag_now);
- S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
+ S_SET_VALUE (last_label_seen, frag_now_fix ());
S_SET_SEGMENT (last_label_seen, now_seg);
}
@@ -9041,12 +9139,15 @@ aarch64_handle_align (fragS * fragP)
#endif
memset (p, 0, fix);
p += fix;
+ bytes -= fix;
fragP->fr_fix += fix;
}
- if (noop_size)
- memcpy (p, aarch64_noop, noop_size);
- fragP->fr_var = noop_size;
+ if (bytes != 0)
+ {
+ fragP->fr_var = noop_size;
+ memcpy (p, aarch64_noop, noop_size);
+ }
}
/* Perform target specific initialisation of a frag.
@@ -9121,7 +9222,7 @@ aarch64_sframe_cfa_ra_offset (void)
return (offsetT) SFRAME_CFA_FIXED_RA_INVALID;
}
-/* Get the abi/arch indentifier for SFrame. */
+/* Get the abi/arch identifier for SFrame. */
unsigned char
aarch64_sframe_get_abi_arch (void)
@@ -9306,6 +9407,10 @@ try_to_encode_as_unscaled_ldst (aarch64_inst *instr)
if (new_op == OP_NIL)
return false;
+ if ((instr->opcode->op == OP_PRFM_POS)
+ && (instr->operands[0].prfop->value == 0x18))
+ return false;
+
new_opcode = aarch64_get_opcode (new_op);
gas_assert (new_opcode != NULL);
@@ -9670,6 +9775,20 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
}
break;
+ case BFD_RELOC_AARCH64_BRANCH9:
+ if (fixP->fx_done || !seg->use_rela_p)
+ {
+ if (value & 3)
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("conditional branch target not word aligned"));
+ if (signed_overflow (value, 11))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("conditional branch out of range"));
+ insn = get_aarch64_insn (buf);
+ insn |= encode_cond_branch_ofs_9 (value >> 2);
+ put_aarch64_insn (buf, insn);
+ }
+ break;
case BFD_RELOC_AARCH64_BRANCH19:
if (fixP->fx_done || !seg->use_rela_p)
{
@@ -10068,7 +10187,7 @@ cons_fix_new_aarch64 (fragS * frag, int where, int size, expressionS * exp)
}
#endif
- fix_new_exp (frag, where, (int) size, exp, pcrel, type);
+ fix_new_exp (frag, where, size, exp, pcrel, type);
}
/* Implement md_after_parse_args. This is the earliest time we need to decide
@@ -10214,20 +10333,20 @@ aarch64_adjust_symtab (void)
{
#ifdef OBJ_ELF
/* Remove any overlapping mapping symbols generated by alignment frags. */
- bfd_map_over_sections (stdoutput, check_mapping_symbols, (char *) 0);
+ bfd_map_over_sections (stdoutput, check_mapping_symbols, NULL);
/* Now do generic ELF adjustments. */
elf_adjust_symtab ();
#endif
}
static void
-checked_hash_insert (htab_t table, const char *key, void *value)
+checked_hash_insert (htab_t table, const char *key, const void *value)
{
str_hash_insert (table, key, value, 0);
}
static void
-sysreg_hash_insert (htab_t table, const char *key, void *value)
+sysreg_hash_insert (htab_t table, const char *key, const void *value)
{
gas_assert (strlen (key) < AARCH64_MAX_SYSREG_NAME_LEN);
checked_hash_insert (table, key, value);
@@ -10248,7 +10367,7 @@ fill_instruction_hash_table (void)
new_templ->next = NULL;
if (!templ)
- checked_hash_insert (aarch64_ops_hsh, opcode->name, (void *) new_templ);
+ checked_hash_insert (aarch64_ops_hsh, opcode->name, new_templ);
else
{
new_templ->next = templ->next;
@@ -10307,54 +10426,54 @@ md_begin (void)
for (i = 0; aarch64_sys_regs[i].name != NULL; ++i)
sysreg_hash_insert (aarch64_sys_regs_hsh, aarch64_sys_regs[i].name,
- (void *) (aarch64_sys_regs + i));
+ aarch64_sys_regs + i);
for (i = 0; aarch64_pstatefields[i].name != NULL; ++i)
sysreg_hash_insert (aarch64_pstatefield_hsh,
- aarch64_pstatefields[i].name,
- (void *) (aarch64_pstatefields + i));
+ aarch64_pstatefields[i].name,
+ aarch64_pstatefields + i);
for (i = 0; aarch64_sys_regs_ic[i].name != NULL; i++)
sysreg_hash_insert (aarch64_sys_regs_ic_hsh,
- aarch64_sys_regs_ic[i].name,
- (void *) (aarch64_sys_regs_ic + i));
+ aarch64_sys_regs_ic[i].name,
+ aarch64_sys_regs_ic + i);
for (i = 0; aarch64_sys_regs_dc[i].name != NULL; i++)
sysreg_hash_insert (aarch64_sys_regs_dc_hsh,
- aarch64_sys_regs_dc[i].name,
- (void *) (aarch64_sys_regs_dc + i));
+ aarch64_sys_regs_dc[i].name,
+ aarch64_sys_regs_dc + i);
for (i = 0; aarch64_sys_regs_at[i].name != NULL; i++)
sysreg_hash_insert (aarch64_sys_regs_at_hsh,
- aarch64_sys_regs_at[i].name,
- (void *) (aarch64_sys_regs_at + i));
+ aarch64_sys_regs_at[i].name,
+ aarch64_sys_regs_at + i);
for (i = 0; aarch64_sys_regs_tlbi[i].name != NULL; i++)
sysreg_hash_insert (aarch64_sys_regs_tlbi_hsh,
- aarch64_sys_regs_tlbi[i].name,
- (void *) (aarch64_sys_regs_tlbi + i));
+ aarch64_sys_regs_tlbi[i].name,
+ aarch64_sys_regs_tlbi + i);
for (i = 0; aarch64_sys_regs_sr[i].name != NULL; i++)
sysreg_hash_insert (aarch64_sys_regs_sr_hsh,
- aarch64_sys_regs_sr[i].name,
- (void *) (aarch64_sys_regs_sr + i));
+ aarch64_sys_regs_sr[i].name,
+ aarch64_sys_regs_sr + i);
for (i = 0; i < ARRAY_SIZE (reg_names); i++)
checked_hash_insert (aarch64_reg_hsh, reg_names[i].name,
- (void *) (reg_names + i));
+ reg_names + i);
for (i = 0; i < ARRAY_SIZE (nzcv_names); i++)
checked_hash_insert (aarch64_nzcv_hsh, nzcv_names[i].template,
- (void *) (nzcv_names + i));
+ nzcv_names + i);
for (i = 0; aarch64_operand_modifiers[i].name != NULL; i++)
{
const char *name = aarch64_operand_modifiers[i].name;
checked_hash_insert (aarch64_shift_hsh, name,
- (void *) (aarch64_operand_modifiers + i));
+ aarch64_operand_modifiers + i);
/* Also hash the name in the upper case. */
checked_hash_insert (aarch64_shift_hsh, get_upper_str (name),
- (void *) (aarch64_operand_modifiers + i));
+ aarch64_operand_modifiers + i);
}
for (i = 0; i < ARRAY_SIZE (aarch64_conds); i++)
@@ -10368,10 +10487,10 @@ md_begin (void)
if (name == NULL)
break;
checked_hash_insert (aarch64_cond_hsh, name,
- (void *) (aarch64_conds + i));
+ aarch64_conds + i);
/* Also hash the name in the upper case. */
checked_hash_insert (aarch64_cond_hsh, get_upper_str (name),
- (void *) (aarch64_conds + i));
+ aarch64_conds + i);
}
}
@@ -10382,20 +10501,20 @@ md_begin (void)
if ((i & 0x3) == 0)
continue;
checked_hash_insert (aarch64_barrier_opt_hsh, name,
- (void *) (aarch64_barrier_options + i));
+ aarch64_barrier_options + i);
/* Also hash the name in the upper case. */
checked_hash_insert (aarch64_barrier_opt_hsh, get_upper_str (name),
- (void *) (aarch64_barrier_options + i));
+ aarch64_barrier_options + i);
}
for (i = 0; i < ARRAY_SIZE (aarch64_barrier_dsb_nxs_options); i++)
{
const char *name = aarch64_barrier_dsb_nxs_options[i].name;
checked_hash_insert (aarch64_barrier_opt_hsh, name,
- (void *) (aarch64_barrier_dsb_nxs_options + i));
+ aarch64_barrier_dsb_nxs_options + i);
/* Also hash the name in the upper case. */
checked_hash_insert (aarch64_barrier_opt_hsh, get_upper_str (name),
- (void *) (aarch64_barrier_dsb_nxs_options + i));
+ aarch64_barrier_dsb_nxs_options + i);
}
for (i = 0; i < ARRAY_SIZE (aarch64_prfops); i++)
@@ -10405,10 +10524,10 @@ md_begin (void)
if (name == NULL)
continue;
checked_hash_insert (aarch64_pldop_hsh, name,
- (void *) (aarch64_prfops + i));
+ aarch64_prfops + i);
/* Also hash the name in the upper case. */
checked_hash_insert (aarch64_pldop_hsh, get_upper_str (name),
- (void *) (aarch64_prfops + i));
+ aarch64_prfops + i);
}
for (i = 0; aarch64_hint_options[i].name != NULL; i++)
@@ -10417,12 +10536,12 @@ md_begin (void)
const char* upper_name = get_upper_str(name);
checked_hash_insert (aarch64_hint_opt_hsh, name,
- (void *) (aarch64_hint_options + i));
+ aarch64_hint_options + i);
/* Also hash the name in the upper case if not the same. */
if (strcmp (name, upper_name) != 0)
checked_hash_insert (aarch64_hint_opt_hsh, upper_name,
- (void *) (aarch64_hint_options + i));
+ aarch64_hint_options + i);
}
/* Set the cpu variant based on the command-line options. */
@@ -10498,6 +10617,9 @@ static struct aarch64_option_table aarch64_opts[] = {
NULL},
{"mno-verbose-error", N_("do not output verbose error messages"),
&verbose_error_p, 0, NULL},
+ {"menable-sysreg-checking",
+ N_("enable feature flag gating for system registers"),
+ &sysreg_checking_p, 1, NULL},
{NULL, NULL, NULL, 0, NULL}
};
@@ -10620,6 +10742,7 @@ static const struct aarch64_arch_option_table aarch64_archs[] = {
{"armv9.3-a", AARCH64_ARCH_FEATURES (V9_3A)},
{"armv9.4-a", AARCH64_ARCH_FEATURES (V9_4A)},
{"armv9.5-a", AARCH64_ARCH_FEATURES (V9_5A)},
+ {"armv9.6-a", AARCH64_ARCH_FEATURES (V9_6A)},
{NULL, AARCH64_NO_FEATURES}
};
@@ -10641,7 +10764,9 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
AARCH64_FEATURE (SIMD)},
{"fp", AARCH64_FEATURE (FP), AARCH64_NO_FEATURES},
{"lse", AARCH64_FEATURE (LSE), AARCH64_NO_FEATURES},
+ {"lsfe", AARCH64_FEATURE (LSFE), AARCH64_FEATURE (FP)},
{"lse128", AARCH64_FEATURE (LSE128), AARCH64_FEATURE (LSE)},
+ {"lsui", AARCH64_FEATURE (LSUI), AARCH64_NO_FEATURES},
{"simd", AARCH64_FEATURE (SIMD), AARCH64_FEATURE (FP)},
{"pan", AARCH64_FEATURE (PAN), AARCH64_NO_FEATURES},
{"lor", AARCH64_FEATURE (LOR), AARCH64_NO_FEATURES},
@@ -10650,6 +10775,7 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"rdm", AARCH64_FEATURE (RDMA), AARCH64_FEATURE (SIMD)},
{"fp16", AARCH64_FEATURE (F16), AARCH64_FEATURE (FP)},
{"fp16fml", AARCH64_FEATURE (F16_FML), AARCH64_FEATURE (F16)},
+ {"fprcvt", AARCH64_FEATURE (FPRCVT), AARCH64_FEATURE (FP)},
{"profile", AARCH64_FEATURE (PROFILE), AARCH64_NO_FEATURES},
{"sve", AARCH64_FEATURE (SVE), AARCH64_FEATURE (COMPNUM)},
{"tme", AARCH64_FEATURE (TME), AARCH64_NO_FEATURES},
@@ -10672,11 +10798,13 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"rng", AARCH64_FEATURE (RNG), AARCH64_NO_FEATURES},
{"ssbs", AARCH64_FEATURE (SSBS), AARCH64_NO_FEATURES},
{"memtag", AARCH64_FEATURE (MEMTAG), AARCH64_NO_FEATURES},
+ {"occmo", AARCH64_FEATURE (OCCMO), AARCH64_NO_FEATURES},
+ {"cmpbr", AARCH64_FEATURE (CMPBR), AARCH64_NO_FEATURES},
{"sve2", AARCH64_FEATURE (SVE2), AARCH64_FEATURE (SVE)},
{"sve2-sm4", AARCH64_FEATURE (SVE2_SM4),
AARCH64_FEATURES (2, SVE2, SM4)},
{"sve2-aes", AARCH64_FEATURE (SVE2_AES),
- AARCH64_FEATURES (2, SVE2, AES)},
+ AARCH64_FEATURES (2, SVE2, SVE_AES)},
{"sve2-sha3", AARCH64_FEATURE (SVE2_SHA3),
AARCH64_FEATURES (2, SVE2, SHA3)},
{"sve2-bitperm", AARCH64_FEATURE (SVE2_BITPERM),
@@ -10708,8 +10836,15 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"ite", AARCH64_FEATURE (ITE), AARCH64_NO_FEATURES},
{"d128", AARCH64_FEATURE (D128), D128_FEATURE_DEPS},
{"sve-b16b16", AARCH64_FEATURE (SVE_B16B16), AARCH64_NO_FEATURES},
+ {"sve-bfscale", AARCH64_FEATURE (SVE_BFSCALE), AARCH64_NO_FEATURES},
{"sme2p1", AARCH64_FEATURE (SME2p1), AARCH64_FEATURE (SME2)},
{"sve2p1", AARCH64_FEATURE (SVE2p1), AARCH64_FEATURE (SVE2)},
+ {"sve-f16f32mm", AARCH64_FEATURE (SVE_F16F32MM), AARCH64_FEATURE (SVE)},
+ {"f8f32mm", AARCH64_FEATURE (F8F32MM), AARCH64_FEATURES (2, SIMD, FP8)},
+ {"f8f16mm", AARCH64_FEATURE (F8F16MM), AARCH64_FEATURES (2, SIMD, FP8)},
+ {"sve-aes", AARCH64_FEATURE (SVE_AES), AARCH64_FEATURE (AES)},
+ {"sve-aes2", AARCH64_FEATURE (SVE_AES2), AARCH64_NO_FEATURES},
+ {"ssve-aes", AARCH64_FEATURE (SSVE_AES), AARCH64_FEATURES (2, SME2, SVE_AES)},
{"rcpc3", AARCH64_FEATURE (RCPC3), AARCH64_FEATURE (RCPC2)},
{"cpa", AARCH64_FEATURE (CPA), AARCH64_NO_FEATURES},
{"faminmax", AARCH64_FEATURE (FAMINMAX), AARCH64_FEATURE (SIMD)},
@@ -10733,6 +10868,9 @@ static const struct aarch64_option_cpu_value_table aarch64_features[] = {
{"sme-f16f16", AARCH64_FEATURE (SME_F16F16), AARCH64_FEATURE (SME2)},
{"sme-b16b16", AARCH64_FEATURE (SME_B16B16),
AARCH64_FEATURES (2, SVE_B16B16, SME2)},
+ {"pops", AARCH64_FEATURE (PoPS), AARCH64_NO_FEATURES},
+ {"sve2p2", AARCH64_FEATURE (SVE2p2), AARCH64_FEATURE (SVE2p1)},
+ {"sme2p2", AARCH64_FEATURE (SME2p2), AARCH64_FEATURE (SME2p1)},
{NULL, AARCH64_NO_FEATURES, AARCH64_NO_FEATURES},
};
@@ -10745,6 +10883,8 @@ struct aarch64_virtual_dependency_table
};
static const struct aarch64_virtual_dependency_table aarch64_dependencies[] = {
+ {AARCH64_FEATURE (SVE2), AARCH64_FEATURE (SVE2_SSVE_AES)},
+ {AARCH64_FEATURE (SSVE_AES), AARCH64_FEATURE (SVE2_SSVE_AES)},
{AARCH64_FEATURES (2, FP8FMA, SVE2), AARCH64_FEATURE (FP8FMA_SVE)},
{AARCH64_FEATURE (SSVE_FP8FMA), AARCH64_FEATURE (FP8FMA_SVE)},
{AARCH64_FEATURES (2, FP8DOT4, SVE2), AARCH64_FEATURE (FP8DOT4_SVE)},
@@ -10753,11 +10893,15 @@ static const struct aarch64_virtual_dependency_table aarch64_dependencies[] = {
{AARCH64_FEATURE (SSVE_FP8DOT2), AARCH64_FEATURE (FP8DOT2_SVE)},
{AARCH64_FEATURE (SME_F16F16), AARCH64_FEATURE (SME_F16F16_F8F16)},
{AARCH64_FEATURE (SME_F8F16), AARCH64_FEATURE (SME_F16F16_F8F16)},
+ {AARCH64_FEATURE (SVE), AARCH64_FEATURE (SVE_SME2p2)},
+ {AARCH64_FEATURE (SME), AARCH64_FEATURE (SVE2p1_SME)},
+ {AARCH64_FEATURE (SVE2), AARCH64_FEATURE (SVE2_SME2)},
+ {AARCH64_FEATURE (SME2), AARCH64_FEATURES (2, SVE2_SME2, SVE2p1_SME2)},
{AARCH64_FEATURE (SVE2p1), AARCH64_FEATURES (3, SVE2p1_SME, SVE2p1_SME2,
SVE2p1_SME2p1)},
- {AARCH64_FEATURE (SME), AARCH64_FEATURE (SVE2p1_SME)},
- {AARCH64_FEATURE (SME2), AARCH64_FEATURE (SVE2p1_SME2)},
{AARCH64_FEATURE (SME2p1), AARCH64_FEATURE (SVE2p1_SME2p1)},
+ {AARCH64_FEATURE (SVE2p2), AARCH64_FEATURE (SVE2p2_SME2p2)},
+ {AARCH64_FEATURE (SME2p2), AARCH64_FEATURES (2, SVE_SME2p2, SVE2p2_SME2p2)},
};
static aarch64_feature_set
@@ -10987,7 +11131,7 @@ aarch64_parse_arch (const char *str)
return aarch64_parse_features (ext, &march_cpu_opt, false);
}
- as_bad (_("unknown architecture `%s'\n"), str);
+ as_bad (_("unknown architecture `%s'"), str);
return 0;
}
@@ -11025,7 +11169,7 @@ aarch64_parse_abi (const char *str)
return 1;
}
- as_bad (_("unknown abi `%s'\n"), str);
+ as_bad (_("unknown abi `%s'"), str);
return 0;
}
@@ -11224,7 +11368,7 @@ s_aarch64_arch (int ignored ATTRIBUTE_UNUSED)
return;
}
- as_bad (_("unknown architecture `%s'\n"), name);
+ as_bad (_("unknown architecture `%s'"), name);
*input_line_pointer = saved_char;
ignore_rest_of_line ();
}
@@ -11257,34 +11401,3 @@ aarch64_copy_symbol_attributes (symbolS * dest, symbolS * src)
{
AARCH64_GET_FLAG (dest) = AARCH64_GET_FLAG (src);
}
-
-#ifdef OBJ_ELF
-/* Same as elf_copy_symbol_attributes, but without copying st_other.
- This is needed so AArch64 specific st_other values can be independently
- specified for an IFUNC resolver (that is called by the dynamic linker)
- and the symbol it resolves (aliased to the resolver). In particular,
- if a function symbol has special st_other value set via directives,
- then attaching an IFUNC resolver to that symbol should not override
- the st_other setting. Requiring the directive on the IFUNC resolver
- symbol would be unexpected and problematic in C code, where the two
- symbols appear as two independent function declarations. */
-
-void
-aarch64_elf_copy_symbol_attributes (symbolS *dest, symbolS *src)
-{
- struct elf_obj_sy *srcelf = symbol_get_obj (src);
- struct elf_obj_sy *destelf = symbol_get_obj (dest);
- /* If size is unset, copy size from src. Because we don't track whether
- .size has been used, we can't differentiate .size dest, 0 from the case
- where dest's size is unset. */
- if (!destelf->size && S_GET_SIZE (dest) == 0)
- {
- if (srcelf->size)
- {
- destelf->size = XNEW (expressionS);
- *destelf->size = *srcelf->size;
- }
- S_SET_SIZE (dest, S_GET_SIZE (src));
- }
-}
-#endif