summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2021-12-02 15:00:57 +0000
committerRichard Sandiford <richard.sandiford@arm.com>2021-12-02 15:00:57 +0000
commit63eff947512b36c770c92d45e4b22cb8a18a39be (patch)
tree336e8d9a01ee6665d9ec7b8148155ee7cab992a0 /include
parent6327658ee73502ffb55dfb6b28a20d1dde15a4dc (diff)
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.
Diffstat (limited to 'include')
-rw-r--r--include/opcode/aarch64.h32
1 files changed, 25 insertions, 7 deletions
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 183d28150c..21ba0bf007 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -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;
};