summaryrefslogtreecommitdiff
path: root/opcodes/aarch64-opc.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
commitb408ebbf526e7293f08825d04b34c7d2ad7fc753 (patch)
tree3331d54d3c7cafb02746194a07d78646b65f5c73 /opcodes/aarch64-opc.c
parentd8773a8a5f5614f508d9919cb7626ae0497b8141 (diff)
downloadbinutils-gdb-b408ebbf526e7293f08825d04b34c7d2ad7fc753.tar.gz
aarch64: Add the SME2 multivector LD1 and ST1 instructions
SME2 adds LD1 and ST1 variants for lists of 2 and 4 registers. The registers can be consecutive or strided. In the strided case, 2-register lists have a stride of 8, starting at register x0xxx. 4-register lists have a stride of 4, starting at register x00xx. The instructions are predicated on a predicate-as-counter register in the range pn8-pn15. Although we already had register fields with upper bounds of 7 and 15, this is the first plain register operand to have a nonzero lower bound. The patch uses the operand-specific data field to record the minimum value, rather than having separate inserters and extractors for each lower bound. This in turn required adding an extra bit to the field.
Diffstat (limited to 'opcodes/aarch64-opc.c')
-rw-r--r--opcodes/aarch64-opc.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index b3308955cc8..66c9d65d16e 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -231,6 +231,9 @@ const aarch64_field fields[] =
{ 2, 3 }, /* SME_Zdn4: Z0-Z31, multiple of 4, bits [4:2]. */
{ 6, 4 }, /* SME_Zn2: Z0-Z31, multiple of 2, bits [9:6]. */
{ 7, 3 }, /* SME_Zn4: Z0-Z31, multiple of 4, bits [9:7]. */
+ { 4, 1 }, /* SME_ZtT: upper bit of Zt, bit [4]. */
+ { 0, 3 }, /* SME_Zt3: lower 3 bits of Zt, bits [2:0]. */
+ { 0, 2 }, /* SME_Zt2: lower 2 bits of Zt, bits [1:0]. */
{ 23, 1 }, /* SME_i1: immediate field, bit 23. */
{ 22, 2 }, /* SME_size_22: size<1>, size<0> class field, [23:22]. */
{ 22, 1 }, /* SME_tszh: immediate and qualifier field, bit 22. */
@@ -1748,6 +1751,22 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
}
break;
+ case AARCH64_OPND_SME_Ztx2_STRIDED:
+ case AARCH64_OPND_SME_Ztx4_STRIDED:
+ /* 2-register lists have a stride of 8 and 4-register lists
+ have a stride of 4. */
+ num = get_operand_specific_data (&aarch64_operands[type]);
+ if (!check_reglist (opnd, mismatch_detail, idx, num, 16 / num))
+ return 0;
+ num = 16 | (opnd->reglist.stride - 1);
+ if ((opnd->reglist.first_regno & ~num) != 0)
+ {
+ set_other_error (mismatch_detail, idx,
+ _("start register out of range"));
+ return 0;
+ }
+ break;
+
case AARCH64_OPND_SVE_ZnxN:
case AARCH64_OPND_SVE_ZtxN:
num = get_opcode_dependent_value (opcode);
@@ -1804,11 +1823,24 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
break;
case AARCH64_OPND_CLASS_PRED_REG:
- if (opnd->reg.regno >= 8
- && get_operand_fields_width (get_operand_from_code (type)) == 3)
+ switch (type)
{
- set_invalid_regno_error (mismatch_detail, idx, "p", 0, 7);
- return 0;
+ case AARCH64_OPND_SME_PNg3:
+ if (opnd->reg.regno < 8)
+ {
+ set_invalid_regno_error (mismatch_detail, idx, "pn", 8, 15);
+ return 0;
+ }
+ break;
+
+ default:
+ if (opnd->reg.regno >= 8
+ && get_operand_fields_width (get_operand_from_code (type)) == 3)
+ {
+ set_invalid_regno_error (mismatch_detail, idx, "p", 0, 7);
+ return 0;
+ }
+ break;
}
break;
@@ -3742,9 +3774,15 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
case AARCH64_OPND_SVE_PNg4_10:
case AARCH64_OPND_SVE_PNn:
case AARCH64_OPND_SVE_PNt:
+ case AARCH64_OPND_SME_PNg3:
if (opnd->qualifier == AARCH64_OPND_QLF_NIL)
snprintf (buf, size, "%s",
style_reg (styler, "pn%d", opnd->reg.regno));
+ else if (opnd->qualifier == AARCH64_OPND_QLF_P_Z
+ || opnd->qualifier == AARCH64_OPND_QLF_P_M)
+ snprintf (buf, size, "%s",
+ style_reg (styler, "pn%d/%s", opnd->reg.regno,
+ aarch64_get_qualifier_name (opnd->qualifier)));
else
snprintf (buf, size, "%s",
style_reg (styler, "pn%d.%s", opnd->reg.regno,
@@ -3772,6 +3810,8 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
case AARCH64_OPND_SME_Zdnx4:
case AARCH64_OPND_SME_Znx2:
case AARCH64_OPND_SME_Znx4:
+ case AARCH64_OPND_SME_Ztx2_STRIDED:
+ case AARCH64_OPND_SME_Ztx4_STRIDED:
print_register_list (buf, size, opnd, "z", styler);
break;