[2/2] RISC-V: Add Zvbdota extension support

Message ID 20260630033438.143289-2-jiawei@iscas.ac.cn
State New
Headers
Series [1/2] RISC-V: Add Zvdota extension classes |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm fail Patch failed to apply

Commit Message

Jiawei June 30, 2026, 3:34 a.m. UTC
  This patch supports the RISC-V Zvbdota family of batched dot-product
extensions [1].

Compared to the non-batched Zvdota family, Zvbdota computes up to eight
dot products at a time.  These instructions use an EMUL=8 `vs2` vector
register group and a scaled-by-8 `ci` immediate encoded in `vs2[2:0]`.
This patch adds assembler/disassembler support for those additional
operand constraints.

The Zvbdota extension family includes the following extensions:

* Zvqwbdota8i: batched dot product of 8-bit integers with 32-bit
  accumulation.
* Zvqwbdota16i: batched dot product of 16-bit integers with 64-bit
  accumulation.
* Zvfwbdota16bf: batched dot product of bfloat16 floating-point numbers
  with 32-bit accumulation.
* Zvfqwbdota8f: batched dot product of 8-bit floating-point numbers with
  32-bit accumulation.
* Zvfbdota32f: batched dot product of 32-bit single-precision
  floating-point numbers with 32-bit accumulation.

[1] https://github.com/riscv/riscv-isa-manual/blob/zvbdot/src/zvdota.adoc

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_implicit_subsets): New implies.
	(riscv_supported_std_z_ext): New extensions.
	(riscv_multi_subset_supports): Ditto.
	(riscv_multi_subset_supports_ext): Ditto.

gas/ChangeLog:

	* NEWS: Add zvqwbdota8i, zvqwbdota16i, zvfwbdota16bf,
	zvfqwbdota8f and zvfbdota32f extensions.
	* config/tc-riscv.c (validate_riscv_insn): Add Zvbdota operand
	type 'q' and 'r' bits validation.
	(riscv_vtype_altfmt_supported): Add Zvbdota extensions.
	(my_getVsetvliExpression): Update altfmt error message.
	(riscv_ip): Add 'q' operand for VS2 EMUL=8 alignment check
	and 'r' operand for ci immediate.
	* testsuite/gas/riscv/march-help.l: Ditto.
	* testsuite/gas/riscv/zvbdota.d: New test.
	* testsuite/gas/riscv/zvbdota.s: Ditto.
	* testsuite/gas/riscv/zvbdota-operands-fail.d: Ditto.
	* testsuite/gas/riscv/zvbdota-operands-fail.l: Ditto.
	* testsuite/gas/riscv/zvbdota-operands-fail.s: Ditto.
	* testsuite/gas/riscv/zvbdota-zvqwbdota16i.d: Ditto.
	* testsuite/gas/riscv/zvbdota-zvqwbdota16i.s: Ditto.

include/ChangeLog:

	* opcode/riscv-opc.h (MATCH_VQWBDOTAU_VV, MASK_VQWBDOTAU_VV):
	New encoding.
	(MATCH_VQWBDOTAS_VV, MASK_VQWBDOTAS_VV): Ditto.
	(MATCH_VFWBDOTA_VV, MASK_VFWBDOTA_VV): Ditto.
	(MATCH_VFQWBDOTA_VV, MASK_VFQWBDOTA_VV): Ditto.
	(MATCH_VFQWBDOTA_ALT_VV, MASK_VFQWBDOTA_ALT_VV): Ditto.
	(MATCH_VFBDOTA_VV, MASK_VFBDOTA_VV): Ditto.
	(DECLARE_INSN): New declarations.
	* opcode/riscv.h (enum riscv_insn_class): New extension classes.

opcodes/ChangeLog:

	* riscv-dis.c (print_insn_args): Add 'q' and 'r' operand types
	for Zvbdota.
	* riscv-opc.c (riscv_opcodes): New instructions.
---
 bfd/elfxx-riscv.c                             | 35 ++++++++++++++++++
 gas/NEWS                                      |  4 +-
 gas/config/tc-riscv.c                         | 37 ++++++++++++++++++-
 gas/testsuite/gas/riscv/march-help.l          |  5 +++
 .../gas/riscv/zvbdota-operands-fail.d         |  3 ++
 .../gas/riscv/zvbdota-operands-fail.l         |  4 ++
 .../gas/riscv/zvbdota-operands-fail.s         |  4 ++
 .../gas/riscv/zvbdota-zvqwbdota16i.d          | 11 ++++++
 .../gas/riscv/zvbdota-zvqwbdota16i.s          |  3 ++
 gas/testsuite/gas/riscv/zvbdota.d             | 23 ++++++++++++
 gas/testsuite/gas/riscv/zvbdota.s             | 15 ++++++++
 include/opcode/riscv-opc.h                    | 20 ++++++++++
 include/opcode/riscv.h                        |  6 +++
 opcodes/riscv-dis.c                           | 11 ++++++
 opcodes/riscv-opc.c                           |  8 ++++
 15 files changed, 187 insertions(+), 2 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/zvbdota-operands-fail.d
 create mode 100644 gas/testsuite/gas/riscv/zvbdota-operands-fail.l
 create mode 100644 gas/testsuite/gas/riscv/zvbdota-operands-fail.s
 create mode 100644 gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.d
 create mode 100644 gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.s
 create mode 100644 gas/testsuite/gas/riscv/zvbdota.d
 create mode 100644 gas/testsuite/gas/riscv/zvbdota.s
  

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 44bdb5f2a99..e1639cbc2cb 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1239,8 +1239,13 @@  static const struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"zvfhmin", "+zve32f", check_implicit_always},
   {"zvfbfwma", "+zve32f,+zfbfmin", check_implicit_always},
   {"zvfbfmin", "+zve32f", check_implicit_always},
+  {"zvfbdota32f", "+zve32f", check_implicit_always},
+  {"zvfqwbdota8f", "+zve32f", check_implicit_always},
   {"zvfqwdota8f", "+zve32f", check_implicit_always},
+  {"zvfwbdota16bf", "+zve32f", check_implicit_always},
   {"zvfwdota16bf", "+zve32f", check_implicit_always},
+  {"zvqwbdota8i", "+zve32x", check_implicit_always},
+  {"zvqwbdota16i", "+zve64x", check_implicit_always},
   {"zvqwdota8i", "+zve32x", check_implicit_always},
   {"zvqwdota16i", "+zve64x", check_implicit_always},
   {"zve64d", "+d,+zve64f", check_implicit_always},
@@ -1524,11 +1529,14 @@  static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zvabd",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvbb",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvbc",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
+  {"zvfbdota32f",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfbfmin",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfbfwma",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfh",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfhmin",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
+  {"zvfqwbdota8f",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfqwdota8f",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
+  {"zvfwbdota16bf",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvfwdota16bf",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvkb",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvkg",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
@@ -1544,6 +1552,8 @@  static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zvksg",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvksc",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvkt",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
+  {"zvqwbdota8i",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
+  {"zvqwbdota16i",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvqwdota8i",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvqwdota16i",	ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
   {"zvl32b",		ISA_SPEC_CLASS_DRAFT,		1, 0, 0 },
@@ -2993,8 +3003,14 @@  riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "zvfbfmin");
     case INSN_CLASS_ZVFBFWMA:
       return riscv_subset_supports (rps, "zvfbfwma");
+    case INSN_CLASS_ZVFBDOTA32F:
+      return riscv_subset_supports (rps, "zvfbdota32f");
+    case INSN_CLASS_ZVFQWBDOTA8F:
+      return riscv_subset_supports (rps, "zvfqwbdota8f");
     case INSN_CLASS_ZVFQWDOTA8F:
       return riscv_subset_supports (rps, "zvfqwdota8f");
+    case INSN_CLASS_ZVFWBDOTA16BF:
+      return riscv_subset_supports (rps, "zvfwbdota16bf");
     case INSN_CLASS_ZVFWDOTA16BF:
       return riscv_subset_supports (rps, "zvfwdota16bf");
     case INSN_CLASS_ZVKB:
@@ -3010,6 +3026,13 @@  riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "zvksed");
     case INSN_CLASS_ZVKSH:
       return riscv_subset_supports (rps, "zvksh");
+    case INSN_CLASS_ZVQWBDOTA8I:
+      return riscv_subset_supports (rps, "zvqwbdota8i");
+    case INSN_CLASS_ZVQWBDOTA16I:
+      return riscv_subset_supports (rps, "zvqwbdota16i");
+    case INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I:
+      return (riscv_subset_supports (rps, "zvqwbdota8i")
+	      || riscv_subset_supports (rps, "zvqwbdota16i"));
     case INSN_CLASS_ZVQWDOTA8I:
       return riscv_subset_supports (rps, "zvqwdota8i");
     case INSN_CLASS_ZVQWDOTA16I:
@@ -3331,8 +3354,14 @@  riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "zvfbfmin";
     case INSN_CLASS_ZVFBFWMA:
       return "zvfbfwma";
+    case INSN_CLASS_ZVFBDOTA32F:
+      return "zvfbdota32f";
+    case INSN_CLASS_ZVFQWBDOTA8F:
+      return "zvfqwbdota8f";
     case INSN_CLASS_ZVFQWDOTA8F:
       return "zvfqwdota8f";
+    case INSN_CLASS_ZVFWBDOTA16BF:
+      return "zvfwbdota16bf";
     case INSN_CLASS_ZVFWDOTA16BF:
       return "zvfwdota16bf";
     case INSN_CLASS_ZVKB:
@@ -3347,6 +3376,12 @@  riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return _("zvksed");
     case INSN_CLASS_ZVKSH:
       return _("zvksh");
+    case INSN_CLASS_ZVQWBDOTA8I:
+      return "zvqwbdota8i";
+    case INSN_CLASS_ZVQWBDOTA16I:
+      return "zvqwbdota16i";
+    case INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I:
+      return _("zvqwbdota8i' or `zvqwbdota16i");
     case INSN_CLASS_ZVQWDOTA8I:
       return "zvqwdota8i";
     case INSN_CLASS_ZVQWDOTA16I:
diff --git a/gas/NEWS b/gas/NEWS
index c3e254689e0..b36bcb5cf3d 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -7,7 +7,9 @@ 
 
 * Add support for RISC-V standard extensions:
   zalasr v1.0, svrsw60t59b v1.0, zvabd v1.0, smpmpmt v1.0,
-  zvqwdota8i, zvqwdota16i, zvfwdota16bf and zvfqwdota8f v1.0.
+  zvqwdota8i, zvqwdota16i, zvfwdota16bf and zvfqwdota8f v1.0,
+  zvqwbdota8i, zvqwbdota16i, zvfwbdota16bf, zvfqwbdota8f and
+  zvfbdota32f v1.0.
 
 * Add support for RISC-V vendor extensions:
   SpacemiT: xsmtvdot v1.0, xsmtvdotii v1.0.
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 53cc234cde4..0f3283cbb96 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1568,6 +1568,8 @@  validate_riscv_insn (const struct riscv_opcode *opc, int length)
 	    case 'e': USE_BITS (OP_MASK_VWD, OP_SH_VWD); break;
 	    case 's': USE_BITS (OP_MASK_VS1, OP_SH_VS1); break;
 	    case 't': USE_BITS (OP_MASK_VS2, OP_SH_VS2); break;
+	    case 'q': USE_BITS (0x3, OP_SH_VS2 + 3); break;
+	    case 'r': USE_BITS (0x7, OP_SH_VS2); break;
 	    case 'u': USE_BITS (OP_MASK_VS1, OP_SH_VS1);
 		      USE_BITS (OP_MASK_VS2, OP_SH_VS2); break;
 	    case 'v': USE_BITS (OP_MASK_VD, OP_SH_VD);
@@ -2697,8 +2699,12 @@  riscv_vtype_altfmt_supported (void)
 {
   return (riscv_subset_supports (&riscv_rps_as, "zvfbfa")
 	  || riscv_subset_supports (&riscv_rps_as, "zvfofp8min")
+	  || riscv_subset_supports (&riscv_rps_as, "zvfqwbdota8f")
 	  || riscv_subset_supports (&riscv_rps_as, "zvfqwdota8f")
+	  || riscv_subset_supports (&riscv_rps_as, "zvfwbdota16bf")
 	  || riscv_subset_supports (&riscv_rps_as, "zvfwdota16bf")
+	  || riscv_subset_supports (&riscv_rps_as, "zvqwbdota8i")
+	  || riscv_subset_supports (&riscv_rps_as, "zvqwbdota16i")
 	  || riscv_subset_supports (&riscv_rps_as, "zvqwdota8i")
 	  || riscv_subset_supports (&riscv_rps_as, "zvqwdota16i"));
 }
@@ -2720,7 +2726,7 @@  my_getVsetvliExpression (expressionS *ep, char *str)
 	as_bad (_("multiple vsew constants"));
       if (!riscv_vtype_altfmt_supported ())
 	as_bad (_("symbolic vtype altfmt requires `zvfbfa', "
-		  "`zvfofp8min' or a `zvdota' extension"));
+		  "`zvfofp8min' or an altfmt dot-product extension"));
       altfmt_value = 1 << OP_SH_VTYPE_ALTFMT;
       vsew_found = true;
     }
@@ -3376,6 +3382,35 @@  riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 		  INSERT_OPERAND (VS2, *ip, regno);
 		  continue;
 
+		case 'q': /* Zvbdota VS2 group base.  */
+		  if (!reg_lookup (&asarg, RCLASS_VECR, &regno))
+		    break;
+		  if (regno & 0x7)
+		    as_bad (_("vector register must be aligned to an "
+			      "EMUL=8 group"));
+		  INSERT_BITS (ip->insn_opcode, regno & 0x18, 0x18,
+			       OP_SH_VS2);
+		  continue;
+
+		case 'r': /* Zvbdota ci immediate in VS2.  */
+		  {
+		    offsetT ci;
+
+		    my_getExpression (imm_expr, asarg, force_reloc);
+		    check_absolute_expr (ip, imm_expr, false);
+		    ci = imm_expr->X_add_number;
+		    if (ci < 0 || ci > 56 || (ci & 0x7))
+		      {
+			as_bad (_("bad value for Zvbdota ci immediate field, "
+				  "value must be a multiple of 8 in 0..56"));
+			ci = 0;
+		      }
+		    INSERT_BITS (ip->insn_opcode, ci / 8, 0x7, OP_SH_VS2);
+		    imm_expr->X_op = O_absent;
+		    asarg = expr_parse_end;
+		    continue;
+		  }
+
 		case 'u': /* VS1 == VS2 */
 		  if (!reg_lookup (&asarg, RCLASS_VECR, &regno))
 		    break;
diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l
index 2b5efe808d6..142369b6b1d 100644
--- a/gas/testsuite/gas/riscv/march-help.l
+++ b/gas/testsuite/gas/riscv/march-help.l
@@ -72,11 +72,14 @@  All available -march extensions for RISC-V:
 	zvabd                                   1.0
 	zvbb                                    1.0
 	zvbc                                    1.0
+	zvfbdota32f                             1.0
 	zvfbfmin                                1.0
 	zvfbfwma                                1.0
 	zvfh                                    1.0
 	zvfhmin                                 1.0
+	zvfqwbdota8f                            1.0
 	zvfqwdota8f                             1.0
+	zvfwbdota16bf                           1.0
 	zvfwdota16bf                            1.0
 	zvkb                                    1.0
 	zvkg                                    1.0
@@ -92,6 +95,8 @@  All available -march extensions for RISC-V:
 	zvksg                                   1.0
 	zvksc                                   1.0
 	zvkt                                    1.0
+	zvqwbdota8i                             1.0
+	zvqwbdota16i                            1.0
 	zvqwdota8i                              1.0
 	zvqwdota16i                             1.0
 	zvl32b                                  1.0
diff --git a/gas/testsuite/gas/riscv/zvbdota-operands-fail.d b/gas/testsuite/gas/riscv/zvbdota-operands-fail.d
new file mode 100644
index 00000000000..32028f6bb8c
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota-operands-fail.d
@@ -0,0 +1,3 @@ 
+#as: -march=rv64gc_zvqwbdota8i
+#source: zvbdota-operands-fail.s
+#error_output: zvbdota-operands-fail.l
diff --git a/gas/testsuite/gas/riscv/zvbdota-operands-fail.l b/gas/testsuite/gas/riscv/zvbdota-operands-fail.l
new file mode 100644
index 00000000000..6ba8dfca2e8
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota-operands-fail.l
@@ -0,0 +1,4 @@ 
+.*: Assembler messages:
+.*: Error: vector register must be aligned to an EMUL=8 group
+.*: Error: bad value for Zvbdota ci immediate field, value must be a multiple of 8 in 0..56
+.*: Error: bad value for Zvbdota ci immediate field, value must be a multiple of 8 in 0..56
diff --git a/gas/testsuite/gas/riscv/zvbdota-operands-fail.s b/gas/testsuite/gas/riscv/zvbdota-operands-fail.s
new file mode 100644
index 00000000000..0709892db8d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota-operands-fail.s
@@ -0,0 +1,4 @@ 
+target:
+	vqwbdotas.vv v16, v9, v31, 0
+	vqwbdotas.vv v16, v8, v31, 4
+	vqwbdotas.vv v16, v8, v31, 64
diff --git a/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.d b/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.d
new file mode 100644
index 00000000000..349cd81f759
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.d
@@ -0,0 +1,11 @@ 
+#as: -march=rv64gc_zvqwbdota16i
+#objdump: -dr
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+ba8f8877[ 	]+vqwbdotau.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+be9f8877[ 	]+vqwbdotas.vv[ 	]+v16,v8,v31,8
diff --git a/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.s b/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.s
new file mode 100644
index 00000000000..1a5bb4ef4bc
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota-zvqwbdota16i.s
@@ -0,0 +1,3 @@ 
+target:
+	vqwbdotau.vv v16, v8, v31, 0
+	vqwbdotas.vv v16, v8, v31, 8
diff --git a/gas/testsuite/gas/riscv/zvbdota.d b/gas/testsuite/gas/riscv/zvbdota.d
new file mode 100644
index 00000000000..63fa13853fa
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota.d
@@ -0,0 +1,23 @@ 
+#as: -march=rv64gc_zvqwbdota8i_zvqwbdota16i_zvfwbdota16bf_zvfqwbdota8f_zvfbdota32f
+#objdump: -dr
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+ba8f8877[ 	]+vqwbdotau.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+ba9f8877[ 	]+vqwbdotau.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+be8f8877[ 	]+vqwbdotas.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+be9f8877[ 	]+vqwbdotas.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+b28f9877[ 	]+vfwbdota.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+b29f9877[ 	]+vfwbdota.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+ba8f9877[ 	]+vfqwbdota.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+ba9f9877[ 	]+vfqwbdota.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+be8f9877[ 	]+vfqwbdota.alt.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+be9f9877[ 	]+vfqwbdota.alt.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+ae8f9877[ 	]+vfbdota.vv[ 	]+v16,v8,v31,0
+[ 	]+[0-9a-f]+:[ 	]+ae9f9877[ 	]+vfbdota.vv[ 	]+v16,v8,v31,8
+[ 	]+[0-9a-f]+:[ 	]+bc8f8877[ 	]+vqwbdotas.vv[ 	]+v16,v8,v31,0,v0.t
+[ 	]+[0-9a-f]+:[ 	]+b89f9877[ 	]+vfqwbdota.vv[ 	]+v16,v8,v31,8,v0.t
diff --git a/gas/testsuite/gas/riscv/zvbdota.s b/gas/testsuite/gas/riscv/zvbdota.s
new file mode 100644
index 00000000000..c87975a4cc9
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zvbdota.s
@@ -0,0 +1,15 @@ 
+target:
+	vqwbdotau.vv v16, v8, v31, 0
+	vqwbdotau.vv v16, v8, v31, 8
+	vqwbdotas.vv v16, v8, v31, 0
+	vqwbdotas.vv v16, v8, v31, 8
+	vfwbdota.vv v16, v8, v31, 0
+	vfwbdota.vv v16, v8, v31, 8
+	vfqwbdota.vv v16, v8, v31, 0
+	vfqwbdota.vv v16, v8, v31, 8
+	vfqwbdota.alt.vv v16, v8, v31, 0
+	vfqwbdota.alt.vv v16, v8, v31, 8
+	vfbdota.vv v16, v8, v31, 0
+	vfbdota.vv v16, v8, v31, 8
+	vqwbdotas.vv v16, v8, v31, 0, v0.t
+	vfqwbdota.vv v16, v8, v31, 8, v0.t
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 812f24c083c..6846655aeed 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2588,6 +2588,19 @@ 
 #define MASK_VFQWDOTA_VV 0xfc00707f
 #define MATCH_VFQWDOTA_ALT_VV 0x9c001077
 #define MASK_VFQWDOTA_ALT_VV 0xfc00707f
+/* Zvbdota instructions.  */
+#define MATCH_VQWBDOTAU_VV 0xb8000077
+#define MASK_VQWBDOTAU_VV 0xfc00707f
+#define MATCH_VQWBDOTAS_VV 0xbc000077
+#define MASK_VQWBDOTAS_VV 0xfc00707f
+#define MATCH_VFWBDOTA_VV 0xb0001077
+#define MASK_VFWBDOTA_VV 0xfc00707f
+#define MATCH_VFQWBDOTA_VV 0xb8001077
+#define MASK_VFQWBDOTA_VV 0xfc00707f
+#define MATCH_VFQWBDOTA_ALT_VV 0xbc001077
+#define MASK_VFQWBDOTA_ALT_VV 0xfc00707f
+#define MATCH_VFBDOTA_VV 0xac001077
+#define MASK_VFBDOTA_VV 0xfc00707f
 /* Vendor-specific (CORE-V) Xcvmac instructions.  */
 #define MATCH_CV_MAC       0x9000302b
 #define MASK_CV_MAC        0xfe00707f
@@ -4919,6 +4932,13 @@  DECLARE_INSN(vqwdotas_vv, MATCH_VQWDOTAS_VV, MASK_VQWDOTAS_VV)
 DECLARE_INSN(vfwdota_vv, MATCH_VFWDOTA_VV, MASK_VFWDOTA_VV)
 DECLARE_INSN(vfqwdota_vv, MATCH_VFQWDOTA_VV, MASK_VFQWDOTA_VV)
 DECLARE_INSN(vfqwdota_alt_vv, MATCH_VFQWDOTA_ALT_VV, MASK_VFQWDOTA_ALT_VV)
+/* Zvbdota instructions.  */
+DECLARE_INSN(vqwbdotau_vv, MATCH_VQWBDOTAU_VV, MASK_VQWBDOTAU_VV)
+DECLARE_INSN(vqwbdotas_vv, MATCH_VQWBDOTAS_VV, MASK_VQWBDOTAS_VV)
+DECLARE_INSN(vfwbdota_vv, MATCH_VFWBDOTA_VV, MASK_VFWBDOTA_VV)
+DECLARE_INSN(vfqwbdota_vv, MATCH_VFQWBDOTA_VV, MASK_VFQWBDOTA_VV)
+DECLARE_INSN(vfqwbdota_alt_vv, MATCH_VFQWBDOTA_ALT_VV, MASK_VFQWBDOTA_ALT_VV)
+DECLARE_INSN(vfbdota_vv, MATCH_VFBDOTA_VV, MASK_VFBDOTA_VV)
 /* Zvbb/Zvkb instructions.  */
 DECLARE_INSN(vandn_vv, MATCH_VANDN_VV, MASK_VANDN_VV)
 DECLARE_INSN(vandn_vx, MATCH_VANDN_VX, MASK_VANDN_VX)
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 45b6c7979db..f500b877ca6 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -562,7 +562,10 @@  enum riscv_insn_class
   INSN_CLASS_ZVBC,
   INSN_CLASS_ZVFBFMIN,
   INSN_CLASS_ZVFBFWMA,
+  INSN_CLASS_ZVFBDOTA32F,
+  INSN_CLASS_ZVFQWBDOTA8F,
   INSN_CLASS_ZVFQWDOTA8F,
+  INSN_CLASS_ZVFWBDOTA16BF,
   INSN_CLASS_ZVFWDOTA16BF,
   INSN_CLASS_ZVKB,
   INSN_CLASS_ZVKG,
@@ -571,6 +574,9 @@  enum riscv_insn_class
   INSN_CLASS_ZVKSED,
   INSN_CLASS_ZVKSH,
   INSN_CLASS_ZVABD,
+  INSN_CLASS_ZVQWBDOTA8I,
+  INSN_CLASS_ZVQWBDOTA16I,
+  INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I,
   INSN_CLASS_ZVQWDOTA8I,
   INSN_CLASS_ZVQWDOTA16I,
   INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I,
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 86dbdb18456..724c8b90b12 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -440,6 +440,17 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	      print (info->stream, dis_style_register, "%s",
 		     riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]);
 	      break;
+	    case 'q':
+	      {
+		unsigned int vs2 = EXTRACT_OPERAND (VS2, l);
+		print (info->stream, dis_style_register, "%s",
+		       riscv_vecr_names_numeric[vs2 & 0x18]);
+	      }
+	      break;
+	    case 'r':
+	      print (info->stream, dis_style_immediate, "%u",
+		     (unsigned int) (EXTRACT_OPERAND (VS2, l) & 0x7) * 8);
+	      break;
 	    case '0':
 	      print (info->stream, dis_style_register, "%s",
 		     riscv_vecr_names_numeric[0]);
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index cfec774ecdb..cd1e2910307 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -2257,6 +2257,14 @@  const struct riscv_opcode riscv_opcodes[] =
 {"vfqwdota.vv", 0, INSN_CLASS_ZVFQWDOTA8F, "Vd,Vt,VsVm", MATCH_VFQWDOTA_VV, MASK_VFQWDOTA_VV, match_opcode, 0},
 {"vfqwdota.alt.vv", 0, INSN_CLASS_ZVFQWDOTA8F, "Vd,Vt,VsVm", MATCH_VFQWDOTA_ALT_VV, MASK_VFQWDOTA_ALT_VV, match_opcode, 0},
 
+/* Zvbdota instructions.  */
+{"vqwbdotau.vv", 0, INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I, "Vd,Vq,Vs,VrVm", MATCH_VQWBDOTAU_VV, MASK_VQWBDOTAU_VV, match_opcode, 0},
+{"vqwbdotas.vv", 0, INSN_CLASS_ZVQWBDOTA8I_OR_ZVQWBDOTA16I, "Vd,Vq,Vs,VrVm", MATCH_VQWBDOTAS_VV, MASK_VQWBDOTAS_VV, match_opcode, 0},
+{"vfwbdota.vv",  0, INSN_CLASS_ZVFWBDOTA16BF, "Vd,Vq,Vs,VrVm", MATCH_VFWBDOTA_VV, MASK_VFWBDOTA_VV, match_opcode, 0},
+{"vfqwbdota.vv", 0, INSN_CLASS_ZVFQWBDOTA8F, "Vd,Vq,Vs,VrVm", MATCH_VFQWBDOTA_VV, MASK_VFQWBDOTA_VV, match_opcode, 0},
+{"vfqwbdota.alt.vv", 0, INSN_CLASS_ZVFQWBDOTA8F, "Vd,Vq,Vs,VrVm", MATCH_VFQWBDOTA_ALT_VV, MASK_VFQWBDOTA_ALT_VV, match_opcode, 0},
+{"vfbdota.vv",   0, INSN_CLASS_ZVFBDOTA32F, "Vd,Vq,Vs,VrVm", MATCH_VFBDOTA_VV, MASK_VFBDOTA_VV, match_opcode, 0},
+
 /* Zvbb/Zvkb instructions.  */
 {"vandn.vv",   0, INSN_CLASS_ZVKB, "Vd,Vt,VsVm", MATCH_VANDN_VV, MASK_VANDN_VV, match_opcode, 0},
 {"vandn.vx",   0, INSN_CLASS_ZVKB, "Vd,Vt,sVm", MATCH_VANDN_VX, MASK_VANDN_VX, match_opcode, 0},