summaryrefslogtreecommitdiff
path: root/opcodes/aarch64-asm.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
commitd8773a8a5f5614f508d9919cb7626ae0497b8141 (patch)
tree5ba56e29d3a94109568b7f1d01c7330863d007e2 /opcodes/aarch64-asm.c
parent503fae12992e5dbf48b4e30cea8d35f31d87effe (diff)
downloadbinutils-gdb-d8773a8a5f5614f508d9919cb7626ae0497b8141.tar.gz
aarch64: Add the SME2 MOVA instructions
SME2 defines new MOVA instructions for moving multiple registers to and from ZA. As with SME, the instructions are also available through MOV aliases. One notable feature of these instructions (and many other SME2 instructions) is that some register lists must start at a multiple of the list's size. The patch uses the general error "start register out of range" when this constraint isn't met, rather than an error specifically about multiples. This ensures that the error is consistent between these simple consecutive lists and later strided lists, for which the requirements aren't a simple multiple.
Diffstat (limited to 'opcodes/aarch64-asm.c')
-rw-r--r--opcodes/aarch64-asm.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c
index 10b70824b05..516aa8ecb81 100644
--- a/opcodes/aarch64-asm.c
+++ b/opcodes/aarch64-asm.c
@@ -1167,6 +1167,19 @@ aarch64_ins_sve_aimm (const aarch64_operand *self,
return true;
}
+bool
+aarch64_ins_sve_aligned_reglist (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors ATTRIBUTE_UNUSED)
+{
+ unsigned int num_regs = get_operand_specific_data (self);
+ unsigned int val = info->reglist.first_regno;
+ insert_field (self->fields[0], code, val / num_regs, 0);
+ return true;
+}
+
/* Encode an SVE CPY/DUP immediate. */
bool
aarch64_ins_sve_asimm (const aarch64_operand *self,
@@ -1384,6 +1397,35 @@ aarch64_ins_sme_za_hv_tiles (const aarch64_operand *self,
return true;
}
+bool
+aarch64_ins_sme_za_hv_tiles_range (const aarch64_operand *self,
+ const aarch64_opnd_info *info,
+ aarch64_insn *code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED,
+ aarch64_operand_error *errors
+ ATTRIBUTE_UNUSED)
+{
+ int ebytes = aarch64_get_qualifier_esize (info->qualifier);
+ int range_size = get_opcode_dependent_value (inst->opcode);
+ int fld_v = info->indexed_za.v;
+ int fld_rv = info->indexed_za.index.regno - 12;
+ int imm = info->indexed_za.index.imm;
+ int max_value = 16 / range_size / ebytes;
+
+ if (max_value == 0)
+ max_value = 1;
+
+ assert (imm % range_size == 0 && (imm / range_size) < max_value);
+ int fld_zan_imm = (info->indexed_za.regno * max_value) | (imm / range_size);
+ assert (fld_zan_imm < (range_size == 4 && ebytes < 8 ? 4 : 8));
+
+ insert_field (self->fields[0], code, fld_v, 0);
+ insert_field (self->fields[1], code, fld_rv, 0);
+ insert_field (self->fields[2], code, fld_zan_imm, 0);
+
+ return true;
+}
+
/* Encode in SME instruction ZERO list of up to eight 64-bit element tile names
separated by commas, encoded in the "imm8" field.
@@ -1410,7 +1452,7 @@ aarch64_ins_sme_za_array (const aarch64_operand *self,
const aarch64_inst *inst ATTRIBUTE_UNUSED,
aarch64_operand_error *errors ATTRIBUTE_UNUSED)
{
- int regno = info->indexed_za.index.regno - 12;
+ int regno = info->indexed_za.index.regno & 3;
int imm = info->indexed_za.index.imm;
insert_field (self->fields[0], code, regno, 0);
insert_field (self->fields[1], code, imm, 0);
@@ -1858,6 +1900,11 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
/* The variant is encoded as part of the immediate. */
break;
+ case sme_size_22:
+ insert_field (FLD_SME_size_22, &inst->value,
+ aarch64_get_variant (inst), 0);
+ break;
+
case sve_cpy:
insert_fields (&inst->value, aarch64_get_variant (inst),
0, 2, FLD_SVE_M_14, FLD_size);
@@ -1873,6 +1920,7 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst)
break;
case sve_limm:
+ case sme2_mov:
/* For sve_limm, the .B, .H, and .S forms are just a convenience
and depend on the immediate. They don't have a separate
encoding. */