summaryrefslogtreecommitdiff
path: root/opcodes/aarch64-dis.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2023-03-30 11:09:12 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2023-03-30 11:09:12 +0100
commit99e01a66b4c619fb8c7d6f978038eb7a3661c160 (patch)
tree7493699028bd43202975111c09e89213f1dd8df7 /opcodes/aarch64-dis.c
parentb408ebbf526e7293f08825d04b34c7d2ad7fc753 (diff)
downloadbinutils-gdb-99e01a66b4c619fb8c7d6f978038eb7a3661c160.tar.gz
aarch64: Add the SME2 predicate-related instructions
Implementation-wise, the main things to note here are: - the WHILE* instructions have forms that return a pair of predicate registers. This is the first time that we've had lists of predicate registers, and they wrap around after register 15 rather than after register 31. - the predicate-as-counter WHILE* instructions have a fourth operand that specifies the vector length. We can treat this as an enumeration, except that immediate values aren't allowed. - PEXT takes an unsuffixed predicate index of the form PN<n>[<imm>]. This is the first instance of a vector/predicate index having no suffix.
Diffstat (limited to 'opcodes/aarch64-dis.c')
-rw-r--r--opcodes/aarch64-dis.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 29b12d238e2..a2f69186355 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -168,18 +168,20 @@ extract_fields (aarch64_insn code, aarch64_insn mask, ...)
return value;
}
-/* Extract the value of all fields in SELF->fields from instruction CODE.
- The least significant bit comes from the final field. */
+/* Extract the value of all fields in SELF->fields after START from
+ instruction CODE. The least significant bit comes from the final field. */
static aarch64_insn
-extract_all_fields (const aarch64_operand *self, aarch64_insn code)
+extract_all_fields_after (const aarch64_operand *self, unsigned int start,
+ aarch64_insn code)
{
aarch64_insn value;
unsigned int i;
enum aarch64_field_kind kind;
value = 0;
- for (i = 0; i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i)
+ for (i = start;
+ i < ARRAY_SIZE (self->fields) && self->fields[i] != FLD_NIL; ++i)
{
kind = self->fields[i];
value <<= fields[kind].width;
@@ -188,6 +190,15 @@ extract_all_fields (const aarch64_operand *self, aarch64_insn code)
return value;
}
+/* Extract the value of all fields in SELF->fields from instruction CODE.
+ The least significant bit comes from the final field. */
+
+static aarch64_insn
+extract_all_fields (const aarch64_operand *self, aarch64_insn code)
+{
+ return extract_all_fields_after (self, 0, code);
+}
+
/* Sign-extend bit I of VALUE. */
static inline uint64_t
sign_extend (aarch64_insn value, unsigned i)
@@ -2126,6 +2137,20 @@ aarch64_ext_x0_to_x30 (const aarch64_operand *self, aarch64_opnd_info *info,
info->reg.regno = extract_field (self->fields[0], code, 0);
return info->reg.regno <= 30;
}
+
+/* Decode an indexed register, with the first field being the register
+ number and the remaining fields being the index. */
+bool
+aarch64_ext_simple_index (const aarch64_operand *self, aarch64_opnd_info *info,
+ const aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ int bias = get_operand_specific_data (self);
+ info->reglane.regno = extract_field (self->fields[0], code, 0) + bias;
+ info->reglane.index = extract_all_fields_after (self, 1, code);
+ return true;
+}
/* Bitfields that are commonly used to encode certain operands' information
may be partially used as part of the base opcode in some instructions.