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

Jiawei <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
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

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},
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.