demand_empty_rest_of_line ();
}
+static void
+s_aarch64_cfi_b_key_frame (int ignored ATTRIBUTE_UNUSED)
+{
+ demand_empty_rest_of_line ();
+ struct fde_entry *fde = frchain_now->frch_cfi_data->cur_fde_data;
+ fde->pauth_key = AARCH64_PAUTH_KEY_B;
+}
+
#ifdef OBJ_ELF
/* Emit BFD_RELOC_AARCH64_TLSDESC_ADD on the next ADD instruction. */
{"arch", s_aarch64_arch, 0},
{"arch_extension", s_aarch64_arch_extension, 0},
{"inst", s_aarch64_inst, 0},
+ {"cfi_b_key_frame", s_aarch64_cfi_b_key_frame, 0},
#ifdef OBJ_ELF
{"tlsdescadd", s_tlsdescadd, 0},
{"tlsdesccall", s_tlsdesccall, 0},
[base,Wm,(S|U)XTW {#imm}]
Pre-indexed
[base,#imm]!
+ [base]! // in ld/stgv
Post-indexed
[base],#imm
[base],Xm // in SIMD ld/st structure
}
/* If at this point neither .preind nor .postind is set, we have a
- bare [Rn]{!}; reject [Rn]! but accept [Rn] as a shorthand for [Rn,#0]. */
+ bare [Rn]{!}; reject [Rn]! except for ld/stgv but accept [Rn]
+ as a shorthand for [Rn,#0]. */
if (operand->addr.preind == 0 && operand->addr.postind == 0)
{
- if (operand->addr.writeback)
+ if (operand->type != AARCH64_OPND_ADDR_SIMPLE_2 && operand->addr.writeback)
{
/* Reject [Rn]! */
set_syntax_error (_("missing offset in the pre-indexed address"));
return 0;
}
+/* Parse an operand for BTI. Set *HINT_OPT to the hint-option record
+ return 0 if successful. Otherwise return PARSE_FAIL. */
+
+static int
+parse_bti_operand (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 option to BTI"));
+ return PARSE_FAIL;
+ }
+
+ switch (o->value)
+ {
+ /* Valid BTI operands. */
+ case HINT_OPD_C:
+ case HINT_OPD_J:
+ case HINT_OPD_JC:
+ break;
+
+ default:
+ set_syntax_error
+ (_("unknown option to BTI"));
+ 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.
case AARCH64_OPND_BARRIER_ISB:
operand->barrier = aarch64_barrier_options + default_value;
+ break;
+
+ case AARCH64_OPND_BTI_TARGET:
+ operand->hint_option = aarch64_hint_options + default_value;
+ break;
default:
break;
case AARCH64_OPND_SIMM5:
case AARCH64_OPND_FBITS:
case AARCH64_OPND_UIMM4:
+ case AARCH64_OPND_UIMM4_ADDG:
+ case AARCH64_OPND_UIMM10:
case AARCH64_OPND_UIMM3_OP1:
case AARCH64_OPND_UIMM3_OP2:
case AARCH64_OPND_IMM_VLSL:
break;
case AARCH64_OPND_ADDR_SIMPLE:
+ case AARCH64_OPND_ADDR_SIMPLE_2:
case AARCH64_OPND_SIMD_ADDR_SIMPLE:
{
/* [<Xn|SP>{, #<simm>}] */
po_misc_or_fail (parse_address (&str, info));
if (info->addr.pcrel || info->addr.offset.is_reg
|| !info->addr.preind || info->addr.postind
- || info->addr.writeback)
+ || (info->addr.writeback
+ && operands[i] != AARCH64_OPND_ADDR_SIMPLE_2))
{
set_syntax_error (_("invalid addressing mode"));
goto failure;
}
}
po_char_or_fail (']');
+ if (operands[i] == AARCH64_OPND_ADDR_SIMPLE_2)
+ po_char_or_fail ('!');
break;
}
case AARCH64_OPND_ADDR_SIMM9:
case AARCH64_OPND_ADDR_SIMM9_2:
+ case AARCH64_OPND_ADDR_SIMM11:
+ case AARCH64_OPND_ADDR_SIMM13:
po_misc_or_fail (parse_address (&str, info));
if (info->addr.pcrel || info->addr.offset.is_reg
|| (!info->addr.preind && !info->addr.postind)
goto failure;
break;
+ case AARCH64_OPND_BTI_TARGET:
+ val = parse_bti_operand (&str, &(info->hint_option));
+ if (val == PARSE_FAIL)
+ goto failure;
+ break;
+
default:
as_fatal (_("unhandled operand code %d"), operands[i]);
}
&& opnds[1].addr.writeback)
as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
break;
+
+ case ldstgv_indexed:
+ /* Load operations must load different registers. */
+ if ((opcode->opcode & (1 << 22))
+ && opnds[0].reg.regno == opnds[1].addr.base_regno)
+ as_warn (_("unpredictable load of register -- `%s'"), str);
+ break;
+
case ldstpair_off:
case ldstnapair_offs:
case ldstpair_indexed:
&& (opnds[0].reg.regno == opnds[2].addr.base_regno
|| opnds[1].reg.regno == opnds[2].addr.base_regno)
&& opnds[2].addr.base_regno != REG_SP
+ /* Exempt STGP. */
+ && !(opnds[2].type == AARCH64_OPND_ADDR_SIMM11)
&& opnds[2].addr.writeback)
as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
/* Load operations must load different registers. */
case AARCH64_OPND_ADDR_SIMM9_2:
case AARCH64_OPND_ADDR_SIMM10:
case AARCH64_OPND_ADDR_UIMM12:
+ case AARCH64_OPND_ADDR_SIMM11:
+ case AARCH64_OPND_ADDR_SIMM13:
/* Immediate offset in an address. */
insn = get_aarch64_insn (buf);
{"sha3", AARCH64_FEATURE (AARCH64_FEATURE_SHA2
| AARCH64_FEATURE_SHA3, 0),
AARCH64_ARCH_NONE},
+ {"rng", AARCH64_FEATURE (AARCH64_FEATURE_RNG, 0),
+ AARCH64_ARCH_NONE},
+ {"ssbs", AARCH64_FEATURE (AARCH64_FEATURE_SSBS, 0),
+ AARCH64_ARCH_NONE},
+ {"memtag", AARCH64_FEATURE (AARCH64_FEATURE_MEMTAG, 0),
+ AARCH64_ARCH_NONE},
{NULL, AARCH64_ARCH_NONE, AARCH64_ARCH_NONE},
};