mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-30 13:33:53 +08:00
gas: Implement categorization of Morello-specific instructions
While the concept of a core instruction relates to the idea of instructions that are available irrespective of the presence of architectural extensions, this concept breaks down with the introduction of the Morello architecture. Rather, what is observed in Morello is that when PSTATE.C64 == 1, the A64C_INSN variant becomes the ONLY valid aarch64_opcode variant, with the CORE_INSN variant becoming illegal. Therefore, some way of ruling out the use of such CORE_INSNs is needed. Similarly, some A64C_INSN instructions are only valid for PSTATE.C64 == 1 and are not valid when compiling for Morello A64 mode. At the assembly level, the CORE_INSN and A64C_INSN variants share the same mnemonic, differing only by whether they are passed a general- purpose register argument or its capability counterpart, e.g. * CORE_INSN: adr x0, #0 * A64C_INSN: adr c0, #0 This makes the prospect of combining both insn variants in binutils into a single insn entry in aarch64_opcode_table[], resolving the appropriate operand code (e.g. AARCH64_OPND_Can versus AARCH64_OPND_Rn) at compile time by analyzing the -march and -mabi flags. This approach falls short when dealing with instructions such as `bl' where the core and morello instructions share the same mnemonic but have distinct encodings. A more flexible approach is therefore presented here. Special restrictions to instructions are encoded in the FLAGS field, which can then be used in checks carried out in `md_assemble'. This fixes two issues: 1. Wrong fix suggestions in `output_operand_error_record': - attempting to assemble `adr w0, #0' at present, for example, results in a suggestion that `w0' be changed to `x0' as opposed to `c0'. 2. Purecap only instructions being accepted when assembling without the C64 extension: - `adr c0, #0' is currently accepted when assembling for Hybrid mode. This patch defines the F_NONC64 and F_C64ONLY flags for labellig these instructions in aarch64_opcode.flags, such that unavailable instructions could be identified by cross-referencing this field along with whether C64 is set in the `cpu_variant' aarch64_feature_set variable. When the conditions set by the flag is not met by `cpu_variant', the instruction can be attributed a AARCH64_OPDE_SYNTAX_ERROR, allowing for correct error handling in md_assemble. ChangeLog: * include/opcode/aarch64.h (F_NONC64): New flag. * include/opcode/aarch64.h (F_C64ONLY): Likewise. opcodes/ChangeLog: * aarch64-tbl.h (aarch64_opcode_table): Add F_NONC64 and F_C64ONLY to relevant aarch64_opcodes gas/ChangeLog: * config/tc-aarch64.c (validate_opcode_for_feature): New. (md_assemble): Use `validate_opcode_for_feature' in template selection. * gas/testsuite/gas/aarch64/morello-exclude.l: New testcase. * gas/testsuite/gas/aarch64/morello-exclude.s: Likewise. * gas/testsuite/gas/aarch64/morello-exclude.l: Likewise. * gas/testsuite/gas/aarch64/morello_insn.s: Fix hybrid codegen.
This commit is contained in:
parent
f103ba71c7
commit
459784def0
@ -7642,6 +7642,36 @@ dump_opcode_operands (const aarch64_opcode *opcode)
|
||||
}
|
||||
#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. */
|
||||
@ -7736,7 +7766,8 @@ md_assemble (char *str)
|
||||
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))
|
||||
{
|
||||
|
4
gas/testsuite/gas/aarch64/morello-exclude.d
Normal file
4
gas/testsuite/gas/aarch64/morello-exclude.d
Normal file
@ -0,0 +1,4 @@
|
||||
#name: Morello opcode filter
|
||||
#as: -march=morello+c64 -mabi=purecap
|
||||
#source: morello-exclude.s
|
||||
#error_output: morello-exclude.l
|
9
gas/testsuite/gas/aarch64/morello-exclude.l
Normal file
9
gas/testsuite/gas/aarch64/morello-exclude.l
Normal file
@ -0,0 +1,9 @@
|
||||
[^:]+: Assembler messages:
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adr w0,#0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adr x0,#0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adrp w0,#0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adrp x0,#0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `blr w0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `blr x0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `ret w0'
|
||||
[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `ret x0'
|
8
gas/testsuite/gas/aarch64/morello-exclude.s
Normal file
8
gas/testsuite/gas/aarch64/morello-exclude.s
Normal file
@ -0,0 +1,8 @@
|
||||
adr w0, #0
|
||||
adr x0, #0
|
||||
adrp w0, #0
|
||||
adrp x0, #0
|
||||
blr w0
|
||||
blr x0
|
||||
ret w0
|
||||
ret x0
|
@ -72,7 +72,12 @@ Label:
|
||||
\op \cd, Label
|
||||
.endr
|
||||
.endm
|
||||
morello_adrx c0
|
||||
|
||||
.ifdef C64MODE
|
||||
morello_adrx c0
|
||||
.else
|
||||
morello_adrx x0
|
||||
.endif
|
||||
|
||||
.ifdef C64MODE
|
||||
adrdp c0, #4096
|
||||
|
@ -969,7 +969,13 @@ extern aarch64_opcode aarch64_opcode_table[];
|
||||
#define F_SCAN (1ULL << 31)
|
||||
/* Do no shift immediate operand. */
|
||||
#define F_NOSHIFT (1ULL << 32)
|
||||
/* Next bit is 33. */
|
||||
/* Opcode variant is invalidated by PSTATE.C64. When PSTATE.C64 == 1, operation
|
||||
requires use of capability operands. */
|
||||
#define F_NONC64 (1ULL << 33)
|
||||
/* Opcode vatiant not suitable for morello hybrid mode and will fail unless
|
||||
PSTATE.C64 == 1. */
|
||||
#define F_C64ONLY (1ULL << 34)
|
||||
/* Next bit is 35. */
|
||||
|
||||
/* Instruction constraints. */
|
||||
/* This instruction has a predication constraint on the instruction at PC+4. */
|
||||
|
@ -3395,9 +3395,9 @@ struct aarch64_opcode aarch64_opcode_table[] =
|
||||
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),
|
||||
@ -3986,10 +3986,10 @@ struct aarch64_opcode aarch64_opcode_table[] =
|
||||
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. */
|
||||
|
Loading…
Reference in New Issue
Block a user