diff options
-rw-r--r-- | gas/config/tc-aarch64.c | 58 | ||||
-rw-r--r-- | gas/testsuite/gas/aarch64/diagnostic.l | 2 | ||||
-rw-r--r-- | gas/testsuite/gas/aarch64/illegal-sve2.l | 19 | ||||
-rw-r--r-- | gas/testsuite/gas/aarch64/illegal-sve2.s | 1 | ||||
-rw-r--r-- | include/opcode/aarch64.h | 38 | ||||
-rw-r--r-- | opcodes/aarch64-dis.c | 5 | ||||
-rw-r--r-- | opcodes/aarch64-opc.c | 74 |
7 files changed, 135 insertions, 62 deletions
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index c6cc654..0acb364 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -5065,7 +5065,8 @@ const char* operand_mismatch_kind_names[] = "AARCH64_OPDE_SYNTAX_ERROR", "AARCH64_OPDE_FATAL_SYNTAX_ERROR", "AARCH64_OPDE_INVALID_VARIANT", - "AARCH64_OPDE_REG_LIST", + "AARCH64_OPDE_REG_LIST_LENGTH", + "AARCH64_OPDE_REG_LIST_STRIDE", "AARCH64_OPDE_UNTIED_IMMS", "AARCH64_OPDE_UNTIED_OPERAND", "AARCH64_OPDE_OUT_OF_RANGE", @@ -5092,10 +5093,11 @@ operand_error_higher_severity_p (enum aarch64_operand_error_kind lhs, gas_assert (AARCH64_OPDE_SYNTAX_ERROR > AARCH64_OPDE_EXPECTED_A_AFTER_B); gas_assert (AARCH64_OPDE_FATAL_SYNTAX_ERROR > AARCH64_OPDE_SYNTAX_ERROR); gas_assert (AARCH64_OPDE_INVALID_VARIANT > AARCH64_OPDE_FATAL_SYNTAX_ERROR); - gas_assert (AARCH64_OPDE_REG_LIST > AARCH64_OPDE_INVALID_VARIANT); - gas_assert (AARCH64_OPDE_OUT_OF_RANGE > AARCH64_OPDE_REG_LIST); + gas_assert (AARCH64_OPDE_REG_LIST_LENGTH > AARCH64_OPDE_INVALID_VARIANT); + gas_assert (AARCH64_OPDE_REG_LIST_STRIDE > AARCH64_OPDE_REG_LIST_LENGTH); + gas_assert (AARCH64_OPDE_OUT_OF_RANGE > AARCH64_OPDE_REG_LIST_STRIDE); gas_assert (AARCH64_OPDE_UNALIGNED > AARCH64_OPDE_OUT_OF_RANGE); - gas_assert (AARCH64_OPDE_OTHER_ERROR > AARCH64_OPDE_REG_LIST); + gas_assert (AARCH64_OPDE_OTHER_ERROR > AARCH64_OPDE_REG_LIST_STRIDE); gas_assert (AARCH64_OPDE_INVALID_REGNO > AARCH64_OPDE_OTHER_ERROR); return lhs > rhs; } @@ -5745,7 +5747,7 @@ output_operand_error_record (const operand_error_record *record, char *str) detail->data[0].i, idx + 1, str); break; - case AARCH64_OPDE_REG_LIST: + case AARCH64_OPDE_REG_LIST_LENGTH: if (detail->data[0].i == (1 << 1)) handler (_("expected a single-register list at operand %d -- `%s'"), idx + 1, str); @@ -5757,6 +5759,15 @@ output_operand_error_record (const operand_error_record *record, char *str) " at operand %d -- `%s'"), idx + 1, str); break; + case AARCH64_OPDE_REG_LIST_STRIDE: + if (detail->data[0].i == (1 << 1)) + handler (_("the register list must have a stride of %d" + " at operand %d -- `%s'"), 1, idx + 1, str); + else + handler (_("invalid register stride at operand %d -- `%s'"), + idx + 1, str); + break; + case AARCH64_OPDE_UNALIGNED: handler (_("immediate value must be a multiple of " "%d at operand %d -- `%s'"), @@ -5860,7 +5871,8 @@ output_operand_error_report (char *str, bool non_fatal_only) curr->detail.data[0].i, curr->detail.data[1].i, curr->detail.data[2].i); } - else if (curr->detail.kind == AARCH64_OPDE_REG_LIST) + else if (curr->detail.kind == AARCH64_OPDE_REG_LIST_LENGTH + || curr->detail.kind == AARCH64_OPDE_REG_LIST_STRIDE) { DEBUG_TRACE ("\t%s [%x]", operand_mismatch_kind_names[curr->detail.kind], @@ -5908,7 +5920,8 @@ output_operand_error_report (char *str, bool non_fatal_only) curr->detail.data[0].i, curr->detail.data[1].i, curr->detail.data[2].i); } - else if (kind == AARCH64_OPDE_REG_LIST) + else if (kind == AARCH64_OPDE_REG_LIST_LENGTH + || kind == AARCH64_OPDE_REG_LIST_STRIDE) { record->detail.data[0].i |= curr->detail.data[0].i; DEBUG_TRACE ("\t--> %s [%x]", @@ -6352,33 +6365,40 @@ ldst_lo12_determine_real_reloc_type (void) } /* Check whether a register list REGINFO is valid. The registers must be - numbered in increasing order (modulo 32), in increments of one or two. + numbered in increasing order (modulo 32). They must also have a + consistent stride. - If ACCEPT_ALTERNATE is non-zero, the register numbers should be in - increments of two. - - Return FALSE if such a register list is invalid, otherwise return TRUE. */ + Return true if the list is valid, describing it in LIST if so. */ static bool -reg_list_valid_p (uint32_t reginfo, int accept_alternate) +reg_list_valid_p (uint32_t reginfo, struct aarch64_reglist *list) { uint32_t i, nb_regs, prev_regno, incr; nb_regs = 1 + (reginfo & 0x3); reginfo >>= 2; prev_regno = reginfo & 0x1f; - incr = accept_alternate ? 2 : 1; + incr = 1; + + list->first_regno = prev_regno; + list->num_regs = nb_regs; for (i = 1; i < nb_regs; ++i) { - uint32_t curr_regno; + uint32_t curr_regno, curr_incr; reginfo >>= 5; curr_regno = reginfo & 0x1f; - if (curr_regno != ((prev_regno + incr) & 0x1f)) + curr_incr = (curr_regno - prev_regno) & 0x1f; + if (curr_incr == 0) + return false; + else if (i == 1) + incr = curr_incr; + else if (curr_incr != incr) return false; prev_regno = curr_regno; } + list->stride = incr; return true; } @@ -6628,6 +6648,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) goto failure; info->reglist.first_regno = reg->number; info->reglist.num_regs = 1; + info->reglist.stride = 1; } else { @@ -6635,7 +6656,7 @@ parse_operands (char *str, const aarch64_opcode *opcode) if (val == PARSE_FAIL) goto failure; - if (! reg_list_valid_p (val, /* accept_alternate */ 0)) + if (! reg_list_valid_p (val, &info->reglist)) { set_fatal_syntax_error (_("invalid register list")); goto failure; @@ -6647,9 +6668,6 @@ parse_operands (char *str, const aarch64_opcode *opcode) (_("expected element type rather than vector type")); goto failure; } - - info->reglist.first_regno = (val >> 2) & 0x1f; - info->reglist.num_regs = (val & 0x3) + 1; } if (operands[i] == AARCH64_OPND_LEt) { diff --git a/gas/testsuite/gas/aarch64/diagnostic.l b/gas/testsuite/gas/aarch64/diagnostic.l index 6d59564..85ec9fe 100644 --- a/gas/testsuite/gas/aarch64/diagnostic.l +++ b/gas/testsuite/gas/aarch64/diagnostic.l @@ -78,7 +78,7 @@ [^:]*:80: Error: immediate value out of range 0 to 15 at operand 1 -- `dmb #16' [^:]*:81: Error: immediate value out of range 0 to 31 at operand 2 -- `tbz w0,#40,0x17c' [^:]*:82: Error: expected a list of 2 registers at operand 1 -- `st2 \{v4.2d,v5.2d,v6.2d\},\[x3\]' -[^:]*:83: Error: invalid register list at operand 1 -- `ld2 \{v1.4h,v0.4h\},\[x1\]' +[^:]*:83: Error: the register list must have a stride of 1 at operand 1 -- `ld2 \{v1.4h,v0.4h\},\[x1\]' [^:]*:84: Error: the specified option is not accepted in ISB at operand 1 -- `isb osh' [^:]*:85: Error: invalid address at operand 2 -- `st2 \{v4.2d,v5.2d,v6.2d\},\\\[x3\\\]' [^:]*:86: Error: immediate value must be a multiple of 4 at operand 3 -- `ldnp w7,w15,\[x3,#3\]' diff --git a/gas/testsuite/gas/aarch64/illegal-sve2.l b/gas/testsuite/gas/aarch64/illegal-sve2.l index 369c0e6..48281fc 100644 --- a/gas/testsuite/gas/aarch64/illegal-sve2.l +++ b/gas/testsuite/gas/aarch64/illegal-sve2.l @@ -239,7 +239,7 @@ [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `eortb z0\.s,z32\.s,z0\.s' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `eortb z0\.s,z0\.s,z32\.s' [^ :]+:[0-9]+: Error: syntax error in register list at operand 2 -- `ext z0\.b,{,},#0' -[^ :]+:[0-9]+: Error: invalid register list at operand 2 -- `ext z0\.b,{z0\.b,z2\.b},#0' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `ext z0\.b,{z0\.b,z2\.b},#0' [^ :]+:[0-9]+: Error: operand mismatch -- `ext z0\.h,{z0\.b,z1\.b},#0' [^ :]+:[0-9]+: Info: did you mean this\? [^ :]+:[0-9]+: Info: ext z0\.b, {z0\.b, z1\.b}, #0 @@ -251,8 +251,8 @@ [^ :]+:[0-9]+: Error: expected a list of 2 registers at operand 2 -- `ext z0\.b,{z0\.b,z1\.b,z2\.b},#0' [^ :]+:[0-9]+: Error: expected a list of 2 registers at operand 2 -- `ext z0\.b,{z0\.b},#0' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `ext z0\.b,z0\.b,#0' -[^ :]+:[0-9]+: Error: invalid register list at operand 2 -- `ext z0\.b,{z31\.b,z1\.b},#0' -[^ :]+:[0-9]+: Error: invalid register list at operand 2 -- `ext z0\.b,{z0\.b,z31\.b},#0' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `ext z0\.b,{z31\.b,z1\.b},#0' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `ext z0\.b,{z0\.b,z31\.b},#0' [^ :]+:[0-9]+: Error: immediate value out of range 0 to 255 at operand 3 -- `ext z0\.b,{z0\.b,z1\.b},#256' [^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `ext z32\.b,{z0\.b,z1\.b},#0' [^ :]+:[0-9]+: Error: operand 2 must be a list of SVE vector registers -- `ext z0\.b,{z31\.b,z32\.b},#0' @@ -1277,7 +1277,7 @@ [^ :]+:[0-9]+: Info: other valid variant\(s\): [^ :]+:[0-9]+: Info: smullt z0\.s, z0\.h, z0\.h [^ :]+:[0-9]+: Info: smullt z0\.d, z0\.s, z0\.s -[^ :]+:[0-9]+: Error: invalid register list at operand 3 -- `splice z0\.b,p0,{z0\.b,z2\.b}' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 3 -- `splice z0\.b,p0,{z0\.b,z2\.b}' [^ :]+:[0-9]+: Error: operand mismatch -- `splice z0\.h,p0,{z0\.b,z1\.b}' [^ :]+:[0-9]+: Info: did you mean this\? [^ :]+:[0-9]+: Info: splice z0\.b, p0, {z0\.b, z1\.b} @@ -1289,7 +1289,7 @@ [^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 3 -- `splice z0\.b,p0,{z0\.b,z1\.h}' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 1 -- `splice z32\.b,p0,{z0\.b,z1\.b}' [^ :]+:[0-9]+: Error: p0-p7 expected at operand 2 -- `splice z0\.b,p8,{z0\.b,z1\.b}' -[^ :]+:[0-9]+: Error: invalid register list at operand 3 -- `splice z0\.b,p0,{z31\.b,z1\.b}' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 3 -- `splice z0\.b,p0,{z31\.b,z1\.b}' [^ :]+:[0-9]+: Error: operand 3 must be a list of SVE vector registers -- `splice z0\.b,p0,{z31\.b,z32\.b}' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `splice z0\.b,p0,{z32\.b,z1\.b}' [^ :]+:[0-9]+: Error: expected a register at operand 1 -- `sqabs z32\.b,p0/m,z0\.b' @@ -2332,7 +2332,7 @@ [^ :]+:[0-9]+: Info: suqadd z0\.d, p0/m, z0\.d, z0\.d [^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `tbl z32\.b,{z0\.b,z1\.b},z0\.b' [^ :]+:[0-9]+: Error: operand 2 must be a list of SVE vector registers -- `tbl z0\.b,{z31\.b,z32\.b},z0\.b' -[^ :]+:[0-9]+: Error: invalid register list at operand 2 -- `tbl z0\.b,{z31\.b,z1\.b},z0\.b' +[^ :]+:[0-9]+: Error: the register list must have a stride of 1 at operand 2 -- `tbl z0\.b,{z31\.b,z1\.b},z0\.b' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `tbl z0\.b,{z0\.b,z1\.b},z32\.b' [^ :]+:[0-9]+: Error: operand mismatch -- `tbl z0\.b,{z0\.b,z1\.b},z0\.h' [^ :]+:[0-9]+: Info: did you mean this\? @@ -2344,6 +2344,13 @@ [^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 2 -- `tbl z0\.b,{z0\.b,z1\.h},z0\.b' [^ :]+:[0-9]+: Error: type mismatch in vector register list at operand 2 -- `tbl z0\.b,{z0\.h,z0\.b},z0\.b' [^ :]+:[0-9]+: Error: invalid register list at operand 2 -- `tbl z0\.h,{z0\.b,z0\.b},z0\.b' +[^ :]+:[0-9]+: Error: operand mismatch -- `tbl z0\.h,{z0\.b,z1\.b},z0\.b' +[^ :]+:[0-9]+: Info: did you mean this\? +[^ :]+:[0-9]+: Info: tbl z0\.b, {z0\.b, z1\.b}, z0\.b +[^ :]+:[0-9]+: Info: other valid variant\(s\): +[^ :]+:[0-9]+: Info: tbl z0\.h, {z0\.h, z1\.h}, z0\.h +[^ :]+:[0-9]+: Info: tbl z0\.s, {z0\.s, z1\.s}, z0\.s +[^ :]+:[0-9]+: Info: tbl z0\.d, {z0\.d, z1\.d}, z0\.d [^ :]+:[0-9]+: Error: expected a vector register at operand 1 -- `tbx z32\.h,z0\.b,z0\.b' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 2 -- `tbx z0\.h,z32\.b,z0\.b' [^ :]+:[0-9]+: Error: expected an SVE vector register at operand 3 -- `tbx z0\.h,z0\.b,z32\.b' diff --git a/gas/testsuite/gas/aarch64/illegal-sve2.s b/gas/testsuite/gas/aarch64/illegal-sve2.s index 4b6285c..172d0f4 100644 --- a/gas/testsuite/gas/aarch64/illegal-sve2.s +++ b/gas/testsuite/gas/aarch64/illegal-sve2.s @@ -1526,6 +1526,7 @@ tbl z0.b, { z0.b, z1.b }, z0.h tbl z0.b, { z0.b, z1.h }, z0.b tbl z0.b, { z0.h, z0.b }, z0.b tbl z0.h, { z0.b, z0.b }, z0.b +tbl z0.h, { z0.b, z1.b }, z0.b tbx z32.h, z0.b, z0.b tbx z0.h, z32.b, z0.b diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index 61afe56..ef59d53 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -1122,6 +1122,19 @@ struct aarch64_indexed_za unsigned v : 1; /* <HV> horizontal or vertical vector indicator. */ }; +/* Information about a list of registers. */ +struct aarch64_reglist +{ + unsigned first_regno : 8; + unsigned num_regs : 8; + /* The difference between the nth and the n+1th register. */ + unsigned stride : 8; + /* 1 if it is a list of reg element. */ + unsigned has_index : 1; + /* Lane index; valid only when has_index is 1. */ + int64_t index; +} reglist; + /* Structure representing an operand. */ struct aarch64_opnd_info @@ -1142,15 +1155,7 @@ struct aarch64_opnd_info int64_t index; } reglane; /* e.g. LVn. */ - struct - { - unsigned first_regno : 5; - unsigned num_regs : 3; - /* 1 if it is a list of reg element. */ - unsigned has_index : 1; - /* Lane index; valid only when has_index is 1. */ - int64_t index; - } reglist; + struct aarch64_reglist reglist; /* e.g. immediate or pc relative address offset. */ struct { @@ -1288,11 +1293,19 @@ struct aarch64_inst The following errors are only reported against an asm string that is syntactically valid and that has valid operand qualifiers. - AARCH64_OPDE_REG_LIST - Error about the register list operand having an unexpected number of + AARCH64_OPDE_REG_LIST_LENGTH + Error about a register list operand having an unexpected number of registers. This error is low severity because there might be another opcode entry that supports the given number of registers. + AARCH64_OPDE_REG_LIST_STRIDE + Error about a register list operand having the correct number + (and type) of registers, but an unexpected stride. This error is + more severe than AARCH64_OPDE_REG_LIST_LENGTH because it implies + that the length is known to be correct. However, it is lower than + many other errors, since some instructions have forms that share + the same number of registers but have different strides. + AARCH64_OPDE_UNTIED_IMMS The asm failed to use the same immediate for a destination operand and a tied source operand. @@ -1342,7 +1355,8 @@ enum aarch64_operand_error_kind AARCH64_OPDE_SYNTAX_ERROR, AARCH64_OPDE_FATAL_SYNTAX_ERROR, AARCH64_OPDE_INVALID_VARIANT, - AARCH64_OPDE_REG_LIST, + AARCH64_OPDE_REG_LIST_LENGTH, + AARCH64_OPDE_REG_LIST_STRIDE, AARCH64_OPDE_UNTIED_IMMS, AARCH64_OPDE_UNTIED_OPERAND, AARCH64_OPDE_OUT_OF_RANGE, diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index 05e285f..e722514 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 8a9e51f..4e950cf 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) { |