forked from Imagelibrary/binutils-gdb
aarch64: Enforce P/M/E order for MOPS instructions
The MOPS instructions should be used as a triple, such as:
cpyfp [x0]!, [x1]!, x2!
cpyfm [x0]!, [x1]!, x2!
cpyfe [x0]!, [x1]!, x2!
The registers should also be the same for each writeback operand.
This patch adds a warning for code that doesn't follow this rule,
along similar lines to the warning that we already emit for
invalid uses of MOVPRFX.
include/
* opcode/aarch64.h (C_SCAN_MOPS_P, C_SCAN_MOPS_M, C_SCAN_MOPS_E)
(C_SCAN_MOPS_PME): New macros.
(AARCH64_OPDE_A_SHOULD_FOLLOW_B): New aarch64_operand_error_kind.
(AARCH64_OPDE_EXPECTED_A_AFTER_B): Likewise.
(aarch64_operand_error): Make each data value a union between
an int and a string.
opcodes/
* aarch64-tbl.h (MOPS_CPY_OP1_OP2_INSN): Add scan flags.
(MOPS_SET_OP1_OP2_INSN): Likewise.
* aarch64-opc.c (set_out_of_range_error): Update after change to
aarch64_operand_error.
(set_unaligned_error, set_reg_list_error): Likewise.
(init_insn_sequence): Use a 3-instruction sequence for
MOPS P instructions.
(verify_mops_pme_sequence): New function.
(verify_constraints): Call it.
* aarch64-dis.c (print_verifier_notes): Handle
AARCH64_OPDE_A_SHOULD_FOLLOW_B and AARCH64_OPDE_EXPECTED_A_AFTER_B.
gas/
* config/tc-aarch64.c (operand_mismatch_kind_names): Add entries
for AARCH64_OPDE_A_SHOULD_FOLLOW_B and AARCH64_OPDE_EXPECTED_A_AFTER_B.
(operand_error_higher_severity_p): Check that
AARCH64_OPDE_A_SHOULD_FOLLOW_B and AARCH64_OPDE_EXPECTED_A_AFTER_B
come between AARCH64_OPDE_RECOVERABLE and AARCH64_OPDE_SYNTAX_ERROR;
their relative order is not significant.
(record_operand_error_with_data): Update after change to
aarch64_operand_error.
(output_operand_error_record): Likewise. Handle
AARCH64_OPDE_A_SHOULD_FOLLOW_B and AARCH64_OPDE_EXPECTED_A_AFTER_B.
* testsuite/gas/aarch64/mops_invalid_2.s,
testsuite/gas/aarch64/mops_invalid_2.d,
testsuite/gas/aarch64/mops_invalid_2.l: New test.
This commit is contained in:
@@ -927,7 +927,11 @@ extern const aarch64_opcode aarch64_opcode_table[];
|
||||
/* This instruction's operation width is determined by the operand with the
|
||||
largest element size. */
|
||||
#define C_MAX_ELEM (1U << 1)
|
||||
/* Next bit is 2. */
|
||||
#define C_SCAN_MOPS_P (1U << 2)
|
||||
#define C_SCAN_MOPS_M (2U << 2)
|
||||
#define C_SCAN_MOPS_E (3U << 2)
|
||||
#define C_SCAN_MOPS_PME (3U << 2)
|
||||
/* Next bit is 4. */
|
||||
|
||||
static inline bool
|
||||
alias_opcode_p (const aarch64_opcode *opcode)
|
||||
@@ -1221,6 +1225,17 @@ struct aarch64_inst
|
||||
Less severe error found during the parsing, very possibly because that
|
||||
GAS has picked up a wrong instruction template for the parsing.
|
||||
|
||||
AARCH64_OPDE_A_SHOULD_FOLLOW_B
|
||||
The instruction forms (or is expected to form) part of a sequence,
|
||||
but the preceding instruction in the sequence wasn't the expected one.
|
||||
The message refers to two strings: the name of the current instruction,
|
||||
followed by the name of the expected preceding instruction.
|
||||
|
||||
AARCH64_OPDE_EXPECTED_A_AFTER_B
|
||||
Same as AARCH64_OPDE_A_SHOULD_FOLLOW_B, but shifting the focus
|
||||
so that the current instruction is assumed to be the incorrect one:
|
||||
"since the previous instruction was B, the current one should be A".
|
||||
|
||||
AARCH64_OPDE_SYNTAX_ERROR
|
||||
General syntax error; it can be either a user error, or simply because
|
||||
that GAS is trying a wrong instruction template.
|
||||
@@ -1255,11 +1270,8 @@ struct aarch64_inst
|
||||
Error of the highest severity and used for any severe issue that does not
|
||||
fall into any of the above categories.
|
||||
|
||||
The enumerators are only interesting to GAS. They are declared here (in
|
||||
libopcodes) because that some errors are detected (and then notified to GAS)
|
||||
by libopcodes (rather than by GAS solely).
|
||||
|
||||
The first three errors are only deteced by GAS while the
|
||||
AARCH64_OPDE_RECOVERABLE, AARCH64_OPDE_SYNTAX_ERROR and
|
||||
AARCH64_OPDE_FATAL_SYNTAX_ERROR are only deteced by GAS while the
|
||||
AARCH64_OPDE_INVALID_VARIANT error can only be spotted by libopcodes as
|
||||
only libopcodes has the information about the valid variants of each
|
||||
instruction.
|
||||
@@ -1273,6 +1285,8 @@ enum aarch64_operand_error_kind
|
||||
{
|
||||
AARCH64_OPDE_NIL,
|
||||
AARCH64_OPDE_RECOVERABLE,
|
||||
AARCH64_OPDE_A_SHOULD_FOLLOW_B,
|
||||
AARCH64_OPDE_EXPECTED_A_AFTER_B,
|
||||
AARCH64_OPDE_SYNTAX_ERROR,
|
||||
AARCH64_OPDE_FATAL_SYNTAX_ERROR,
|
||||
AARCH64_OPDE_INVALID_VARIANT,
|
||||
@@ -1290,7 +1304,11 @@ struct aarch64_operand_error
|
||||
enum aarch64_operand_error_kind kind;
|
||||
int index;
|
||||
const char *error;
|
||||
int data[3]; /* Some data for extra information. */
|
||||
/* Some data for extra information. */
|
||||
union {
|
||||
int i;
|
||||
const char *s;
|
||||
} data[3];
|
||||
bool non_fatal;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user