[PATCH] RISC-V: Check register numbers for vector whole register op
zhuangqiubin@linux.spacemit.com
zhuangqiubin@linux.spacemit.com
Wed Nov 19 15:56:40 GMT 2025
From: Mark Zhuang <mark.zhuang@spacemit.com>
vector register numbers must be aligned appropriately
for the vector register group size
---
gas/config/tc-riscv.c | 72 +++++++++++++++
.../gas/riscv/vector-insns-fail-index.d | 3 +
.../gas/riscv/vector-insns-fail-index.l | 89 +++++++++++++++++++
.../gas/riscv/vector-insns-fail-index.s | 44 +++++++++
opcodes/riscv-dis.c | 6 ++
opcodes/riscv-opc.c | 46 +++++-----
6 files changed, 237 insertions(+), 23 deletions(-)
create mode 100644 gas/testsuite/gas/riscv/vector-insns-fail-index.d
create mode 100644 gas/testsuite/gas/riscv/vector-insns-fail-index.l
create mode 100644 gas/testsuite/gas/riscv/vector-insns-fail-index.s
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index df60c206b82..b93be04542a 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1545,9 +1545,15 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
switch (*++oparg)
{
case 'd':
+ case 'w':
+ case 'x':
+ case 'y':
case 'f': USE_BITS (OP_MASK_VD, OP_SH_VD); break;
case 'e': USE_BITS (OP_MASK_VWD, OP_SH_VWD); break;
case 's': USE_BITS (OP_MASK_VS1, OP_SH_VS1); break;
+ case 'O':
+ case 'P':
+ case 'Q':
case 't': USE_BITS (OP_MASK_VS2, OP_SH_VS2); break;
case 'u': USE_BITS (OP_MASK_VS1, OP_SH_VS1);
USE_BITS (OP_MASK_VS2, OP_SH_VS2); break;
@@ -3274,6 +3280,39 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
break;
INSERT_OPERAND (VD, *ip, regno);
continue;
+ case 'w':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x1) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vd, must be a multiple of 2");
+ break;
+ }
+ INSERT_OPERAND (VD, *ip, regno);
+ continue;
+ case 'x':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x3) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vd, must be a multiple of 4");
+ break;
+ }
+ INSERT_OPERAND (VD, *ip, regno);
+ continue;
+ case 'y':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x7) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vd, must be a multiple of 8");
+ break;
+ }
+ INSERT_OPERAND (VD, *ip, regno);
+ continue;
case 'e': /* AMO VD */
if (reg_lookup (&asarg, RCLASS_GPR, ®no) && regno == 0)
@@ -3311,6 +3350,39 @@ riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
break;
INSERT_OPERAND (VS2, *ip, regno);
continue;
+ case 'O':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x1) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vs2, must be a multiple of 2");
+ break;
+ }
+ INSERT_OPERAND (VS2, *ip, regno);
+ continue;
+ case 'P':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x3) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vs2, must be a multiple of 4");
+ break;
+ }
+ INSERT_OPERAND (VS2, *ip, regno);
+ continue;
+ case 'Q':
+ if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
+ break;
+ if ((regno & 0x7) != 0)
+ {
+ error.msg = _("illegal operands");
+ as_bad ("bad index value for vs2, must be a multiple of 8");
+ break;
+ }
+ INSERT_OPERAND (VS2, *ip, regno);
+ continue;
case 'u': /* VS1 == VS2 */
if (!reg_lookup (&asarg, RCLASS_VECR, ®no))
diff --git a/gas/testsuite/gas/riscv/vector-insns-fail-index.d b/gas/testsuite/gas/riscv/vector-insns-fail-index.d
new file mode 100644
index 00000000000..fe05273d1b8
--- /dev/null
+++ b/gas/testsuite/gas/riscv/vector-insns-fail-index.d
@@ -0,0 +1,3 @@
+#as: -march=rv32iv
+#source: vector-insns-fail-index.s
+#error_output: vector-insns-fail-index.l
diff --git a/gas/testsuite/gas/riscv/vector-insns-fail-index.l b/gas/testsuite/gas/riscv/vector-insns-fail-index.l
new file mode 100644
index 00000000000..1c301bf5f96
--- /dev/null
+++ b/gas/testsuite/gas/riscv/vector-insns-fail-index.l
@@ -0,0 +1,89 @@
+.*Assembler messages:
+.*Error: bad index value for vd, must be a multiple of 2
+.*Error: illegal operands `vl2re8.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vl4re8.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vl4re8.v v2,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vl4re8.v v3,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v2,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v3,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v4,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v5,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v6,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vl8re8.v v7,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 2
+.*Error: illegal operands `vs2r.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vs4r.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vs4r.v v2,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vs4r.v v3,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v1,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v2,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v3,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v4,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v5,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v6,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vs8r.v v7,\(a0\)'
+.*Error: bad index value for vd, must be a multiple of 2
+.*Error: illegal operands `vmv2r.v v1,v0'
+.*Error: bad index value for vs2, must be a multiple of 2
+.*Error: illegal operands `vmv2r.v v0,v1'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v1,v0'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v2,v0'
+.*Error: bad index value for vd, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v3,v0'
+.*Error: bad index value for vs2, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v0,v1'
+.*Error: bad index value for vs2, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v0,v2'
+.*Error: bad index value for vs2, must be a multiple of 4
+.*Error: illegal operands `vmv4r.v v0,v3'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v1,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v2,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v3,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v4,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v5,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v6,v0'
+.*Error: bad index value for vd, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v7,v0'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v1'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v2'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v3'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v4'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v5'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v6'
+.*Error: bad index value for vs2, must be a multiple of 8
+.*Error: illegal operands `vmv8r.v v0,v7'
diff --git a/gas/testsuite/gas/riscv/vector-insns-fail-index.s b/gas/testsuite/gas/riscv/vector-insns-fail-index.s
new file mode 100644
index 00000000000..169cdc6c8e2
--- /dev/null
+++ b/gas/testsuite/gas/riscv/vector-insns-fail-index.s
@@ -0,0 +1,44 @@
+ vl2re8.v v1, (a0)
+ vl4re8.v v1, (a0)
+ vl4re8.v v2, (a0)
+ vl4re8.v v3, (a0)
+ vl8re8.v v1, (a0)
+ vl8re8.v v2, (a0)
+ vl8re8.v v3, (a0)
+ vl8re8.v v4, (a0)
+ vl8re8.v v5, (a0)
+ vl8re8.v v6, (a0)
+ vl8re8.v v7, (a0)
+ vs2r.v v1, (a0)
+ vs4r.v v1, (a0)
+ vs4r.v v2, (a0)
+ vs4r.v v3, (a0)
+ vs8r.v v1, (a0)
+ vs8r.v v2, (a0)
+ vs8r.v v3, (a0)
+ vs8r.v v4, (a0)
+ vs8r.v v5, (a0)
+ vs8r.v v6, (a0)
+ vs8r.v v7, (a0)
+ vmv2r.v v1, v0
+ vmv2r.v v0, v1
+ vmv4r.v v1, v0
+ vmv4r.v v2, v0
+ vmv4r.v v3, v0
+ vmv4r.v v0, v1
+ vmv4r.v v0, v2
+ vmv4r.v v0, v3
+ vmv8r.v v1, v0
+ vmv8r.v v2, v0
+ vmv8r.v v3, v0
+ vmv8r.v v4, v0
+ vmv8r.v v5, v0
+ vmv8r.v v6, v0
+ vmv8r.v v7, v0
+ vmv8r.v v0, v1
+ vmv8r.v v0, v2
+ vmv8r.v v0, v3
+ vmv8r.v v0, v4
+ vmv8r.v v0, v5
+ vmv8r.v v0, v6
+ vmv8r.v v0, v7
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index fa2d44af28f..e9910359790 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -419,6 +419,9 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
{
case 'd':
case 'f':
+ case 'w':
+ case 'x':
+ case 'y':
print (info->stream, dis_style_register, "%s",
riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]);
break;
@@ -437,6 +440,9 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
case 't':
case 'u': /* VS1 == VS2 already verified at this point. */
case 'v': /* VD == VS1 == VS2 already verified at this point. */
+ case 'O':
+ case 'P':
+ case 'Q':
print (info->stream, dis_style_register, "%s",
riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]);
break;
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index e6fe5e9afba..7dfa7e70ee1 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -1785,28 +1785,28 @@ const struct riscv_opcode riscv_opcodes[] =
{"vl1re32.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL1RE32V, MASK_VL1RE32V, match_opcode, INSN_DREF },
{"vl1re64.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL1RE64V, MASK_VL1RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
-{"vl2r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL2RE8V, MASK_VL2RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
-{"vl2re8.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL2RE8V, MASK_VL2RE8V, match_opcode, INSN_DREF },
-{"vl2re16.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL2RE16V, MASK_VL2RE16V, match_opcode, INSN_DREF },
-{"vl2re32.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL2RE32V, MASK_VL2RE32V, match_opcode, INSN_DREF },
-{"vl2re64.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL2RE64V, MASK_VL2RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
-
-{"vl4r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL4RE8V, MASK_VL4RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
-{"vl4re8.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL4RE8V, MASK_VL4RE8V, match_opcode, INSN_DREF },
-{"vl4re16.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL4RE16V, MASK_VL4RE16V, match_opcode, INSN_DREF },
-{"vl4re32.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL4RE32V, MASK_VL4RE32V, match_opcode, INSN_DREF },
-{"vl4re64.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL4RE64V, MASK_VL4RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
-
-{"vl8r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL8RE8V, MASK_VL8RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
-{"vl8re8.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL8RE8V, MASK_VL8RE8V, match_opcode, INSN_DREF },
-{"vl8re16.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL8RE16V, MASK_VL8RE16V, match_opcode, INSN_DREF },
-{"vl8re32.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL8RE32V, MASK_VL8RE32V, match_opcode, INSN_DREF },
-{"vl8re64.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VL8RE64V, MASK_VL8RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
+{"vl2r.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VL2RE8V, MASK_VL2RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
+{"vl2re8.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VL2RE8V, MASK_VL2RE8V, match_opcode, INSN_DREF },
+{"vl2re16.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VL2RE16V, MASK_VL2RE16V, match_opcode, INSN_DREF },
+{"vl2re32.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VL2RE32V, MASK_VL2RE32V, match_opcode, INSN_DREF },
+{"vl2re64.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VL2RE64V, MASK_VL2RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
+
+{"vl4r.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VL4RE8V, MASK_VL4RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
+{"vl4re8.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VL4RE8V, MASK_VL4RE8V, match_opcode, INSN_DREF },
+{"vl4re16.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VL4RE16V, MASK_VL4RE16V, match_opcode, INSN_DREF },
+{"vl4re32.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VL4RE32V, MASK_VL4RE32V, match_opcode, INSN_DREF },
+{"vl4re64.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VL4RE64V, MASK_VL4RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
+
+{"vl8r.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VL8RE8V, MASK_VL8RE8V, match_opcode, INSN_DREF|INSN_ALIAS },
+{"vl8re8.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VL8RE8V, MASK_VL8RE8V, match_opcode, INSN_DREF },
+{"vl8re16.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VL8RE16V, MASK_VL8RE16V, match_opcode, INSN_DREF },
+{"vl8re32.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VL8RE32V, MASK_VL8RE32V, match_opcode, INSN_DREF },
+{"vl8re64.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VL8RE64V, MASK_VL8RE64V, match_opcode, INSN_DREF|INSN_V_EEW64 },
{"vs1r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VS1RV, MASK_VS1RV, match_opcode, INSN_DREF },
-{"vs2r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VS2RV, MASK_VS2RV, match_opcode, INSN_DREF },
-{"vs4r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VS4RV, MASK_VS4RV, match_opcode, INSN_DREF },
-{"vs8r.v", 0, INSN_CLASS_V, "Vd,0(s)", MATCH_VS8RV, MASK_VS8RV, match_opcode, INSN_DREF },
+{"vs2r.v", 0, INSN_CLASS_V, "Vw,0(s)", MATCH_VS2RV, MASK_VS2RV, match_opcode, INSN_DREF },
+{"vs4r.v", 0, INSN_CLASS_V, "Vx,0(s)", MATCH_VS4RV, MASK_VS4RV, match_opcode, INSN_DREF },
+{"vs8r.v", 0, INSN_CLASS_V, "Vy,0(s)", MATCH_VS8RV, MASK_VS8RV, match_opcode, INSN_DREF },
{"vneg.v", 0, INSN_CLASS_V, "Vd,VtVm", MATCH_VRSUBVX, MASK_VRSUBVX | MASK_RS1, match_opcode, INSN_ALIAS },
@@ -2210,9 +2210,9 @@ const struct riscv_opcode riscv_opcodes[] =
{"vcompress.vm",0, INSN_CLASS_V, "Vd,Vt,Vs", MATCH_VCOMPRESSVM, MASK_VCOMPRESSVM, match_opcode, 0},
{"vmv1r.v", 0, INSN_CLASS_V, "Vd,Vt", MATCH_VMV1RV, MASK_VMV1RV, match_opcode, 0},
-{"vmv2r.v", 0, INSN_CLASS_V, "Vd,Vt", MATCH_VMV2RV, MASK_VMV2RV, match_opcode, 0},
-{"vmv4r.v", 0, INSN_CLASS_V, "Vd,Vt", MATCH_VMV4RV, MASK_VMV4RV, match_opcode, 0},
-{"vmv8r.v", 0, INSN_CLASS_V, "Vd,Vt", MATCH_VMV8RV, MASK_VMV8RV, match_opcode, 0},
+{"vmv2r.v", 0, INSN_CLASS_V, "Vw,VO", MATCH_VMV2RV, MASK_VMV2RV, match_opcode, 0},
+{"vmv4r.v", 0, INSN_CLASS_V, "Vx,VP", MATCH_VMV4RV, MASK_VMV4RV, match_opcode, 0},
+{"vmv8r.v", 0, INSN_CLASS_V, "Vy,VQ", MATCH_VMV8RV, MASK_VMV8RV, match_opcode, 0},
/* Zvfbfmin instructions. */
{"vfncvtbf16.f.f.w", 0, INSN_CLASS_ZVFBFMIN, "Vd,VtVm", MATCH_VFNCVTBF16_F_F_W, MASK_VFNCVTBF16_F_F_W, match_opcode, 0},
--
2.34.1
More information about the Binutils
mailing list