RISC-V: Add SpacemiT vendor extensions xsmtvdot

Message ID 20260409113757.3366131-2-zhuangqiubin@linux.spacemit.com
State New
Headers
Series RISC-V: Add SpacemiT vendor extensions xsmtvdot |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Build passed
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_check--master-arm success Test passed

Commit Message

Mark Zhuang April 9, 2026, 11:37 a.m. UTC
  From: Mark Zhuang <mark.zhuang@spacemit.com>

SpacemiT defines Intrinsic Matrix Extension (IME) specification [1].
SpacemiT X60 implement version 1.0 of the SpacemiT Vector Dot Product Extension (XsmtVdot v1.0) [2],
it is a subset of the full IME specification

[1] https://github.com/spacemit-com/riscv-ime-extension-spec/releases/download/v1.0/spacemit-ime-asciidoc.pdf
[2] https://developer.spacemit.com/documentation?token=BWbGwbx7liGW21kq9lucSA6Vnpb#2.1

Co-authored-by: Link <xuqian@spacemit.com>
---
 bfd/elfxx-riscv.c                         |  7 +++
 gas/NEWS                                  |  3 +
 gas/config/tc-riscv.c                     | 71 +++++++++++++++++++++
 gas/doc/c-riscv.texi                      |  7 +++
 gas/testsuite/gas/riscv/march-help.l      |  1 +
 gas/testsuite/gas/riscv/x-smt-vdot-fail.l |  3 +
 gas/testsuite/gas/riscv/x-smt-vdot-fail.s | 46 ++++++++++++++
 gas/testsuite/gas/riscv/x-smt-vdot.d      | 41 +++++++++++++
 gas/testsuite/gas/riscv/x-smt-vdot.s      | 33 ++++++++++
 include/opcode/riscv-opc.h                | 75 +++++++++++++++++++++++
 include/opcode/riscv.h                    | 10 +++
 opcodes/riscv-dis.c                       | 33 ++++++++++
 opcodes/riscv-opc.c                       | 45 ++++++++++++++
 13 files changed, 375 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/x-smt-vdot-fail.l
 create mode 100644 gas/testsuite/gas/riscv/x-smt-vdot-fail.s
 create mode 100644 gas/testsuite/gas/riscv/x-smt-vdot.d
 create mode 100644 gas/testsuite/gas/riscv/x-smt-vdot.s
  

Comments

Jan Beulich April 9, 2026, 12:21 p.m. UTC | #1
On 09.04.2026 13:37, Mark Zhuang wrote:
> --- a/gas/NEWS
> +++ b/gas/NEWS
> @@ -17,6 +17,9 @@ Changes in 2.46:
>  * Add support for RISC-V standard extensions:
>    sdtrig v1.0, ssstrict v1.0.
>  
> +* Add support for RISC-V vendor extensions:
> +  SpacemiT: xsmtvdot v1.0.
> +
>  * The assembler now supports generating SFrame Version 3 format.  This version
>    supports .text > 2 GiB, support for marking outermost frames, support for
>    marking signal trampolines, and support for "flexible" frames which have

This clearly is in need of adjustment. 2.46 has already gone out.

> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -1771,6 +1771,29 @@ validate_riscv_insn (const struct riscv_opcode *opc, int length)
>  		    goto unknown_validate_operand;
>  		}
>  		break;
> +	    case 'p': /* Vendor-specific (SpacemiT) operands.  */
> +		switch (*++oparg)
> +		{
> +		  case 'V':
> +		    switch (*++oparg)
> +			  {
> +			  case 'd': USE_BITS (OP_MASK_SPACEMIT_IME_VD, OP_SH_SPACEMIT_IME_VD); break;
> +			  case 's': USE_BITS (OP_MASK_SPACEMIT_IME_VS1, OP_SH_SPACEMIT_IME_VS1); break;
> +			  default:
> +			    goto unknown_validate_operand;
> +			  }
> +			  break;
> +		  case 'w': /* Xpw&S ... bits in S indicates whether corresponding item is permitted.  */
> +		    if (*++oparg != '&')
> +		      goto unknown_validate_operand;
> +		    strtol (oparg + 1, (char **)&oparg, 16);
> +		    oparg--;
> +		    USE_BITS (OP_MASK_SPACEMIT_IME_WI, OP_SH_SPACEMIT_IME_WI);
> +		    break;
> +		  default:
> +		    goto unknown_validate_operand;
> +		}
> +		break;
>  	    default:
>  	      goto unknown_validate_operand;
>  	    }

There look to be issues with indentation and line length throughout here. And
more further down, including in disassembler code.

> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -122,6 +122,12 @@ const char * const riscv_th_vediv[4] =
>      "d1", "d2", "d4", "d8"
>  };
>  
> +/* XSmtVdot, List of int type width constants.  */
> +const char * const riscv_smt_wi[4] =
> +{
> +    "i2", "i16", "i4", "i8"
> +};

Do you really need to use arg_lookup() for these, and hence do you really need
this table (requiring more space for the pointers than for the actual strings
pointed to)?

> @@ -3579,6 +3585,45 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"mips.sdp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm^(s)", MATCH_MIPS_SDP, MASK_MIPS_SDP, match_opcode, 0 },
>  {"mips.swp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm&(s)", MATCH_MIPS_SWP, MASK_MIPS_SWP, match_opcode, 0 },
>  
> +/* SpacemiT custom instructions. */
> +/* Int Matrix Multi-Accumulation */
> +{"smt.vmadot",   0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt",       MATCH_SMT_VMADOT_I8,   MASK_SMT_VMADOT_I8,   match_opcode, INSN_ALIAS },
> +{"smt.vmadot",   0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt,Xpw&8", MATCH_SMT_VMADOT,      MASK_SMT_VMADOT,      match_opcode, 0 },

Rather than having two entries each, can't you handle to Xpw&8 operand as an
optional one, like is done for Vm (and I'm soon to submit a patch to do the
same for floating point rounding mode operands)? We shouldn't grow this ever
growing table more than necessary, imo.

Jan
  

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index ee962b4f6f1..ea24a68b895 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1229,6 +1229,8 @@  static const struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"xtheadvector", "+zicsr", check_implicit_always},
   {"xtheadzvamo", "+zaamo", check_implicit_always},
 
+  {"xsmtvdot", "+zve32x", check_implicit_always},
+
   {"v", "+zve64d,+zvl128b", check_implicit_always},
   {"zvfh", "+zvfhmin,+zfhmin", check_implicit_always},
   {"zvfhmin", "+zve32f", check_implicit_always},
@@ -1644,6 +1646,7 @@  static const struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
   {"xmipscmov",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {"xmipsexectl",	ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {"xmipslsp",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
+  {"xsmtvdot",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {NULL, 0, 0, 0, 0}
 };
 
@@ -3062,6 +3065,8 @@  riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "xmipsexectl");
     case INSN_CLASS_XMIPSLSP:
       return riscv_subset_supports (rps, "xmipslsp");
+    case INSN_CLASS_XSMTVDOT:
+      return riscv_subset_supports (rps, "xsmtvdot");
     default:
       rps->error_handler
         (_("internal: unreachable INSN_CLASS_*"));
@@ -3365,6 +3370,8 @@  riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "xsfvqmaccdod";
     case INSN_CLASS_XSFVFNRCLIPXFQF:
       return "xsfvfnrclipxfqf";
+    case INSN_CLASS_XSMTVDOT:
+      return "xsmtvdot";
     default:
       rps->error_handler
         (_("internal: unreachable INSN_CLASS_*"));
diff --git a/gas/NEWS b/gas/NEWS
index e384d1135c0..123872e7c02 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -17,6 +17,9 @@  Changes in 2.46:
 * Add support for RISC-V standard extensions:
   sdtrig v1.0, ssstrict v1.0.
 
+* Add support for RISC-V vendor extensions:
+  SpacemiT: xsmtvdot v1.0.
+
 * The assembler now supports generating SFrame Version 3 format.  This version
   supports .text > 2 GiB, support for marking outermost frames, support for
   marking signal trampolines, and support for "flexible" frames which have
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 6bcf53832a0..25cafd83a95 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1771,6 +1771,29 @@  validate_riscv_insn (const struct riscv_opcode *opc, int length)
 		    goto unknown_validate_operand;
 		}
 		break;
+	    case 'p': /* Vendor-specific (SpacemiT) operands.  */
+		switch (*++oparg)
+		{
+		  case 'V':
+		    switch (*++oparg)
+			  {
+			  case 'd': USE_BITS (OP_MASK_SPACEMIT_IME_VD, OP_SH_SPACEMIT_IME_VD); break;
+			  case 's': USE_BITS (OP_MASK_SPACEMIT_IME_VS1, OP_SH_SPACEMIT_IME_VS1); break;
+			  default:
+			    goto unknown_validate_operand;
+			  }
+			  break;
+		  case 'w': /* Xpw&S ... bits in S indicates whether corresponding item is permitted.  */
+		    if (*++oparg != '&')
+		      goto unknown_validate_operand;
+		    strtol (oparg + 1, (char **)&oparg, 16);
+		    oparg--;
+		    USE_BITS (OP_MASK_SPACEMIT_IME_WI, OP_SH_SPACEMIT_IME_WI);
+		    break;
+		  default:
+		    goto unknown_validate_operand;
+		}
+		break;
 	    default:
 	      goto unknown_validate_operand;
 	    }
@@ -4287,6 +4310,54 @@  riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 		    }
 		  break;
 
+		case 'p': /* Vendor-specific (SpacemiT) operands.  */
+		  {
+		  size_t n;
+		  switch (*++oparg)
+		    {
+		    case 'V':
+		      switch (*++oparg)
+		      {
+			    case 'd':
+			      if (!reg_lookup (&asarg, RCLASS_VECR, &regno))
+				    break;
+			      if ((regno & 0x1) != 0)
+			      {
+				    error.msg = _("illegal operands (vd must be even)");
+				    break;
+			      }
+			      INSERT_OPERAND (SPACEMIT_IME_VD, *ip, regno>>1);
+			      continue;
+			    case 's':
+			      if (!reg_lookup (&asarg, RCLASS_VECR, &regno))
+				    break;
+			      if ((regno & 0x1) != 0)
+			      {
+				    error.msg = _("illegal operands (vs1 must be even)");
+				    break;
+			      }
+			      INSERT_OPERAND (SPACEMIT_IME_VS1, *ip, regno>>1);
+			      continue;
+			    default:
+			      goto unknown_riscv_ip_operand;
+		      }
+		      break;
+		    case 'w': /* Xpw&S ... bits in S indicates whether corresponding item is permitted.  */
+		      if (*++oparg != '&')
+			    goto unknown_riscv_ip_operand;
+		      n = strtol (oparg + 1, (char **)&oparg, 16);
+		      oparg--;
+		      if (!arg_lookup (&asarg, riscv_smt_wi, ARRAY_SIZE (riscv_smt_wi), &regno))
+			    break;
+		      if ((n & (1 << regno)) == 0)
+			    break;
+		      INSERT_OPERAND (SPACEMIT_IME_WI, *ip, regno);
+		      continue;
+		    default:
+		      goto unknown_riscv_ip_operand;
+		    }
+		  }
+		  break;
 		default:
 		  goto unknown_riscv_ip_operand;
 		}
diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
index c6c4081c204..88dd1de4aea 100644
--- a/gas/doc/c-riscv.texi
+++ b/gas/doc/c-riscv.texi
@@ -918,4 +918,11 @@  The XMipsSlsp extension provides instructions mips.ldp, mips.lwp, mips.sdp and m
 
 It is documented in @url{https://mips.com/wp-content/uploads/2025/03/P8700-F_Programmers_Reference_Manual_Rev1.82_3-19-2025.pdf}.
 
+@item XSmtVdot
+The XSmtVdot extension provides instructions for vector dot.
+
+SpacemiT defines Intrinsic Matrix Extension (IME) specification, documented in @url{https://github.com/spacemit-com/riscv-ime-extension-spec/releases/download/v1.0/spacemit-ime-asciidoc.pdf}.
+SpacemiT X60 implement version 1.0 of the SpacemiT Vector Dot Product Extension (XsmtVdot v1.0),
+it is a subset of the full IME specification, documented in @url{https://developer.spacemit.com/documentation?token=BWbGwbx7liGW21kq9lucSA6Vnpb#2.1}.
+
 @end table
diff --git a/gas/testsuite/gas/riscv/march-help.l b/gas/testsuite/gas/riscv/march-help.l
index 0ce2f896735..6e52669e9a4 100644
--- a/gas/testsuite/gas/riscv/march-help.l
+++ b/gas/testsuite/gas/riscv/march-help.l
@@ -186,3 +186,4 @@  All available -march extensions for RISC-V:
 	xmipscmov                               1.0
 	xmipsexectl                             1.0
 	xmipslsp                                1.0
+	xsmtvdot                                1.0
diff --git a/gas/testsuite/gas/riscv/x-smt-vdot-fail.l b/gas/testsuite/gas/riscv/x-smt-vdot-fail.l
new file mode 100644
index 00000000000..6e846b401e1
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-smt-vdot-fail.l
@@ -0,0 +1,3 @@ 
+#as: -march=rv64gcv_xsmtvdot
+#source: x-smt-vdot-fail.s
+#error_output: x-smt-vdot-fail.l
diff --git a/gas/testsuite/gas/riscv/x-smt-vdot-fail.s b/gas/testsuite/gas/riscv/x-smt-vdot-fail.s
new file mode 100644
index 00000000000..77399a7fdde
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-smt-vdot-fail.s
@@ -0,0 +1,46 @@ 
+target:
+	smt.vmadot v1, v3, v4
+	smt.vmadotu v1, v3, v4
+	smt.vmadotsu v1, v3, v4
+	smt.vmadotus v1, v3, v4
+	smt.vmadot1u v1, v4, v5
+	smt.vmadot1 v1, v4, v5
+	smt.vmadot1su v1, v4, v5
+	smt.vmadot1us v1, v4, v5
+	smt.vmadot2u v1, v4, v5
+	smt.vmadot2 v1, v4, v5
+	smt.vmadot2su v1, v4, v5
+	smt.vmadot2us v1, v4, v5
+	smt.vmadot3u v1, v4, v5
+	smt.vmadot3 v1, v4, v5
+	smt.vmadot3su v1, v4, v5
+	smt.vmadot3us v1, v4, v5
+	smt.vmadot1u v2, v3, v5
+	smt.vmadot1 v2, v3, v5
+	smt.vmadot1su v2, v3, v5
+	smt.vmadot1us v2, v3, v5
+	smt.vmadot2u v2, v3, v5
+	smt.vmadot2 v2, v3, v5
+	smt.vmadot2su v2, v3, v5
+	smt.vmadot2us v2, v3, v5
+	smt.vmadot3u v2, v3, v5
+	smt.vmadot3 v2, v3, v5
+	smt.vmadot3su v2, v3, v5
+	smt.vmadot3us v2, v3, v5
+	smt.vmadot v2, v3, v4, i4
+	smt.vmadotu v2, v3, v4, i4
+	smt.vmadotsu v2, v3, v4, i4
+	smt.vmadotus v2, v3, v4, i4
+	smt.vmadot1u v2, v4, v5, i4
+	smt.vmadot1 v2, v4, v5, i4
+	smt.vmadot1su v2, v4, v5, i4
+	smt.vmadot1us v2, v4, v5, i4
+	smt.vmadot2u v2, v4, v5, i4
+	smt.vmadot2 v2, v4, v5, i4
+	smt.vmadot2su v2, v4, v5, i4
+	smt.vmadot2us v2, v4, v5, i4
+	smt.vmadot3u v2, v4, v5, i4
+	smt.vmadot3 v2, v4, v5, i4
+	smt.vmadot3su v2, v4, v5, i4
+	smt.vmadot3us v2, v4, v5, i4
+
diff --git a/gas/testsuite/gas/riscv/x-smt-vdot.d b/gas/testsuite/gas/riscv/x-smt-vdot.d
new file mode 100644
index 00000000000..6f86236785d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-smt-vdot.d
@@ -0,0 +1,41 @@ 
+#as: -march=rv64gcv_xsmtvdot
+#objdump: -dr
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+e241b12b[ 	]+smt.vmadot[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241812b[ 	]+smt.vmadotu[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241a12b[ 	]+smt.vmadotsu[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241912b[ 	]+smt.vmadotus[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e652012b[ 	]+smt.vmadot1u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652312b[ 	]+smt.vmadot1[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652212b[ 	]+smt.vmadot1su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652112b[ 	]+smt.vmadot1us[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652412b[ 	]+smt.vmadot2u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652712b[ 	]+smt.vmadot2[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652612b[ 	]+smt.vmadot2su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652512b[ 	]+smt.vmadot2us[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652812b[ 	]+smt.vmadot3u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652b12b[ 	]+smt.vmadot3[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652a12b[ 	]+smt.vmadot3su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652912b[ 	]+smt.vmadot3us[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e241b12b[ 	]+smt.vmadot[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241812b[ 	]+smt.vmadotu[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241a12b[ 	]+smt.vmadotsu[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e241912b[ 	]+smt.vmadotus[ 	]+v2,v3,v4
+[ 	]+[0-9a-f]+:[ 	]+e652012b[ 	]+smt.vmadot1u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652312b[ 	]+smt.vmadot1[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652212b[ 	]+smt.vmadot1su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652112b[ 	]+smt.vmadot1us[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652412b[ 	]+smt.vmadot2u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652712b[ 	]+smt.vmadot2[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652612b[ 	]+smt.vmadot2su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652512b[ 	]+smt.vmadot2us[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652812b[ 	]+smt.vmadot3u[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652b12b[ 	]+smt.vmadot3[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652a12b[ 	]+smt.vmadot3su[ 	]+v2,v4,v5
+[ 	]+[0-9a-f]+:[ 	]+e652912b[ 	]+smt.vmadot3us[ 	]+v2,v4,v5
diff --git a/gas/testsuite/gas/riscv/x-smt-vdot.s b/gas/testsuite/gas/riscv/x-smt-vdot.s
new file mode 100644
index 00000000000..a9991de4fc3
--- /dev/null
+++ b/gas/testsuite/gas/riscv/x-smt-vdot.s
@@ -0,0 +1,33 @@ 
+target:
+	smt.vmadot v2, v3, v4
+	smt.vmadotu v2, v3, v4
+	smt.vmadotsu v2, v3, v4
+	smt.vmadotus v2, v3, v4
+	smt.vmadot1u v2, v4, v5
+	smt.vmadot1 v2, v4, v5
+	smt.vmadot1su v2, v4, v5
+	smt.vmadot1us v2, v4, v5
+	smt.vmadot2u v2, v4, v5
+	smt.vmadot2 v2, v4, v5
+	smt.vmadot2su v2, v4, v5
+	smt.vmadot2us v2, v4, v5
+	smt.vmadot3u v2, v4, v5
+	smt.vmadot3 v2, v4, v5
+	smt.vmadot3su v2, v4, v5
+	smt.vmadot3us v2, v4, v5
+	smt.vmadot v2, v3, v4, i8
+	smt.vmadotu v2, v3, v4, i8
+	smt.vmadotsu v2, v3, v4, i8
+	smt.vmadotus v2, v3, v4, i8
+	smt.vmadot1u v2, v4, v5, i8
+	smt.vmadot1 v2, v4, v5, i8
+	smt.vmadot1su v2, v4, v5, i8
+	smt.vmadot1us v2, v4, v5, i8
+	smt.vmadot2u v2, v4, v5, i8
+	smt.vmadot2 v2, v4, v5, i8
+	smt.vmadot2su v2, v4, v5, i8
+	smt.vmadot2us v2, v4, v5, i8
+	smt.vmadot3u v2, v4, v5, i8
+	smt.vmadot3 v2, v4, v5, i8
+	smt.vmadot3su v2, v4, v5, i8
+	smt.vmadot3us v2, v4, v5, i8
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 6f2775c6152..5a004622c2c 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -3852,6 +3852,81 @@ 
 #define MASK_MIPS_PAUSE  0xffffffff
 #define MATCH_MIPS_PREF 0x0000000b
 #define MASK_MIPS_PREF 0xe000707f
+/* SpacemiT custom instruction.  */
+/* Int Matrix Multiplicative Accumulation */
+#define MATCH_SMT_VMADOT_I8   0xe200302b
+#define MASK_SMT_VMADOT_I8    0xfe0070ff
+#define MATCH_SMT_VMADOTU_I8  0xe200002b
+#define MASK_SMT_VMADOTU_I8   0xfe0070ff
+#define MATCH_SMT_VMADOTSU_I8 0xe200202b
+#define MASK_SMT_VMADOTSU_I8  0xfe0070ff
+#define MATCH_SMT_VMADOTUS_I8 0xe200102b
+#define MASK_SMT_VMADOTUS_I8  0xfe0070ff
+/* Int Sliding Window Multiplicative Accumulation */
+/* Sliding Value = 1 */
+#define MATCH_SMT_VMADOT1U_I8 0xe600002b
+#define MASK_SMT_VMADOT1U_I8  0xfe00f0ff
+#define MATCH_SMT_VMADOT1_I8    0xe600302b
+#define MASK_SMT_VMADOT1_I8     0xfe00f0ff
+#define MATCH_SMT_VMADOT1SU_I8  0xe600202b
+#define MASK_SMT_VMADOT1SU_I8   0xfe00f0ff
+#define MATCH_SMT_VMADOT1US_I8  0xe600102b
+#define MASK_SMT_VMADOT1US_I8   0xfe00f0ff
+/* Sliding Value = 2 */
+#define MATCH_SMT_VMADOT2U_I8   0xe600402b
+#define MASK_SMT_VMADOT2U_I8    0xfe00f0ff
+#define MATCH_SMT_VMADOT2_I8    0xe600702b
+#define MASK_SMT_VMADOT2_I8     0xfe00f0ff
+#define MATCH_SMT_VMADOT2SU_I8  0xe600602b
+#define MASK_SMT_VMADOT2SU_I8   0xfe00f0ff
+#define MATCH_SMT_VMADOT2US_I8  0xe600502b
+#define MASK_SMT_VMADOT2US_I8   0xfe00f0ff
+/* Sliding Value = 3 */
+#define MATCH_SMT_VMADOT3U_I8   0xe600802b
+#define MASK_SMT_VMADOT3U_I8    0xfe00f0ff
+#define MATCH_SMT_VMADOT3_I8    0xe600b02b
+#define MASK_SMT_VMADOT3_I8     0xfe00f0ff
+#define MATCH_SMT_VMADOT3SU_I8  0xe600a02b
+#define MASK_SMT_VMADOT3SU_I8   0xfe00f0ff
+#define MATCH_SMT_VMADOT3US_I8  0xe600902b
+#define MASK_SMT_VMADOT3US_I8   0xfe00f0ff
+/* Int Matrix Multiplicative Accumulation */
+#define MATCH_SMT_VMADOT   0x8200302b
+#define MASK_SMT_VMADOT    0x9e0070ff
+#define MATCH_SMT_VMADOTU  0x8200002b
+#define MASK_SMT_VMADOTU   0x9e0070ff
+#define MATCH_SMT_VMADOTSU 0x8200202b
+#define MASK_SMT_VMADOTSU  0x9e0070ff
+#define MATCH_SMT_VMADOTUS 0x8200102b
+#define MASK_SMT_VMADOTUS  0x9e0070ff
+/* Int Sliding Window Multiplicative Accumulation */
+/* Sliding Value = 1 */
+#define MATCH_SMT_VMADOT1U 0x8600002b
+#define MASK_SMT_VMADOT1U  0x9e00f0ff
+#define MATCH_SMT_VMADOT1  0x8600302b
+#define MASK_SMT_VMADOT1   0x9e00f0ff
+#define MATCH_SMT_VMADOT1SU 0x8600202b
+#define MASK_SMT_VMADOT1SU 0x9e00f0ff
+#define MATCH_SMT_VMADOT1US 0x8600102b
+#define MASK_SMT_VMADOT1US 0x9e00f0ff
+/* Sliding Value = 2 */
+#define MATCH_SMT_VMADOT2U 0x8600402b
+#define MASK_SMT_VMADOT2U 0x9e00f0ff
+#define MATCH_SMT_VMADOT2 0x8600702b
+#define MASK_SMT_VMADOT2 0x9e00f0ff
+#define MATCH_SMT_VMADOT2SU 0x8600602b
+#define MASK_SMT_VMADOT2SU 0x9e00f0ff
+#define MATCH_SMT_VMADOT2US 0x8600502b
+#define MASK_SMT_VMADOT2US 0x9e00f0ff
+/* Sliding Value = 3 */
+#define MATCH_SMT_VMADOT3U 0x8600802b
+#define MASK_SMT_VMADOT3U 0x9e00f0ff
+#define MATCH_SMT_VMADOT3 0x8600b02b
+#define MASK_SMT_VMADOT3 0x9e00f0ff
+#define MATCH_SMT_VMADOT3SU 0x8600a02b
+#define MASK_SMT_VMADOT3SU 0x9e00f0ff
+#define MATCH_SMT_VMADOT3US 0x8600902b
+#define MASK_SMT_VMADOT3US 0x9e00f0ff
 /* Unprivileged Counter/Timers CSR addresses.  */
 #define CSR_CYCLE 0xc00
 #define CSR_TIME 0xc01
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index de105f5df8b..7a7b998b913 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -419,6 +419,14 @@  static inline unsigned int riscv_insn_length (insn_t insn)
 #define OP_MASK_MIPS_SDP_OFFSET25   0x3
 #define OP_SH_MIPS_SDP_OFFSET25     25
 
+/* SpacemiT fields */
+#define OP_MASK_SPACEMIT_IME_VD		0xf
+#define OP_SH_SPACEMIT_IME_VD		8
+#define OP_MASK_SPACEMIT_IME_VS1	0xf
+#define OP_SH_SPACEMIT_IME_VS1		16
+#define OP_MASK_SPACEMIT_IME_WI		0x3
+#define OP_SH_SPACEMIT_IME_WI		29
+
 /* ABI names for selected x-registers.  */
 
 #define X_ZERO 0
@@ -606,6 +614,7 @@  enum riscv_insn_class
   INSN_CLASS_XMIPSCMOV,
   INSN_CLASS_XMIPSEXECTL,
   INSN_CLASS_XMIPSLSP,
+  INSN_CLASS_XSMTVDOT,
 };
 
 /* This structure holds information for a particular instruction.  */
@@ -726,6 +735,7 @@  extern const char * const riscv_th_vlen[4];
 extern const char * const riscv_th_vediv[4];
 extern const char * const riscv_fli_symval[32];
 extern const float riscv_fli_numval[32];
+extern const char * const riscv_smt_wi[4];
 
 extern const struct riscv_opcode riscv_opcodes[];
 extern const struct riscv_opcode riscv_insn_types[];
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 03c8cf1e344..6df1441d48c 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -917,6 +917,39 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 		  goto undefined_modifier;
 		}
 	      break;
+	    case 'p': /* Vendor-specific (SpacemiT) operands.  */
+		  {
+	      switch (*++oparg)
+		  {
+		  case 'V':
+		    switch (*++oparg)
+		      {
+		      case 'd':
+			    print (info->stream, dis_style_register,  "%s",
+			      riscv_vecr_names_numeric[EXTRACT_OPERAND (SPACEMIT_IME_VD, l) * 2]);
+			    break;
+		      case 's':
+			    print (info->stream, dis_style_register,  "%s",
+			      riscv_vecr_names_numeric[EXTRACT_OPERAND (SPACEMIT_IME_VS1, l) * 2]);
+			    break;
+		      default:
+			    goto undefined_modifier;
+		      }
+		    break;
+		  case 'w': /* Xpw&S ... bits in S indicates whether corresponding item is permitted.  */
+			if (*++oparg != '&')
+			  goto undefined_modifier;
+			strtol (oparg + 1, (char **)&oparg, 16);
+		    oparg--;
+			print (info->stream, dis_style_register, "%s",
+				riscv_smt_wi[EXTRACT_OPERAND (SPACEMIT_IME_WI, l)]);
+			  break;
+		  default:
+		    goto undefined_modifier;
+		  }
+			break;
+		  }
+	      break;
 	    default:
 	      goto undefined_modifier;
 	    }
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 54887c97880..8b81dda2008 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -122,6 +122,12 @@  const char * const riscv_th_vediv[4] =
     "d1", "d2", "d4", "d8"
 };
 
+/* XSmtVdot, List of int type width constants.  */
+const char * const riscv_smt_wi[4] =
+{
+    "i2", "i16", "i4", "i8"
+};
+
 /* The FLI.[HSDQ] symbolic constants (NULL for numeric constant).  */
 const char * const riscv_fli_symval[32] =
 {
@@ -3579,6 +3585,45 @@  const struct riscv_opcode riscv_opcodes[] =
 {"mips.sdp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm^(s)", MATCH_MIPS_SDP, MASK_MIPS_SDP, match_opcode, 0 },
 {"mips.swp", 0, INSN_CLASS_XMIPSLSP, "t,r,Xm&(s)", MATCH_MIPS_SWP, MASK_MIPS_SWP, match_opcode, 0 },
 
+/* SpacemiT custom instructions. */
+/* Int Matrix Multi-Accumulation */
+{"smt.vmadot",   0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt",       MATCH_SMT_VMADOT_I8,   MASK_SMT_VMADOT_I8,   match_opcode, INSN_ALIAS },
+{"smt.vmadot",   0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt,Xpw&8", MATCH_SMT_VMADOT,      MASK_SMT_VMADOT,      match_opcode, 0 },
+{"smt.vmadotu",  0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt",       MATCH_SMT_VMADOTU_I8,  MASK_SMT_VMADOTU_I8,  match_opcode, INSN_ALIAS },
+{"smt.vmadotu",  0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt,Xpw&8", MATCH_SMT_VMADOTU,     MASK_SMT_VMADOTU,     match_opcode, 0 },
+{"smt.vmadotsu", 0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt",       MATCH_SMT_VMADOTSU_I8, MASK_SMT_VMADOTSU_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadotsu", 0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt,Xpw&8", MATCH_SMT_VMADOTSU,    MASK_SMT_VMADOTSU,    match_opcode, 0 },
+{"smt.vmadotus", 0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt",       MATCH_SMT_VMADOTUS_I8, MASK_SMT_VMADOTUS_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadotus", 0, INSN_CLASS_XSMTVDOT, "XpVd,Vs,Vt,Xpw&8", MATCH_SMT_VMADOTUS,    MASK_SMT_VMADOTUS,    match_opcode, 0 },
+/* Int Sliding Window Multi-Accumulation */
+/* Sliding Value = 1 */
+{"smt.vmadot1u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT1U_I8,  MASK_SMT_VMADOT1U_I8,  match_opcode, INSN_ALIAS },
+{"smt.vmadot1u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT1U,     MASK_SMT_VMADOT1U,     match_opcode, 0 },
+{"smt.vmadot1",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT1_I8,   MASK_SMT_VMADOT1_I8,   match_opcode, INSN_ALIAS },
+{"smt.vmadot1",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT1,      MASK_SMT_VMADOT1,      match_opcode, 0 },
+{"smt.vmadot1su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT1SU_I8, MASK_SMT_VMADOT1SU_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot1su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT1SU,    MASK_SMT_VMADOT1SU,    match_opcode, 0 },
+{"smt.vmadot1us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT1US_I8, MASK_SMT_VMADOT1US_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot1us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT1US,    MASK_SMT_VMADOT1US,    match_opcode, 0 },
+/* Sliding Value = 2 */
+{"smt.vmadot2u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT2U_I8,  MASK_SMT_VMADOT2U_I8,  match_opcode, INSN_ALIAS },
+{"smt.vmadot2u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT2U,     MASK_SMT_VMADOT2U,     match_opcode, 0},
+{"smt.vmadot2",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT2_I8,   MASK_SMT_VMADOT2_I8,   match_opcode, INSN_ALIAS },
+{"smt.vmadot2",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT2,      MASK_SMT_VMADOT2,      match_opcode, 0},
+{"smt.vmadot2su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT2SU_I8, MASK_SMT_VMADOT2SU_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot2su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT2SU,    MASK_SMT_VMADOT2SU,    match_opcode, 0},
+{"smt.vmadot2us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT2US_I8, MASK_SMT_VMADOT2US_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot2us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT2US,    MASK_SMT_VMADOT2US,    match_opcode, 0},
+/* Sliding Value = 3 */
+{"smt.vmadot3u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT3U_I8,  MASK_SMT_VMADOT3U_I8,  match_opcode, INSN_ALIAS },
+{"smt.vmadot3u",  0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT3U,     MASK_SMT_VMADOT3U,     match_opcode, 0},
+{"smt.vmadot3",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT3_I8,   MASK_SMT_VMADOT3_I8,   match_opcode, INSN_ALIAS },
+{"smt.vmadot3",   0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT3,      MASK_SMT_VMADOT3,      match_opcode, 0},
+{"smt.vmadot3su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT3SU_I8, MASK_SMT_VMADOT3SU_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot3su", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT3SU,    MASK_SMT_VMADOT3SU,    match_opcode, 0},
+{"smt.vmadot3us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt",       MATCH_SMT_VMADOT3US_I8, MASK_SMT_VMADOT3US_I8, match_opcode, INSN_ALIAS },
+{"smt.vmadot3us", 0, INSN_CLASS_XSMTVDOT, "XpVd,XpVs,Vt,Xpw&8", MATCH_SMT_VMADOT3US,    MASK_SMT_VMADOT3US,    match_opcode, 0},
+
 /* Terminate the list.  */
 {0, 0, INSN_CLASS_NONE, 0, 0, 0, 0, 0}
 };