summaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/aarch64-dis.c5
-rw-r--r--opcodes/aarch64-opc.c74
2 files changed, 56 insertions, 23 deletions
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 05e285fac99..e722514053e 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -439,6 +439,7 @@ aarch64_ext_reglist (const aarch64_operand *self, aarch64_opnd_info *info,
info->reglist.first_regno = extract_field (self->fields[0], code, 0);
/* len */
info->reglist.num_regs = extract_field (FLD_len, code, 0) + 1;
+ info->reglist.stride = 1;
return true;
}
@@ -482,6 +483,7 @@ aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED,
if (expected_num != data[value].num_elements || data[value].is_reserved)
return false;
info->reglist.num_regs = data[value].num_regs;
+ info->reglist.stride = 1;
return true;
}
@@ -510,6 +512,7 @@ aarch64_ext_ldst_reglist_r (const aarch64_operand *self ATTRIBUTE_UNUSED,
if (info->reglist.num_regs == 1 && value == (aarch64_insn) 1)
info->reglist.num_regs = 2;
+ info->reglist.stride = 1;
return true;
}
@@ -573,6 +576,7 @@ aarch64_ext_ldst_elemlist (const aarch64_operand *self ATTRIBUTE_UNUSED,
info->reglist.has_index = 1;
info->reglist.num_regs = 0;
+ info->reglist.stride = 1;
/* Number of registers is equal to the number of elements in
each structure to be loaded/stored. */
info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
@@ -1982,6 +1986,7 @@ aarch64_ext_sve_reglist (const aarch64_operand *self,
{
info->reglist.first_regno = extract_field (self->fields[0], code, 0);
info->reglist.num_regs = get_opcode_dependent_value (inst->opcode);
+ info->reglist.stride = 1;
return true;
}
diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c
index 8a9e51faebd..4e950cf70f8 100644
--- a/opcodes/aarch64-opc.c
+++ b/opcodes/aarch64-opc.c
@@ -1439,12 +1439,22 @@ set_unaligned_error (aarch64_operand_error *mismatch_detail, int idx,
}
static inline void
-set_reg_list_error (aarch64_operand_error *mismatch_detail, int idx,
- int expected_num)
+set_reg_list_length_error (aarch64_operand_error *mismatch_detail, int idx,
+ int expected_num)
{
if (mismatch_detail == NULL)
return;
- set_error (mismatch_detail, AARCH64_OPDE_REG_LIST, idx, NULL);
+ set_error (mismatch_detail, AARCH64_OPDE_REG_LIST_LENGTH, idx, NULL);
+ mismatch_detail->data[0].i = 1 << expected_num;
+}
+
+static inline void
+set_reg_list_stride_error (aarch64_operand_error *mismatch_detail, int idx,
+ int expected_num)
+{
+ if (mismatch_detail == NULL)
+ return;
+ set_error (mismatch_detail, AARCH64_OPDE_REG_LIST_STRIDE, idx, NULL);
mismatch_detail->data[0].i = 1 << expected_num;
}
@@ -1482,6 +1492,27 @@ check_reglane (const aarch64_opnd_info *opnd,
return true;
}
+/* Check that register list operand OPND has NUM_REGS registers and a
+ register stride of STRIDE. */
+
+static bool
+check_reglist (const aarch64_opnd_info *opnd,
+ aarch64_operand_error *mismatch_detail, int idx,
+ int num_regs, int stride)
+{
+ if (opnd->reglist.num_regs != num_regs)
+ {
+ set_reg_list_length_error (mismatch_detail, idx, num_regs);
+ return false;
+ }
+ if (opnd->reglist.stride != stride)
+ {
+ set_reg_list_stride_error (mismatch_detail, idx, stride);
+ return false;
+ }
+ return true;
+}
+
/* Check that indexed ZA operand OPND has:
- a selection register in the range [MIN_WREG, MIN_WREG + 3]
@@ -1637,11 +1668,8 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
case AARCH64_OPND_CLASS_SVE_REGLIST:
num = get_opcode_dependent_value (opcode);
- if (opnd->reglist.num_regs != num)
- {
- set_reg_list_error (mismatch_detail, idx, num);
- return 0;
- }
+ if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
+ return 0;
break;
case AARCH64_OPND_CLASS_ZA_ACCESS:
@@ -2123,26 +2151,25 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
assert (num >= 1 && num <= 4);
/* Unless LD1/ST1, the number of registers should be equal to that
of the structure elements. */
- if (num != 1 && opnd->reglist.num_regs != num)
- {
- set_reg_list_error (mismatch_detail, idx, num);
- return 0;
- }
+ if (num != 1 && !check_reglist (opnd, mismatch_detail, idx, num, 1))
+ return 0;
break;
case AARCH64_OPND_LVt_AL:
case AARCH64_OPND_LEt:
assert (num >= 1 && num <= 4);
/* The number of registers should be equal to that of the structure
elements. */
- if (opnd->reglist.num_regs != num)
- {
- set_reg_list_error (mismatch_detail, idx, num);
- return 0;
- }
+ if (!check_reglist (opnd, mismatch_detail, idx, num, 1))
+ return 0;
break;
default:
break;
}
+ if (opnd->reglist.stride != 1)
+ {
+ set_reg_list_stride_error (mismatch_detail, idx, 1);
+ return 0;
+ }
break;
case AARCH64_OPND_CLASS_IMMEDIATE:
@@ -3199,8 +3226,9 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
const char *prefix, struct aarch64_styler *styler)
{
const int num_regs = opnd->reglist.num_regs;
+ const int stride = opnd->reglist.stride;
const int first_reg = opnd->reglist.first_regno;
- const int last_reg = (first_reg + num_regs - 1) & 0x1f;
+ const int last_reg = (first_reg + (num_regs - 1) * stride) & 0x1f;
const char *qlf_name = aarch64_get_qualifier_name (opnd->qualifier);
char tb[16]; /* Temporary buffer. */
@@ -3218,16 +3246,16 @@ print_register_list (char *buf, size_t size, const aarch64_opnd_info *opnd,
/* The hyphenated form is preferred for disassembly if there are
more than two registers in the list, and the register numbers
are monotonically increasing in increments of one. */
- if (num_regs > 2 && last_reg > first_reg)
+ if (stride == 1 && num_regs > 2 && last_reg > first_reg)
snprintf (buf, size, "{%s-%s}%s",
style_reg (styler, "%s%d.%s", prefix, first_reg, qlf_name),
style_reg (styler, "%s%d.%s", prefix, last_reg, qlf_name), tb);
else
{
const int reg0 = first_reg;
- const int reg1 = (first_reg + 1) & 0x1f;
- const int reg2 = (first_reg + 2) & 0x1f;
- const int reg3 = (first_reg + 3) & 0x1f;
+ const int reg1 = (first_reg + stride) & 0x1f;
+ const int reg2 = (first_reg + stride * 2) & 0x1f;
+ const int reg3 = (first_reg + stride * 3) & 0x1f;
switch (num_regs)
{