diff options
Diffstat (limited to 'gas/config/tc-aarch64.c')
-rw-r--r-- | gas/config/tc-aarch64.c | 353 |
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 |