forked from Imagelibrary/binutils-gdb
aarch64; Add support for vector offset ranges
Some SME2 instructions operate on a range of consecutive ZA vectors. This is indicated by syntax such as: za[<Wv>, <imml>:<immh>] Like with the earlier vgx2 and vgx4 support, we get better error messages if the parser allows all ZA indices to have a range. We can then reject invalid cases during constraint checking.
This commit is contained in:
@@ -4550,6 +4550,29 @@ parse_sme_za_index (char **str, struct aarch64_indexed_za *opnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skip_past_char (str, ':'))
|
||||
{
|
||||
int64_t end;
|
||||
if (!parse_sme_immediate (str, &end))
|
||||
{
|
||||
set_syntax_error (_("expected a constant immediate offset"));
|
||||
return false;
|
||||
}
|
||||
if (end < opnd->index.imm)
|
||||
{
|
||||
set_syntax_error (_("the last offset is less than the"
|
||||
" first offset"));
|
||||
return false;
|
||||
}
|
||||
if (end == opnd->index.imm)
|
||||
{
|
||||
set_syntax_error (_("the last offset is equal to the"
|
||||
" first offset"));
|
||||
return false;
|
||||
}
|
||||
opnd->index.countm1 = (uint64_t) end - opnd->index.imm;
|
||||
}
|
||||
|
||||
opnd->group_size = 0;
|
||||
if (skip_past_char (str, ','))
|
||||
{
|
||||
|
||||
@@ -28,3 +28,16 @@
|
||||
[^:]*:[0-9]+: Error: unexpected vector group size at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,#0,vgx2\]'
|
||||
[^:]*:[0-9]+: Error: unexpected vector group size at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,#0,vgx4\]'
|
||||
[^:]*:[0-9]+: Error: invalid vector group size at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,#0,vgx8\]'
|
||||
[^:]*:[0-9]+: Error: the last offset is less than the first offset at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,1:0\]'
|
||||
[^:]*:[0-9]+: Error: the last offset is equal to the first offset at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,0:0\]'
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,0:1\]'
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,0:2\]'
|
||||
[^:]+:[0-9]+: Error: operand mismatch -- `mova z0\.b,p0/m,za0h\.h\[w12,0:1\]'
|
||||
[^:]+:[0-9]+: Info: did you mean this\?
|
||||
[^:]+:[0-9]+: Info: mova z0\.b, p0/m, za0h\.b\[w12, 0:1\]
|
||||
[^:]+:[0-9]+: Info: other valid variant\(s\):
|
||||
[^:]+:[0-9]+: Info: mova z0\.h, p0/m, za0h\.h\[w12, 0:1\]
|
||||
[^:]+:[0-9]+: Info: mova z0\.s, p0/m, za0h\.s\[w12, 0:1\]
|
||||
[^:]+:[0-9]+: Info: mova z0\.d, p0/m, za0h\.d\[w12, 0:1\]
|
||||
[^:]+:[0-9]+: Info: mova z0\.q, p0/m, za0h\.q\[w12, 0:1\]
|
||||
[^:]*:[0-9]+: Error: expected a constant immediate offset at operand 3 -- `mova z0.b,p0/m,za0h.b\[w12,0:foo\]'
|
||||
|
||||
@@ -34,3 +34,10 @@ mova z0.q, p0/m, za0v.q[w12, #1a2]
|
||||
mova z0.b, p0/m, za0h.b[w12, #0, vgx2]
|
||||
mova z0.b, p0/m, za0h.b[w12, #0, vgx4]
|
||||
mova z0.b, p0/m, za0h.b[w12, #0, vgx8]
|
||||
|
||||
mova z0.b, p0/m, za0h.b[w12, 1:0]
|
||||
mova z0.b, p0/m, za0h.b[w12, 0:0]
|
||||
mova z0.b, p0/m, za0h.b[w12, 0:1]
|
||||
mova z0.b, p0/m, za0h.b[w12, 0:2]
|
||||
mova z0.b, p0/m, za0h.h[w12, 0:1]
|
||||
mova z0.b, p0/m, za0h.b[w12, 0:foo]
|
||||
|
||||
@@ -62,3 +62,7 @@
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `ld1b {za0h\.b\[w12,0,vgx4\]},p0/m,\[x0\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: ld1b {za0h\.b\[w12, 0, vgx4\]}, p0/z, \[x0, xzr\]
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 1 -- `ld1b {za0h\.b\[w12,0:1\]},p0/z,\[x0\]'
|
||||
[^:]+:[0-9]+: Error: operand mismatch -- `ld1b {za0h\.b\[w12,0:1\]},p0/m,\[x0\]'
|
||||
[^:]+:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: ld1b {za0h\.b\[w12, 0:1\]}, p0/z, \[x0, xzr\]
|
||||
|
||||
@@ -63,3 +63,6 @@ ld1b {za0h.b[w12, 0, vgx4]}, p0/z, [x0]
|
||||
ld1b {za0h.b[w12, 0, vgx8]}, p0/z, [x0]
|
||||
|
||||
ld1b {za0h.b[w12, 0, vgx4]}, p0/m, [x0]
|
||||
|
||||
ld1b {za0h.b[w12, 0:1]}, p0/z, [x0]
|
||||
ld1b {za0h.b[w12, 0:1]}, p0/m, [x0]
|
||||
|
||||
@@ -49,3 +49,7 @@
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `st1b {za0h\.b\[w12,0,vgx2\]},p0/z,\[x0\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: st1b {za0h\.b\[w12, 0, vgx2\]}, p0, \[x0, xzr\]
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 1 -- `st1b {za0h\.b\[w12,0:1,vgx2\]},p0,\[x0\]'
|
||||
[^:]+:[0-9]+: Error: operand mismatch -- `st1b {za0h\.b\[w12,0:1,vgx2\]},p0/m,\[x0\]'
|
||||
[^:]+:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: st1b {za0h\.b\[w12, 0:1, vgx2\]}, p0, \[x0, xzr\]
|
||||
|
||||
@@ -50,3 +50,6 @@ st1b {za0h.b[w12, 0, vgx4]}, p0, [x0]
|
||||
st1b {za0h.b[w12, 0, vgx8]}, p0, [x0]
|
||||
|
||||
st1b {za0h.b[w12, 0, vgx2]}, p0/z, [x0]
|
||||
|
||||
st1b {za0h.b[w12, 0:1, vgx2]}, p0, [x0]
|
||||
st1b {za0h.b[w12, 0:1, vgx2]}, p0/m, [x0]
|
||||
|
||||
@@ -66,3 +66,11 @@
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `str za\.b\[w12,0,vgx4\],\[x0\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: str za\[w12, 0, vgx4\], \[x0\]
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 1 -- `ldr za\[w12,0:1\],\[x0\]'
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 1 -- `str za\[w12,0:2,vgx4\],\[x0\]'
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `ldr za\.b\[w12,0:1\],\[x0\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: ldr za\[w12, 0:1\], \[x0\]
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `str za\.b\[w12,0:2,vgx4\],\[x0\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: str za\[w12, 0:2, vgx4\], \[x0\]
|
||||
|
||||
@@ -63,3 +63,9 @@ str za[w12, 0, vgx8], [x0]
|
||||
|
||||
ldr za.b[w12, 0, vgx2], [x0]
|
||||
str za.b[w12, 0, vgx4], [x0]
|
||||
|
||||
ldr za[w12, 0:1], [x0]
|
||||
str za[w12, 0:2, vgx4], [x0]
|
||||
|
||||
ldr za.b[w12, 0:1], [x0]
|
||||
str za.b[w12, 0:2, vgx4], [x0]
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.h\[w12, 0\]
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.s\[w12, 0\]
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.d\[w12, 0\]
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 3 -- `psel p0,p0,p0\.b\[w12,0:1\]'
|
||||
[^:]*:[0-9]+: Error: expected a single offset rather than a range at operand 3 -- `psel p0,p0,p0\.b\[w12,0:1,vgx2\]'
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `psel p0\.b,p0\.b,p0\.b\[w12,0:1,vgx2\]'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.b\[w12, 0\]
|
||||
[^:]*:[0-9]+: Info: other valid variant\(s\):
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.h\[w12, 0\]
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.s\[w12, 0\]
|
||||
[^:]*:[0-9]+: Info: psel p0, p0, p0\.d\[w12, 0\]
|
||||
[^:]*:[0-9]+: Error: operand mismatch -- `revd z0.q,p0/m,z0.b'
|
||||
[^:]*:[0-9]+: Info: did you mean this\?
|
||||
[^:]*:[0-9]+: Info: revd z0.q, p0/m, z0.q
|
||||
|
||||
@@ -23,6 +23,10 @@ psel p0, p0, p0.b[w12, #0, vgx8]
|
||||
|
||||
psel p0.b, p0.b, p0.b[w12, #0, vgx2]
|
||||
|
||||
psel p0, p0, p0.b[w12, 0:1]
|
||||
psel p0, p0, p0.b[w12, 0:1, vgx2]
|
||||
psel p0.b, p0.b, p0.b[w12, 0:1, vgx2]
|
||||
|
||||
revd z0.q, p0/m, z0.b
|
||||
|
||||
sclamp z8.b, z1.b, z31.q
|
||||
|
||||
@@ -1114,14 +1114,29 @@ const aarch64_cond* get_inverted_cond (const aarch64_cond *cond);
|
||||
/* Information about a reference to part of ZA. */
|
||||
struct aarch64_indexed_za
|
||||
{
|
||||
int regno; /* <ZAn> */
|
||||
/* Which tile is being accessed. Unused (and 0) for an index into ZA. */
|
||||
int regno;
|
||||
|
||||
struct
|
||||
{
|
||||
int regno; /* <Wv> */
|
||||
int64_t imm; /* <imm> */
|
||||
/* The 32-bit index register. */
|
||||
int regno;
|
||||
|
||||
/* The first (or only) immediate offset. */
|
||||
int64_t imm;
|
||||
|
||||
/* The last immediate offset minus the first immediate offset.
|
||||
Unlike the range size, this is guaranteed not to overflow
|
||||
when the end offset > the start offset. */
|
||||
uint64_t countm1;
|
||||
} index;
|
||||
|
||||
/* The vector group size, or 0 if none. */
|
||||
unsigned group_size : 8;
|
||||
unsigned v : 1; /* <HV> horizontal or vertical vector indicator. */
|
||||
|
||||
/* True if a tile access is vertical, false if it is horizontal.
|
||||
Unused (and 0) for an index into ZA. */
|
||||
unsigned v : 1;
|
||||
};
|
||||
|
||||
/* Information about a list of registers. */
|
||||
|
||||
@@ -1527,14 +1527,18 @@ check_reglist (const aarch64_opnd_info *opnd,
|
||||
|
||||
- a selection register in the range [MIN_WREG, MIN_WREG + 3]
|
||||
|
||||
- an immediate offset in the range [0, MAX_VALUE].
|
||||
- RANGE_SIZE consecutive immediate offsets.
|
||||
|
||||
- an initial immediate offset that is a multiple of RANGE_SIZE
|
||||
in the range [0, MAX_VALUE * RANGE_SIZE]
|
||||
|
||||
- a vector group size of GROUP_SIZE. */
|
||||
|
||||
static bool
|
||||
check_za_access (const aarch64_opnd_info *opnd,
|
||||
aarch64_operand_error *mismatch_detail, int idx,
|
||||
int min_wreg, int max_value, int group_size)
|
||||
int min_wreg, int max_value, unsigned int range_size,
|
||||
int group_size)
|
||||
{
|
||||
if (!value_in_range_p (opnd->indexed_za.index.regno, min_wreg, min_wreg + 3))
|
||||
{
|
||||
@@ -1547,9 +1551,31 @@ check_za_access (const aarch64_opnd_info *opnd,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!value_in_range_p (opnd->indexed_za.index.imm, 0, max_value))
|
||||
int max_index = max_value * range_size;
|
||||
if (!value_in_range_p (opnd->indexed_za.index.imm, 0, max_index))
|
||||
{
|
||||
set_offset_out_of_range_error (mismatch_detail, idx, 0, max_value);
|
||||
set_offset_out_of_range_error (mismatch_detail, idx, 0, max_index);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((opnd->indexed_za.index.imm % range_size) != 0)
|
||||
{
|
||||
assert (range_size == 2 || range_size == 4);
|
||||
set_other_error (mismatch_detail, idx,
|
||||
range_size == 2
|
||||
? _("starting offset is not a multiple of 2")
|
||||
: _("starting offset is not a multiple of 4"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (opnd->indexed_za.index.countm1 != range_size - 1)
|
||||
{
|
||||
if (range_size == 1)
|
||||
set_other_error (mismatch_detail, idx,
|
||||
_("expected a single offset rather than"
|
||||
" a range"));
|
||||
else
|
||||
abort ();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1678,7 +1704,8 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
case AARCH64_OPND_SME_PnT_Wm_imm:
|
||||
size = aarch64_get_qualifier_esize (opnd->qualifier);
|
||||
max_value = 16 / size - 1;
|
||||
if (!check_za_access (opnd, mismatch_detail, idx, 12, max_value, 0))
|
||||
if (!check_za_access (opnd, mismatch_detail, idx,
|
||||
12, max_value, 1, 0))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
@@ -1701,13 +1728,13 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx,
|
||||
case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
|
||||
size = aarch64_get_qualifier_esize (opnd->qualifier);
|
||||
max_value = 16 / size - 1;
|
||||
if (!check_za_access (opnd, mismatch_detail, idx, 12, max_value,
|
||||
if (!check_za_access (opnd, mismatch_detail, idx, 12, max_value, 1,
|
||||
get_opcode_dependent_value (opcode)))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SME_ZA_array_off4:
|
||||
if (!check_za_access (opnd, mismatch_detail, idx, 12, 15,
|
||||
if (!check_za_access (opnd, mismatch_detail, idx, 12, 15, 1,
|
||||
get_opcode_dependent_value (opcode)))
|
||||
return 0;
|
||||
break;
|
||||
@@ -3694,7 +3721,7 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
case AARCH64_OPND_SME_ZA_HV_idx_src:
|
||||
case AARCH64_OPND_SME_ZA_HV_idx_dest:
|
||||
case AARCH64_OPND_SME_ZA_HV_idx_ldstr:
|
||||
snprintf (buf, size, "%s%s[%s, %s%s%s]%s",
|
||||
snprintf (buf, size, "%s%s[%s, %s%s%s%s%s]%s",
|
||||
opnd->type == AARCH64_OPND_SME_ZA_HV_idx_ldstr ? "{" : "",
|
||||
style_reg (styler, "za%d%c.%s",
|
||||
opnd->indexed_za.regno,
|
||||
@@ -3702,6 +3729,12 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
aarch64_get_qualifier_name (opnd->qualifier)),
|
||||
style_reg (styler, "w%d", opnd->indexed_za.index.regno),
|
||||
style_imm (styler, "%" PRIi64, opnd->indexed_za.index.imm),
|
||||
opnd->indexed_za.index.countm1 ? ":" : "",
|
||||
(opnd->indexed_za.index.countm1
|
||||
? style_imm (styler, "%d",
|
||||
opnd->indexed_za.index.imm
|
||||
+ opnd->indexed_za.index.countm1)
|
||||
: ""),
|
||||
opnd->indexed_za.group_size ? ", " : "",
|
||||
opnd->indexed_za.group_size == 2
|
||||
? style_sub_mnem (styler, "vgx2")
|
||||
@@ -3715,10 +3748,16 @@ aarch64_print_operand (char *buf, size_t size, bfd_vma pc,
|
||||
break;
|
||||
|
||||
case AARCH64_OPND_SME_ZA_array_off4:
|
||||
snprintf (buf, size, "%s[%s, %s%s%s]",
|
||||
snprintf (buf, size, "%s[%s, %s%s%s%s%s]",
|
||||
style_reg (styler, "za"),
|
||||
style_reg (styler, "w%d", opnd->indexed_za.index.regno),
|
||||
style_imm (styler, "%" PRIi64, opnd->indexed_za.index.imm),
|
||||
opnd->indexed_za.index.countm1 ? ":" : "",
|
||||
(opnd->indexed_za.index.countm1
|
||||
? style_imm (styler, "%d",
|
||||
opnd->indexed_za.index.imm
|
||||
+ opnd->indexed_za.index.countm1)
|
||||
: ""),
|
||||
opnd->indexed_za.group_size ? ", " : "",
|
||||
opnd->indexed_za.group_size == 2
|
||||
? style_sub_mnem (styler, "vgx2")
|
||||
|
||||
Reference in New Issue
Block a user