}
#endif /* DEBUG_AARCH64 */
+/* With the introduction of Morello, some CORE_INSNs are no longer
+ valid if IS_C64 is true. It is important that such instructions
+ are no longer treated as core in such contexts and are
+ disconsidered, rather being treated as belonging to any other
+ unavailable architectural extension. Likewise, reject purecap-specific
+ instructions when assembling for hybrid (or any other) tartgets. */
+
+static bfd_boolean
+validate_opcode_for_feature (const aarch64_opcode *opcode,
+ aarch64_feature_set features)
+{
+ /* If opcode is memory-related, Ensure this CPU does not impose any
+ restriction on allowed operands. */
+ if (opcode->flags & F_NONC64
+ && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64))
+ {
+ set_default_error ();
+ return FALSE;
+ }
+ /* Reject purecap-specific instructions when assembling for any other
+ target. */
+ if (opcode->flags & F_C64ONLY
+ && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64)))
+ {
+ set_default_error ();
+ return FALSE;
+ }
+ return TRUE;
+}
+
/* This is the guts of the machine-dependent assembler. STR points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
continue;
}
- if (parse_operands (p, opcode)
+ if (validate_opcode_for_feature (opcode, cpu_variant)
+ && parse_operands (p, opcode)
&& programmer_friendly_fixup (&inst)
&& do_encode (inst_base->opcode, &inst.base, &inst_base->value))
{
CORE_INSN ("b", 0x14000000, 0xfc000000, branch_imm, OP_B, OP1 (ADDR_PCREL26), QL_PCREL_26, 0),
CORE_INSN ("bl", 0x94000000, 0xfc000000, branch_imm, OP_BL, OP1 (ADDR_PCREL26), QL_PCREL_26, 0),
/* Unconditional branch (register). */
- CORE_INSN ("br", 0xd61f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, 0),
- CORE_INSN ("blr", 0xd63f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, 0),
- CORE_INSN ("ret", 0xd65f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, F_OPD0_OPT | F_DEFAULT (30)),
+ CORE_INSN ("br", 0xd61f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, F_NONC64),
+ CORE_INSN ("blr", 0xd63f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, F_NONC64),
+ CORE_INSN ("ret", 0xd65f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn), QL_I1X, F_OPD0_OPT | F_DEFAULT (30) | F_NONC64),
CORE_INSN ("eret", 0xd69f03e0, 0xffffffff, branch_reg, 0, OP0 (), {}, 0),
CORE_INSN ("drps", 0xd6bf03e0, 0xffffffff, branch_reg, 0, OP0 (), {}, 0),
V8_3_INSN ("braa", 0xd71f0800, 0xfffffc00, branch_reg, OP2 (Rn, Rd_SP), QL_I2SAMEX, 0),
CORE_INSN ("mov", 0x52800000, 0x7f800000, movewide, OP_MOV_IMM_WIDE, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_CONV),
CORE_INSN ("movk", 0x72800000, 0x7f800000, movewide, OP_MOVK, OP2 (Rd, HALF), QL_DST_R, F_SF),
/* PC-rel. addressing. */
- CORE_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_PCREL21), QL_ADRP, 0),
- CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_ADRP), QL_ADRP, 0),
+ CORE_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_PCREL21), QL_ADRP,F_NONC64),
+ CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd, ADDR_ADRP), QL_ADRP, F_NONC64),
/* Pc-rel. addressing with capabilities. */
- A64C_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Cad, ADDR_PCREL21), QL2_A64C_CA_NIL, 0),
+ A64C_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Cad, ADDR_PCREL21), QL2_A64C_CA_NIL, F_C64ONLY),
A64C_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Cad, ADDR_ADRP), QL2_A64C_CA_NIL, 0),
A64C_INSN ("adrdp", 0x90000000, 0x9f800000, pcreladdr, 0, OP2 (Cad, A64C_ADDR_ADRDP), QL2_A64C_CA_NIL, 0),
/* A64C Instructions. */