[1/2] RISC-V: Add support for XCVmac extension in CV32E40P

Message ID 20230905145300.652455-2-mary.bennett@embecosm.com
State New
Headers
Series RISC-V: Support CORE-V XCVMAC and XCVALU extensions |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_binutils_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_binutils_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_binutils_build--master-aarch64 success Testing passed

Commit Message

Mary Bennett Sept. 5, 2023, 2:52 p.m. UTC
  Spec: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html

Contributors:
  Mary Bennett <mary.bennett@embecosm.com>
  Nandni Jamnadas <nandni.jamnadas@embecosm.com>
  Pietra Ferreira <pietra.ferreira@embecosm.com>
  Charlie Keaney
  Jessica Mills
  Craig Blackmore <craig.blackmore@embecosm.com>
  Simon Cook <simon.cook@embecosm.com>
  Jeremy Bennett <jeremy.bennett@embecosm.com>

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_multi_subset_supports): Added `xcvmac`
          instruction class.
	(riscv_multi_subset_supports_ext): Likewise.

gas/ChangeLog:

	* config/tc-riscv.c (validate_riscv_insn): Added the necessary
          operands for the extension.
	(riscv_ip): Likewise.
	* doc/c-riscv.texi: Noted XCVmac as an additional ISA extension
          for CORE-V.
	* testsuite/gas/riscv/cv-mac-fail-march.d: New test.
	* testsuite/gas/riscv/cv-mac-fail-march.l: New test.
	* testsuite/gas/riscv/cv-mac-fail-march.s: New test.
	* testsuite/gas/riscv/cv-mac-fail-operand.d: New test.
	* testsuite/gas/riscv/cv-mac-fail-operand.l: New test.
	* testsuite/gas/riscv/cv-mac-fail-operand.s: New test.
	* testsuite/gas/riscv/cv-mac-insns.d: New test.
	* testsuite/gas/riscv/cv-mac-insns.s: New test.

opcodes/ChangeLog:

	* riscv-dis.c (print_insn_args): Disassemble information with
          the EXTRACT macro implemented.
	* riscv-opc.c: Defined the MASK and added
          XCVmac instructions.

include/ChangeLog:

	* opcode/riscv-opc.h: Added corresponding MATCH and MASK macros
          for XCVmac.
	* opcode/riscv.h: Added corresponding EXTRACT and ENCODE macros
          for uimm.
	(enum riscv_insn_class): Added the XCVmac instruction class.
---
 bfd/elfxx-riscv.c                             |   6 +
 gas/config/tc-riscv.c                         |  45 +++++
 gas/doc/c-riscv.texi                          |   5 +
 gas/testsuite/gas/riscv/cv-mac-fail-march.d   |   3 +
 gas/testsuite/gas/riscv/cv-mac-fail-march.l   |  23 +++
 gas/testsuite/gas/riscv/cv-mac-fail-march.s   |  24 +++
 gas/testsuite/gas/riscv/cv-mac-fail-operand.d |   3 +
 gas/testsuite/gas/riscv/cv-mac-fail-operand.l | 147 +++++++++++++++++
 gas/testsuite/gas/riscv/cv-mac-fail-operand.s | 156 ++++++++++++++++++
 gas/testsuite/gas/riscv/cv-mac-insns.d        |  87 ++++++++++
 gas/testsuite/gas/riscv/cv-mac-insns.s        |  81 +++++++++
 include/opcode/riscv-opc.h                    |  21 +++
 include/opcode/riscv.h                        |   7 +
 opcodes/riscv-dis.c                           |  16 ++
 opcodes/riscv-opc.c                           |  26 +++
 15 files changed, 650 insertions(+)
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.d
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.l
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.s
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.d
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.l
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.s
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-insns.d
 create mode 100644 gas/testsuite/gas/riscv/cv-mac-insns.s
  

Comments

Nelson Chu Sept. 7, 2023, 4:35 a.m. UTC | #1
Hi,

I just noticed that - it isn't clear from the old code that the operands,
which are named starting with X, are reserved for vendors.  Therefore, I
sent the patch to clarify the vendor operands' naming rules,
https://sourceware.org/pipermail/binutils/2023-September/129414.html.  So
that everything vendor operands will be named starting with X, and then
follows one letter (or a keyword in the future) to represent which vendors
belonged.

Thanks
Nelson

On Tue, Sep 5, 2023 at 10:54 PM Mary Bennett <mary.bennett@embecosm.com>
wrote:

> Spec:
> https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html
>
> Contributors:
>   Mary Bennett <mary.bennett@embecosm.com>
>   Nandni Jamnadas <nandni.jamnadas@embecosm.com>
>   Pietra Ferreira <pietra.ferreira@embecosm.com>
>   Charlie Keaney
>   Jessica Mills
>   Craig Blackmore <craig.blackmore@embecosm.com>
>   Simon Cook <simon.cook@embecosm.com>
>   Jeremy Bennett <jeremy.bennett@embecosm.com>
>
> bfd/ChangeLog:
>
>         * elfxx-riscv.c (riscv_multi_subset_supports): Added `xcvmac`
>           instruction class.
>         (riscv_multi_subset_supports_ext): Likewise.
>
> gas/ChangeLog:
>
>         * config/tc-riscv.c (validate_riscv_insn): Added the necessary
>           operands for the extension.
>         (riscv_ip): Likewise.
>         * doc/c-riscv.texi: Noted XCVmac as an additional ISA extension
>           for CORE-V.
>         * testsuite/gas/riscv/cv-mac-fail-march.d: New test.
>         * testsuite/gas/riscv/cv-mac-fail-march.l: New test.
>         * testsuite/gas/riscv/cv-mac-fail-march.s: New test.
>         * testsuite/gas/riscv/cv-mac-fail-operand.d: New test.
>         * testsuite/gas/riscv/cv-mac-fail-operand.l: New test.
>         * testsuite/gas/riscv/cv-mac-fail-operand.s: New test.
>         * testsuite/gas/riscv/cv-mac-insns.d: New test.
>         * testsuite/gas/riscv/cv-mac-insns.s: New test.
>
> opcodes/ChangeLog:
>
>         * riscv-dis.c (print_insn_args): Disassemble information with
>           the EXTRACT macro implemented.
>         * riscv-opc.c: Defined the MASK and added
>           XCVmac instructions.
>
> include/ChangeLog:
>
>         * opcode/riscv-opc.h: Added corresponding MATCH and MASK macros
>           for XCVmac.
>         * opcode/riscv.h: Added corresponding EXTRACT and ENCODE macros
>           for uimm.
>         (enum riscv_insn_class): Added the XCVmac instruction class.
> ---
>  bfd/elfxx-riscv.c                             |   6 +
>  gas/config/tc-riscv.c                         |  45 +++++
>  gas/doc/c-riscv.texi                          |   5 +
>  gas/testsuite/gas/riscv/cv-mac-fail-march.d   |   3 +
>  gas/testsuite/gas/riscv/cv-mac-fail-march.l   |  23 +++
>  gas/testsuite/gas/riscv/cv-mac-fail-march.s   |  24 +++
>  gas/testsuite/gas/riscv/cv-mac-fail-operand.d |   3 +
>  gas/testsuite/gas/riscv/cv-mac-fail-operand.l | 147 +++++++++++++++++
>  gas/testsuite/gas/riscv/cv-mac-fail-operand.s | 156 ++++++++++++++++++
>  gas/testsuite/gas/riscv/cv-mac-insns.d        |  87 ++++++++++
>  gas/testsuite/gas/riscv/cv-mac-insns.s        |  81 +++++++++
>  include/opcode/riscv-opc.h                    |  21 +++
>  include/opcode/riscv.h                        |   7 +
>  opcodes/riscv-dis.c                           |  16 ++
>  opcodes/riscv-opc.c                           |  26 +++
>  15 files changed, 650 insertions(+)
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.d
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.l
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-march.s
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.d
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.l
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-fail-operand.s
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-insns.d
>  create mode 100644 gas/testsuite/gas/riscv/cv-mac-insns.s
>
> diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
> index cb65024beaf..a3c32941866 100644
> --- a/bfd/elfxx-riscv.c
> +++ b/bfd/elfxx-riscv.c
> @@ -1347,6 +1347,8 @@ static struct riscv_supported_ext
> riscv_supported_std_zxm_ext[] =
>
>  static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
>  {
> +  /* CORE-V ISA extension spec:
> https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html
> */
> +  {"xcvmac",           ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
>

The document link should already be recorded in gas/doc/c-riscv.texi.


>    {"xtheadba",         ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
>    {"xtheadbb",         ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
>    {"xtheadbs",         ISA_SPEC_CLASS_DRAFT,   1, 0, 0 },
> @@ -2539,6 +2541,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t
> *rps,
>        return riscv_subset_supports (rps, "svinval");
>      case INSN_CLASS_H:
>        return riscv_subset_supports (rps, "h");
> +    case INSN_CLASS_XCVMAC:
> +      return riscv_subset_supports (rps, "xcvmac");
>      case INSN_CLASS_XTHEADBA:
>        return riscv_subset_supports (rps, "xtheadba");
>      case INSN_CLASS_XTHEADBB:
> @@ -2779,6 +2783,8 @@ riscv_multi_subset_supports_ext
> (riscv_parse_subset_t *rps,
>        return "svinval";
>      case INSN_CLASS_H:
>        return _("h");
> +    case INSN_CLASS_XCVMAC:
> +      return "xcvmac";
>      case INSN_CLASS_XTHEADBA:
>        return "xtheadba";
>      case INSN_CLASS_XTHEADBB:
> diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
> index e49b34fd524..3100a2e135f 100644
> --- a/gas/config/tc-riscv.c
> +++ b/gas/config/tc-riscv.c
> @@ -1470,6 +1470,25 @@ validate_riscv_insn (const struct riscv_opcode
> *opc, int length)
>               }
>           }
>           break;
> +       case 'x': /* Vendor-specific operands.  */
>

Considering consistency, it's better to use `X'.


> +         switch (*++oparg)
> +           {
> +             /* Vendor-specific (CORE-V) operands.  */
> +             case 'c':
> +               switch (*++oparg)
> +                 {
> +                   case '3':
> +                     used_bits |= ENCODE_CV_IS3_UIMM5 (-1U);
> +                     break;
> +                   default:
> +                     goto unknown_validate_operand;
> +                 }
> +               break;
> +             default:
> +               goto unknown_validate_operand;
> +           }
> +         break;
> +
>         default:
>         unknown_validate_operand:
>           as_bad (_("internal: bad RISC-V opcode "
> @@ -3669,6 +3688,32 @@ riscv_ip (char *str, struct riscv_cl_insn *ip,
> expressionS *imm_expr,
>               }
>               break;
>
> +           case 'x': /* Vendor-specific operands.  */
>

Likewise.


> +             switch (*++oparg)
> +               {
> +                 /* Vendor-specific (CORE-V) operands.  */
> +                 case 'c':
>

Use c to represent vendor core-v looks reasonable.


> +                   switch (*++oparg)
> +                     {
> +                       case '3':
> +                         my_getExpression (imm_expr, asarg);
> +                         check_absolute_expr (ip, imm_expr, FALSE);
> +                         asarg = expr_parse_end;
> +                         if (imm_expr->X_add_number<0
> +                             || imm_expr->X_add_number>31)
> +                           break;
> +                         ip->insn_opcode
> +                           |= ENCODE_CV_IS3_UIMM5
> (imm_expr->X_add_number);
> +                         continue;
> +                       default:
> +                         goto unknown_riscv_ip_operand;
> +                     }
> +                   break;
> +                 default:
> +                   goto unknown_riscv_ip_operand;
> +               }
> +           break;
> +
>             default:
>             unknown_riscv_ip_operand:
>               as_fatal (_("internal: unknown argument type `%s'"),
> diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
> index b175ba0a729..1dcdeeb7b36 100644
> --- a/gas/doc/c-riscv.texi
> +++ b/gas/doc/c-riscv.texi
> @@ -745,6 +745,11 @@ extensions supported and provides the location of
> their
>  publicly-released documentation:
>
>  @table @r
> +@item Xcvmac
> +The Xcvmac extension provides instructions for multiply-accumulate
> operations.
> +
> +It is documented in @url{
> https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html
> }
> +
>  @item XTheadBa
>  The XTheadBa extension provides instructions for address calculations.
>
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.d
> b/gas/testsuite/gas/riscv/cv-mac-fail-march.d
> new file mode 100644
> index 00000000000..eb6352f85f2
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32i
> +#source: cv-mac-fail-march.s
> +#error_output: cv-mac-fail-march.l
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.l
> b/gas/testsuite/gas/riscv/cv-mac-fail-march.l
> new file mode 100644
> index 00000000000..d2bc12c804a
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.l
> @@ -0,0 +1,23 @@
> +.*: Assembler messages:
> +.*: Error: unrecognized opcode `cv.mac t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.msu t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.muls t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulhhs t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulsn t4,t2,t0,4', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulhhsn t4,t2,t0,16', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.mulsrn t4,t2,t0,10', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.mulhhsrn t4,t2,t0,17', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.mulu t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulhhu t4,t2,t0', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulun t4,t2,t0,7', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.mulhhun t4,t2,t0,16', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.mulurn t4,t2,t0,11', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.mulhhurn t4,t2,t0,9', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.macsn t4,t2,t0,24', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.machhsn t4,t2,t0,11', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.macsrn t4,t2,t0,9', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.machhsrn t4,t2,t0,24', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.macun t4,t2,t0,27', extension `xcvmac'
> required
> +.*: Error: unrecognized opcode `cv.machhun t4,t2,t0,18', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.macurn t4,t2,t0,25', extension
> `xcvmac' required
> +.*: Error: unrecognized opcode `cv.machhurn t4,t2,t0,5', extension
> `xcvmac' required
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.s
> b/gas/testsuite/gas/riscv/cv-mac-fail-march.s
> new file mode 100644
> index 00000000000..78b08423a64
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.s
> @@ -0,0 +1,24 @@
> +# Absence of the xcvmac march option disables all CORE-V MAC extensions.
> +target:
> +       cv.mac t4, t2, t0
> +       cv.msu t4, t2, t0
> +       cv.muls t4, t2, t0
> +       cv.mulhhs t4, t2, t0
> +       cv.mulsn t4, t2, t0, 4
> +       cv.mulhhsn t4, t2, t0, 16
> +       cv.mulsrn t4, t2, t0, 10
> +       cv.mulhhsrn t4, t2, t0, 17
> +       cv.mulu t4, t2, t0
> +       cv.mulhhu t4, t2, t0
> +       cv.mulun t4, t2, t0, 7
> +       cv.mulhhun t4, t2, t0, 16
> +       cv.mulurn t4, t2, t0, 11
> +       cv.mulhhurn t4, t2, t0, 9
> +       cv.macsn t4, t2, t0, 24
> +       cv.machhsn t4, t2, t0, 11
> +       cv.macsrn t4, t2, t0, 9
> +       cv.machhsrn t4, t2, t0, 24
> +       cv.macun t4, t2, t0, 27
> +       cv.machhun t4, t2, t0, 18
> +       cv.macurn t4, t2, t0, 25
> +       cv.machhurn t4, t2, t0, 5
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.d
> b/gas/testsuite/gas/riscv/cv-mac-fail-operand.d
> new file mode 100644
> index 00000000000..51e1b3052c9
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.d
> @@ -0,0 +1,3 @@
> +#as: -march=rv32i_xcvmac
> +#source: cv-mac-fail-operand.s
> +#error_output: cv-mac-fail-operand.l
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.l
> b/gas/testsuite/gas/riscv/cv-mac-fail-operand.l
> new file mode 100644
> index 00000000000..645949696cb
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.l
> @@ -0,0 +1,147 @@
> +.*: Assembler messages:
> +.*: Error: illegal operands `cv.mac 8,t2,t0'
> +.*: Error: illegal operands `cv.msu 23,t2,t0'
> +.*: Error: illegal operands `cv.muls 43,t2,t0'
> +.*: Error: illegal operands `cv.mulhhs 7,t2,t0'
> +.*: Error: illegal operands `cv.mulsn 345,t2,t0,4'
> +.*: Error: illegal operands `cv.mulhhsn 356,t2,t0,16'
> +.*: Error: illegal operands `cv.mulsrn 867,t2,t0,10'
> +.*: Error: illegal operands `cv.mulhhsrn 3454,t2,t0,17'
> +.*: Error: illegal operands `cv.mulu 9,t2,t0'
> +.*: Error: illegal operands `cv.mulhhu 54,t2,t0'
> +.*: Error: illegal operands `cv.mulun 965,t2,t0,7'
> +.*: Error: illegal operands `cv.mulhhun 35,t2,t0,16'
> +.*: Error: illegal operands `cv.mulurn 87,t2,t0,11'
> +.*: Error: illegal operands `cv.mulhhurn 38,t2,t0,9'
> +.*: Error: illegal operands `cv.macsn 985,t2,t0,24'
> +.*: Error: illegal operands `cv.machhsn 83,t2,t0,11'
> +.*: Error: illegal operands `cv.macsrn 960,t2,t0,9'
> +.*: Error: illegal operands `cv.machhsrn 385,t2,t0,24'
> +.*: Error: illegal operands `cv.macun 58,t2,t0,27'
> +.*: Error: illegal operands `cv.machhun 6,t2,t0,18'
> +.*: Error: illegal operands `cv.macurn 35,t2,t0,25'
> +.*: Error: illegal operands `cv.machhurn 67,t2,t0,5'
> +.*: Error: illegal operands `cv.mac t4,43,t0'
> +.*: Error: illegal operands `cv.msu t4,3,t0'
> +.*: Error: illegal operands `cv.muls t4,345,t0'
> +.*: Error: illegal operands `cv.mulhhs t4,54,t0'
> +.*: Error: illegal operands `cv.mulsn t4,4,t0,4'
> +.*: Error: illegal operands `cv.mulhhsn t4,35,t0,16'
> +.*: Error: illegal operands `cv.mulsrn t4,53,t0,10'
> +.*: Error: illegal operands `cv.mulhhsrn t4,4456,t0,17'
> +.*: Error: illegal operands `cv.mulu t4,868,t0'
> +.*: Error: illegal operands `cv.mulhhu t4,95,t0'
> +.*: Error: illegal operands `cv.mulun t4,584,t0,7'
> +.*: Error: illegal operands `cv.mulhhun t4,37545,t0,16'
> +.*: Error: illegal operands `cv.mulurn t4,943,t0,11'
> +.*: Error: illegal operands `cv.mulhhurn t4,34,t0,9'
> +.*: Error: illegal operands `cv.macsn t4,93,t0,24'
> +.*: Error: illegal operands `cv.machhsn t4,584,t0,11'
> +.*: Error: illegal operands `cv.macsrn t4,28,t0,9'
> +.*: Error: illegal operands `cv.machhsrn t4,9,t0,24'
> +.*: Error: illegal operands `cv.macun t4,834,t0,27'
> +.*: Error: illegal operands `cv.machhun t4,92,t0,18'
> +.*: Error: illegal operands `cv.macurn t4,49,t0,25'
> +.*: Error: illegal operands `cv.machhurn t4,6,t0,5'
> +.*: Error: illegal operands `cv.mac t4,t2,344'
> +.*: Error: illegal operands `cv.msu t4,t2,23'
> +.*: Error: illegal operands `cv.muls t4,t2,2'
> +.*: Error: illegal operands `cv.mulhhs t4,t2,8'
> +.*: Error: illegal operands `cv.mulsn t4,t2,45,4'
> +.*: Error: illegal operands `cv.mulhhsn t4,t2,655,16'
> +.*: Error: illegal operands `cv.mulsrn t4,t2,465,10'
> +.*: Error: illegal operands `cv.mulhhsrn t4,t2,3534,17'
> +.*: Error: illegal operands `cv.mulu t4,t2,46'
> +.*: Error: illegal operands `cv.mulhhu t4,t2,35'
> +.*: Error: illegal operands `cv.mulun t4,t2,67,7'
> +.*: Error: illegal operands `cv.mulhhun t4,t2,6,16'
> +.*: Error: illegal operands `cv.mulurn t4,t2,787,11'
> +.*: Error: illegal operands `cv.mulhhurn t4,t2,3545,9'
> +.*: Error: illegal operands `cv.macsn t4,t2,6,24'
> +.*: Error: illegal operands `cv.machhsn t4,t2,765,11'
> +.*: Error: illegal operands `cv.macsrn t4,t2,45,9'
> +.*: Error: illegal operands `cv.machhsrn t4,t2,7,24'
> +.*: Error: illegal operands `cv.macun t4,t2,98,27'
> +.*: Error: illegal operands `cv.machhun t4,t2,654,18'
> +.*: Error: illegal operands `cv.macurn t4,t2,900,25'
> +.*: Error: illegal operands `cv.machhurn t4,t2,354,5'
> +.*: Error: illegal operands `cv.mulsn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulsrn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulun t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulhhun t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulurn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.macsn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.machhsn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.macsrn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.machhsrn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.macun t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.machhun t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.macurn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.machhurn t4,t2,t0,-1'
> +.*: Error: illegal operands `cv.mulsn t4,t2,t0,-43'
> +.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,-531'
> +.*: Error: illegal operands `cv.mulsrn t4,t2,t0,-4454'
> +.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,-32'
> +.*: Error: illegal operands `cv.mulun t4,t2,t0,-23'
> +.*: Error: illegal operands `cv.mulhhun t4,t2,t0,-459'
> +.*: Error: illegal operands `cv.mulurn t4,t2,t0,-549'
> +.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,-32'
> +.*: Error: illegal operands `cv.macsn t4,t2,t0,-223'
> +.*: Error: illegal operands `cv.machhsn t4,t2,t0,-56'
> +.*: Error: illegal operands `cv.macsrn t4,t2,t0,-8'
> +.*: Error: illegal operands `cv.machhsrn t4,t2,t0,-2'
> +.*: Error: illegal operands `cv.macun t4,t2,t0,-432'
> +.*: Error: illegal operands `cv.machhun t4,t2,t0,-1245'
> +.*: Error: illegal operands `cv.macurn t4,t2,t0,-45'
> +.*: Error: illegal operands `cv.machhurn t4,t2,t0,-354'
> +.*: Error: illegal operands `cv.mulsn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulsrn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulun t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulhhun t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulurn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.macsn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.machhsn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.macsrn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.machhsrn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.macun t4,t2,t0,32'
> +.*: Error: illegal operands `cv.machhun t4,t2,t0,32'
> +.*: Error: illegal operands `cv.macurn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.machhurn t4,t2,t0,32'
> +.*: Error: illegal operands `cv.mulsn t4,t2,t0,325'
> +.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,531'
> +.*: Error: illegal operands `cv.mulsrn t4,t2,t0,4454'
> +.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,254'
> +.*: Error: illegal operands `cv.mulun t4,t2,t0,76'
> +.*: Error: illegal operands `cv.mulhhun t4,t2,t0,459'
> +.*: Error: illegal operands `cv.mulurn t4,t2,t0,549'
> +.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,5364'
> +.*: Error: illegal operands `cv.macsn t4,t2,t0,34435'
> +.*: Error: illegal operands `cv.machhsn t4,t2,t0,56'
> +.*: Error: illegal operands `cv.macsrn t4,t2,t0,3423'
> +.*: Error: illegal operands `cv.machhsrn t4,t2,t0,365'
> +.*: Error: illegal operands `cv.macun t4,t2,t0,432'
> +.*: Error: illegal operands `cv.machhun t4,t2,t0,1245'
> +.*: Error: illegal operands `cv.macurn t4,t2,t0,45'
> +.*: Error: instruction cv.mulsn requires absolute expression
> +.*: Error: instruction cv.mulhhsn requires absolute expression
> +.*: Error: instruction cv.mulsrn requires absolute expression
> +.*: Error: instruction cv.mulhhsrn requires absolute expression
> +.*: Error: instruction cv.mulun requires absolute expression
> +.*: Error: instruction cv.mulhhun requires absolute expression
> +.*: Error: instruction cv.mulurn requires absolute expression
> +.*: Error: instruction cv.mulhhurn requires absolute expression
> +.*: Error: instruction cv.macsn requires absolute expression
> +.*: Error: instruction cv.machhsn requires absolute expression
> +.*: Error: instruction cv.macsrn requires absolute expression
> +.*: Error: instruction cv.machhsrn requires absolute expression
> +.*: Error: instruction cv.macun requires absolute expression
> +.*: Error: instruction cv.machhun requires absolute expression
> +.*: Error: instruction cv.macurn requires absolute expression
> +.*: Error: instruction cv.machhurn requires absolute expression
> +.*: Error: illegal operands `cv.machhurn t4,t2,t0,354'
> diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.s
> b/gas/testsuite/gas/riscv/cv-mac-fail-operand.s
> new file mode 100644
> index 00000000000..97a29448ebd
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.s
> @@ -0,0 +1,156 @@
> +# Destination must be of type register
> +target:
> +       cv.mac 8, t2, t0
> +       cv.msu 23, t2, t0
> +       cv.muls 43, t2, t0
> +       cv.mulhhs 7, t2, t0
> +       cv.mulsn 345, t2, t0, 4
> +       cv.mulhhsn 356, t2, t0, 16
> +       cv.mulsrn 867, t2, t0, 10
> +       cv.mulhhsrn 3454, t2, t0, 17
> +       cv.mulu 9, t2, t0
> +       cv.mulhhu 54, t2, t0
> +       cv.mulun 965, t2, t0, 7
> +       cv.mulhhun 35, t2, t0, 16
> +       cv.mulurn 87, t2, t0, 11
> +       cv.mulhhurn 38, t2, t0, 9
> +       cv.macsn 985, t2, t0, 24
> +       cv.machhsn 83, t2, t0, 11
> +       cv.macsrn 960, t2, t0, 9
> +       cv.machhsrn 385, t2, t0, 24
> +       cv.macun 58, t2, t0, 27
> +       cv.machhun 6, t2, t0, 18
> +       cv.macurn 35, t2, t0, 25
> +       cv.machhurn 67, t2, t0, 5
> +
> +# Source one must be of type register
> +       cv.mac t4, 43, t0
> +       cv.msu t4, 3, t0
> +       cv.muls t4, 345, t0
> +       cv.mulhhs t4, 54, t0
> +       cv.mulsn t4, 4, t0, 4
> +       cv.mulhhsn t4, 35, t0, 16
> +       cv.mulsrn t4, 53, t0, 10
> +       cv.mulhhsrn t4, 4456, t0, 17
> +       cv.mulu t4, 868, t0
> +       cv.mulhhu t4, 95, t0
> +       cv.mulun t4, 584, t0, 7
> +       cv.mulhhun t4, 37545, t0, 16
> +       cv.mulurn t4, 943, t0, 11
> +       cv.mulhhurn t4, 34, t0, 9
> +       cv.macsn t4, 93, t0, 24
> +       cv.machhsn t4, 584, t0, 11
> +       cv.macsrn t4, 28, t0, 9
> +       cv.machhsrn t4, 9, t0, 24
> +       cv.macun t4, 834, t0, 27
> +       cv.machhun t4, 92, t0, 18
> +       cv.macurn t4, 49, t0, 25
> +       cv.machhurn t4, 6, t0, 5
> +
> +# Source two must be of type register
> +       cv.mac t4, t2, 344
> +       cv.msu t4, t2, 23
> +       cv.muls t4, t2, 2
> +       cv.mulhhs t4, t2, 8
> +       cv.mulsn t4, t2, 45, 4
> +       cv.mulhhsn t4, t2, 655, 16
> +       cv.mulsrn t4, t2, 465, 10
> +       cv.mulhhsrn t4, t2, 3534, 17
> +       cv.mulu t4, t2, 46
> +       cv.mulhhu t4, t2, 35
> +       cv.mulun t4, t2, 67, 7
> +       cv.mulhhun t4, t2, 6, 16
> +       cv.mulurn t4, t2, 787, 11
> +       cv.mulhhurn t4, t2, 3545, 9
> +       cv.macsn t4, t2, 6, 24
> +       cv.machhsn t4, t2, 765, 11
> +       cv.macsrn t4, t2, 45, 9
> +       cv.machhsrn t4, t2, 7, 24
> +       cv.macun t4, t2, 98, 27
> +       cv.machhun t4, t2, 654, 18
> +       cv.macurn t4, t2, 900, 25
> +       cv.machhurn t4, t2, 354, 5
> +
> +# Immediate value must be in range [0, 31]
> +       cv.mulsn t4, t2, t0, -1
> +       cv.mulhhsn t4, t2, t0, -1
> +       cv.mulsrn t4, t2, t0, -1
> +       cv.mulhhsrn t4, t2, t0, -1
> +       cv.mulun t4, t2, t0, -1
> +       cv.mulhhun t4, t2, t0, -1
> +       cv.mulurn t4, t2, t0, -1
> +       cv.mulhhurn t4, t2, t0, -1
> +       cv.macsn t4, t2, t0, -1
> +       cv.machhsn t4, t2, t0, -1
> +       cv.macsrn t4, t2, t0, -1
> +       cv.machhsrn t4, t2, t0, -1
> +       cv.macun t4, t2, t0, -1
> +       cv.machhun t4, t2, t0, -1
> +       cv.macurn t4, t2, t0, -1
> +       cv.machhurn t4, t2, t0, -1
> +       cv.mulsn t4, t2, t0, -43
> +       cv.mulhhsn t4, t2, t0, -531
> +       cv.mulsrn t4, t2, t0, -4454
> +       cv.mulhhsrn t4, t2, t0, -32
> +       cv.mulun t4, t2, t0, -23
> +       cv.mulhhun t4, t2, t0, -459
> +       cv.mulurn t4, t2, t0, -549
> +       cv.mulhhurn t4, t2, t0, -32
> +       cv.macsn t4, t2, t0, -223
> +       cv.machhsn t4, t2, t0, -56
> +       cv.macsrn t4, t2, t0, -8
> +       cv.machhsrn t4, t2, t0, -2
> +       cv.macun t4, t2, t0, -432
> +       cv.machhun t4, t2, t0, -1245
> +       cv.macurn t4, t2, t0, -45
> +       cv.machhurn t4, t2, t0, -354
> +       cv.mulsn t4, t2, t0, 32
> +       cv.mulhhsn t4, t2, t0, 32
> +       cv.mulsrn t4, t2, t0, 32
> +       cv.mulhhsrn t4, t2, t0, 32
> +       cv.mulun t4, t2, t0, 32
> +       cv.mulhhun t4, t2, t0, 32
> +       cv.mulurn t4, t2, t0, 32
> +       cv.mulhhurn t4, t2, t0, 32
> +       cv.macsn t4, t2, t0, 32
> +       cv.machhsn t4, t2, t0, 32
> +       cv.macsrn t4, t2, t0, 32
> +       cv.machhsrn t4, t2, t0, 32
> +       cv.macun t4, t2, t0, 32
> +       cv.machhun t4, t2, t0, 32
> +       cv.macurn t4, t2, t0, 32
> +       cv.machhurn t4, t2, t0, 32
> +       cv.mulsn t4, t2, t0, 325
> +       cv.mulhhsn t4, t2, t0, 531
> +       cv.mulsrn t4, t2, t0, 4454
> +       cv.mulhhsrn t4, t2, t0, 254
> +       cv.mulun t4, t2, t0, 76
> +       cv.mulhhun t4, t2, t0, 459
> +       cv.mulurn t4, t2, t0, 549
> +       cv.mulhhurn t4, t2, t0, 5364
> +       cv.macsn t4, t2, t0, 34435
> +       cv.machhsn t4, t2, t0, 56
> +       cv.macsrn t4, t2, t0, 3423
> +       cv.machhsrn t4, t2, t0, 365
> +       cv.macun t4, t2, t0, 432
> +       cv.machhun t4, t2, t0, 1245
> +       cv.macurn t4, t2, t0, 45
> +
> +# Immediate value must be an absolute expression
> +       cv.mulsn t4, t2, t0, t3
> +       cv.mulhhsn t4, t2, t0, t1
> +       cv.mulsrn t4, t2, t0, t6
> +       cv.mulhhsrn t4, t2, t0, t3
> +       cv.mulun t4, t2, t0, t1
> +       cv.mulhhun t4, t2, t0, t3
> +       cv.mulurn t4, t2, t0, t5
> +       cv.mulhhurn t4, t2, t0, t1
> +       cv.macsn t4, t2, t0, t3
> +       cv.machhsn t4, t2, t0, t5
> +       cv.macsrn t4, t2, t0, t1
> +       cv.machhsrn t4, t2, t0, t6
> +       cv.macun t4, t2, t0, t1
> +       cv.machhun t4, t2, t0, t3
> +       cv.macurn t4, t2, t0, t6
> +       cv.machhurn t4, t2, t0, t5
> +       cv.machhurn t4, t2, t0, 354
> diff --git a/gas/testsuite/gas/riscv/cv-mac-insns.d
> b/gas/testsuite/gas/riscv/cv-mac-insns.d
> new file mode 100644
> index 00000000000..9a961051a97
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-insns.d
> @@ -0,0 +1,87 @@
> +#as: -march=rv32i_xcvmac
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+0:[   ]+907332ab[     ]+cv.mac[       ]+t0,t1,t2
> +[      ]+4:[   ]+9053beab[     ]+cv.mac[       ]+t4,t2,t0
> +[      ]+8:[   ]+906f3e2b[     ]+cv.mac[       ]+t3,t5,t1
> +[      ]+c:[   ]+407362db[     ]+cv.machhsn[   ]+t0,t1,t2,0
> +[      ]+10:[  ]+5653eedb[     ]+cv.machhsn[   ]+t4,t2,t0,11
> +[      ]+14:[  ]+7e6f6e5b[     ]+cv.machhsn[   ]+t3,t5,t1,31
> +[      ]+18:[  ]+c07362db[     ]+cv.machhsrn[  ]+t0,t1,t2,0
> +[      ]+1c:[  ]+f053eedb[     ]+cv.machhsrn[  ]+t4,t2,t0,24
> +[      ]+20:[  ]+fe6f6e5b[     ]+cv.machhsrn[  ]+t3,t5,t1,31
> +[      ]+24:[  ]+407372db[     ]+cv.machhun[   ]+t0,t1,t2,0
> +[      ]+28:[  ]+6453fedb[     ]+cv.machhun[   ]+t4,t2,t0,18
> +[      ]+2c:[  ]+7e6f7e5b[     ]+cv.machhun[   ]+t3,t5,t1,31
> +[      ]+30:[  ]+c07372db[     ]+cv.machhurn[  ]+t0,t1,t2,0
> +[      ]+34:[  ]+ca53fedb[     ]+cv.machhurn[  ]+t4,t2,t0,5
> +[      ]+38:[  ]+fe6f7e5b[     ]+cv.machhurn[  ]+t3,t5,t1,31
> +[      ]+3c:[  ]+007362db[     ]+cv.macsn[     ]+t0,t1,t2,0
> +[      ]+40:[  ]+3053eedb[     ]+cv.macsn[     ]+t4,t2,t0,24
> +[      ]+44:[  ]+3e6f6e5b[     ]+cv.macsn[     ]+t3,t5,t1,31
> +[      ]+48:[  ]+807362db[     ]+cv.macsrn[    ]+t0,t1,t2,0
> +[      ]+4c:[  ]+9253eedb[     ]+cv.macsrn[    ]+t4,t2,t0,9
> +[      ]+50:[  ]+be6f6e5b[     ]+cv.macsrn[    ]+t3,t5,t1,31
> +[      ]+54:[  ]+007372db[     ]+cv.macun[     ]+t0,t1,t2,0
> +[      ]+58:[  ]+3653fedb[     ]+cv.macun[     ]+t4,t2,t0,27
> +[      ]+5c:[  ]+3e6f7e5b[     ]+cv.macun[     ]+t3,t5,t1,31
> +[      ]+60:[  ]+807372db[     ]+cv.macurn[    ]+t0,t1,t2,0
> +[      ]+64:[  ]+b253fedb[     ]+cv.macurn[    ]+t4,t2,t0,25
> +[      ]+68:[  ]+be6f7e5b[     ]+cv.macurn[    ]+t3,t5,t1,31
> +[      ]+6c:[  ]+927332ab[     ]+cv.msu[       ]+t0,t1,t2
> +[      ]+70:[  ]+9253beab[     ]+cv.msu[       ]+t4,t2,t0
> +[      ]+74:[  ]+926f3e2b[     ]+cv.msu[       ]+t3,t5,t1
> +[      ]+78:[  ]+407342db[     ]+cv.mulhhsn[   ]+t0,t1,t2,0
> +[      ]+7c:[  ]+4053cedb[     ]+cv.mulhhsn[   ]+t4,t2,t0,0
> +[      ]+80:[  ]+406f4e5b[     ]+cv.mulhhsn[   ]+t3,t5,t1,0
> +[      ]+84:[  ]+407342db[     ]+cv.mulhhsn[   ]+t0,t1,t2,0
> +[      ]+88:[  ]+6053cedb[     ]+cv.mulhhsn[   ]+t4,t2,t0,16
> +[      ]+8c:[  ]+7e6f4e5b[     ]+cv.mulhhsn[   ]+t3,t5,t1,31
> +[      ]+90:[  ]+c07342db[     ]+cv.mulhhsrn[  ]+t0,t1,t2,0
> +[      ]+94:[  ]+e253cedb[     ]+cv.mulhhsrn[  ]+t4,t2,t0,17
> +[      ]+98:[  ]+fe6f4e5b[     ]+cv.mulhhsrn[  ]+t3,t5,t1,31
> +[      ]+9c:[  ]+407352db[     ]+cv.mulhhun[   ]+t0,t1,t2,0
> +[      ]+a0:[  ]+4053dedb[     ]+cv.mulhhun[   ]+t4,t2,t0,0
> +[      ]+a4:[  ]+406f5e5b[     ]+cv.mulhhun[   ]+t3,t5,t1,0
> +[      ]+a8:[  ]+407352db[     ]+cv.mulhhun[   ]+t0,t1,t2,0
> +[      ]+ac:[  ]+6053dedb[     ]+cv.mulhhun[   ]+t4,t2,t0,16
> +[      ]+b0:[  ]+7e6f5e5b[     ]+cv.mulhhun[   ]+t3,t5,t1,31
> +[      ]+b4:[  ]+c07352db[     ]+cv.mulhhurn[  ]+t0,t1,t2,0
> +[      ]+b8:[  ]+d253dedb[     ]+cv.mulhhurn[  ]+t4,t2,t0,9
> +[      ]+bc:[  ]+fe6f5e5b[     ]+cv.mulhhurn[  ]+t3,t5,t1,31
> +[      ]+c0:[  ]+007342db[     ]+cv.mulsn[     ]+t0,t1,t2,0
> +[      ]+c4:[  ]+0053cedb[     ]+cv.mulsn[     ]+t4,t2,t0,0
> +[      ]+c8:[  ]+006f4e5b[     ]+cv.mulsn[     ]+t3,t5,t1,0
> +[      ]+cc:[  ]+007342db[     ]+cv.mulsn[     ]+t0,t1,t2,0
> +[      ]+d0:[  ]+0853cedb[     ]+cv.mulsn[     ]+t4,t2,t0,4
> +[      ]+d4:[  ]+3e6f4e5b[     ]+cv.mulsn[     ]+t3,t5,t1,31
> +[      ]+d8:[  ]+807342db[     ]+cv.mulsrn[    ]+t0,t1,t2,0
> +[      ]+dc:[  ]+9453cedb[     ]+cv.mulsrn[    ]+t4,t2,t0,10
> +[      ]+e0:[  ]+be6f4e5b[     ]+cv.mulsrn[    ]+t3,t5,t1,31
> +[      ]+e4:[  ]+007352db[     ]+cv.mulun[     ]+t0,t1,t2,0
> +[      ]+e8:[  ]+0053dedb[     ]+cv.mulun[     ]+t4,t2,t0,0
> +[      ]+ec:[  ]+006f5e5b[     ]+cv.mulun[     ]+t3,t5,t1,0
> +[      ]+f0:[  ]+007352db[     ]+cv.mulun[     ]+t0,t1,t2,0
> +[      ]+f4:[  ]+0e53dedb[     ]+cv.mulun[     ]+t4,t2,t0,7
> +[      ]+f8:[  ]+3e6f5e5b[     ]+cv.mulun[     ]+t3,t5,t1,31
> +[      ]+fc:[  ]+807352db[     ]+cv.mulurn[    ]+t0,t1,t2,0
> +[      ]+100:[         ]+9653dedb[     ]+cv.mulurn[    ]+t4,t2,t0,11
> +[      ]+104:[         ]+be6f5e5b[     ]+cv.mulurn[    ]+t3,t5,t1,31
> +[      ]+108:[         ]+407342db[     ]+cv.mulhhsn[   ]+t0,t1,t2,0
> +[      ]+10c:[         ]+4053cedb[     ]+cv.mulhhsn[   ]+t4,t2,t0,0
> +[      ]+110:[         ]+406f4e5b[     ]+cv.mulhhsn[   ]+t3,t5,t1,0
> +[      ]+114:[         ]+407352db[     ]+cv.mulhhun[   ]+t0,t1,t2,0
> +[      ]+118:[         ]+4053dedb[     ]+cv.mulhhun[   ]+t4,t2,t0,0
> +[      ]+11c:[         ]+406f5e5b[     ]+cv.mulhhun[   ]+t3,t5,t1,0
> +[      ]+120:[         ]+007342db[     ]+cv.mulsn[     ]+t0,t1,t2,0
> +[      ]+124:[         ]+0053cedb[     ]+cv.mulsn[     ]+t4,t2,t0,0
> +[      ]+128:[         ]+006f4e5b[     ]+cv.mulsn[     ]+t3,t5,t1,0
> +[      ]+12c:[         ]+007352db[     ]+cv.mulun[     ]+t0,t1,t2,0
> +[      ]+130:[         ]+0053dedb[     ]+cv.mulun[     ]+t4,t2,t0,0
> +[      ]+134:[         ]+006f5e5b[     ]+cv.mulun[     ]+t3,t5,t1,0
> diff --git a/gas/testsuite/gas/riscv/cv-mac-insns.s
> b/gas/testsuite/gas/riscv/cv-mac-insns.s
> new file mode 100644
> index 00000000000..a699a3ba461
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/cv-mac-insns.s
> @@ -0,0 +1,81 @@
> +target:
> +       cv.mac t0, t1, t2
> +       cv.mac t4, t2, t0
> +       cv.mac t3, t5, t1
> +       cv.machhsn t0, t1, t2, 0
> +       cv.machhsn t4, t2, t0, 11
> +       cv.machhsn t3, t5, t1, 31
> +       cv.machhsrn t0, t1, t2, 0
> +       cv.machhsrn t4, t2, t0, 24
> +       cv.machhsrn t3, t5, t1, 31
> +       cv.machhun t0, t1, t2, 0
> +       cv.machhun t4, t2, t0, 18
> +       cv.machhun t3, t5, t1, 31
> +       cv.machhurn t0, t1, t2, 0
> +       cv.machhurn t4, t2, t0, 5
> +       cv.machhurn t3, t5, t1, 31
> +       cv.macsn t0, t1, t2, 0
> +       cv.macsn t4, t2, t0, 24
> +       cv.macsn t3, t5, t1, 31
> +       cv.macsrn t0, t1, t2, 0
> +       cv.macsrn t4, t2, t0, 9
> +       cv.macsrn t3, t5, t1, 31
> +       cv.macun t0, t1, t2, 0
> +       cv.macun t4, t2, t0, 27
> +       cv.macun t3, t5, t1, 31
> +       cv.macurn t0, t1, t2, 0
> +       cv.macurn t4, t2, t0, 25
> +       cv.macurn t3, t5, t1, 31
> +       cv.msu t0, t1, t2
> +       cv.msu t4, t2, t0
> +       cv.msu t3, t5, t1
> +       cv.mulhhs t0, t1, t2
> +       cv.mulhhs t4, t2, t0
> +       cv.mulhhs t3, t5, t1
> +       cv.mulhhsn t0, t1, t2, 0
> +       cv.mulhhsn t4, t2, t0, 16
> +       cv.mulhhsn t3, t5, t1, 31
> +       cv.mulhhsrn t0, t1, t2, 0
> +       cv.mulhhsrn t4, t2, t0, 17
> +       cv.mulhhsrn t3, t5, t1, 31
> +       cv.mulhhu t0, t1, t2
> +       cv.mulhhu t4, t2, t0
> +       cv.mulhhu t3, t5, t1
> +       cv.mulhhun t0, t1, t2, 0
> +       cv.mulhhun t4, t2, t0, 16
> +       cv.mulhhun t3, t5, t1, 31
> +       cv.mulhhurn t0, t1, t2, 0
> +       cv.mulhhurn t4, t2, t0, 9
> +       cv.mulhhurn t3, t5, t1, 31
> +       cv.muls t0, t1, t2
> +       cv.muls t4, t2, t0
> +       cv.muls t3, t5, t1
> +       cv.mulsn t0, t1, t2, 0
> +       cv.mulsn t4, t2, t0, 4
> +       cv.mulsn t3, t5, t1, 31
> +       cv.mulsrn t0, t1, t2, 0
> +       cv.mulsrn t4, t2, t0, 10
> +       cv.mulsrn t3, t5, t1, 31
> +       cv.mulu t0, t1, t2
> +       cv.mulu t4, t2, t0
> +       cv.mulu t3, t5, t1
> +       cv.mulun t0, t1, t2, 0
> +       cv.mulun t4, t2, t0, 7
> +       cv.mulun t3, t5, t1, 31
> +       cv.mulurn t0, t1, t2, 0
> +       cv.mulurn t4, t2, t0, 11
> +       cv.mulurn t3, t5, t1, 31
> +
> +  # Pseudo-instructions
> +       cv.mulhhsn t0, t1, t2, 0
> +       cv.mulhhsn t4, t2, t0, 0
> +       cv.mulhhsn t3, t5, t1, 0
> +       cv.mulhhun t0, t1, t2, 0
> +       cv.mulhhun t4, t2, t0, 0
> +       cv.mulhhun t3, t5, t1, 0
> +       cv.mulsn t0, t1, t2, 0
> +       cv.mulsn t4, t2, t0, 0
> +       cv.mulsn t3, t5, t1, 0
> +       cv.mulun t0, t1, t2, 0
> +       cv.mulun t4, t2, t0, 0
> +       cv.mulun t3, t5, t1, 0
> diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
> index 26d2c04bf24..199ae63585f 100644
> --- a/include/opcode/riscv-opc.h
> +++ b/include/opcode/riscv-opc.h
> @@ -2320,6 +2320,27 @@
>  #define MASK_WRS_NTO 0xffffffff
>  #define MATCH_WRS_STO 0x01d00073
>  #define MASK_WRS_STO 0xffffffff
> +/* Vendor-specific (CORE-V) Xcvmac instructions.  */
> +#define MATCH_CV_MAC       0x9000302b
> +#define MATCH_CV_MSU       0x9200302b
> +#define MASK_CV_MACMSU     0xfe00707f
> +#define MATCH_CV_MULSN     0x405b
> +#define MATCH_CV_MULHHSN   0x4000405b
> +#define MATCH_CV_MULSRN    0x8000405b
> +#define MATCH_CV_MULHHSRN  0xc000405b
> +#define MATCH_CV_MULUN     0x505b
> +#define MATCH_CV_MULHHUN   0x4000505b
> +#define MATCH_CV_MULURN    0x8000505b
> +#define MATCH_CV_MULHHURN  0xc000505b
> +#define MATCH_CV_MACSN     0x605b
> +#define MATCH_CV_MACHHSN   0x4000605b
> +#define MATCH_CV_MACSRN    0x8000605b
> +#define MATCH_CV_MACHHSRN  0xc000605b
> +#define MATCH_CV_MACUN     0x705b
> +#define MATCH_CV_MACHHUN   0x4000705b
> +#define MATCH_CV_MACURN    0x8000705b
> +#define MATCH_CV_MACHHURN  0xc000705b
> +#define MASK_CV_MULMACN    0xc000707f
>  /* Vendor-specific (T-Head) XTheadBa instructions.  */
>  #define MATCH_TH_ADDSL 0x0000100b
>  #define MASK_TH_ADDSL 0xf800707f
> diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
> index 38927bd0c74..5097d2cf6c1 100644
> --- a/include/opcode/riscv.h
> +++ b/include/opcode/riscv.h
> @@ -112,6 +112,9 @@ static inline unsigned int riscv_insn_length (insn_t
> insn)
>    (RV_X(x, 6, 1) | (RV_X(x, 5, 1) << 1))
>  #define EXTRACT_ZCB_HALFWORD_UIMM(x) \
>    (RV_X(x, 5, 1) << 1)
> +/* Vendor-specific (CORE-V) extract macros.  */
> +#define EXTRACT_CV_IS3_UIMM5(x) \
> +  (RV_X(x, 25, 5))
>
>  #define ENCODE_ITYPE_IMM(x) \
>    (RV_X(x, 0, 12) << 20)
> @@ -163,6 +166,9 @@ static inline unsigned int riscv_insn_length (insn_t
> insn)
>    ((RV_X(x, 0, 1) << 6) | (RV_X(x, 1, 1) << 5))
>  #define ENCODE_ZCB_HALFWORD_UIMM(x) \
>    (RV_X(x, 1, 1) << 5)
> +/* Vendor-specific (CORE-V) encode macros.  */
> +#define ENCODE_CV_IS3_UIMM5(x) \
> +  (RV_X(x, 0, 5) << 25)
>
>  #define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
>  #define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
> @@ -443,6 +449,7 @@ enum riscv_insn_class
>    INSN_CLASS_ZICBOP,
>    INSN_CLASS_ZICBOZ,
>    INSN_CLASS_H,
> +  INSN_CLASS_XCVMAC,
>    INSN_CLASS_XTHEADBA,
>    INSN_CLASS_XTHEADBB,
>    INSN_CLASS_XTHEADBS,
> diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
> index 90f0fea1692..b16db5113b1 100644
> --- a/opcodes/riscv-dis.c
> +++ b/opcodes/riscv-dis.c
> @@ -429,6 +429,22 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma
> pc, disassemble_info *info
>             print (info->stream, dis_style_immediate, "0");
>           break;
>
> +       case 'x': /* Vendor-specific operands.  */
>

Likewise, use `X'.


> +         switch (*++oparg)
> +           {
> +             /* Vendor-specific (CORE-V) operands.  */
> +             case 'c':
> +               switch (*++oparg)
> +                 {
> +                   case '3':
> +                     print (info->stream, dis_style_immediate, "%d",
> +                            ((int) EXTRACT_CV_IS3_UIMM5 (l)));
> +                     break;
> +                 }
> +               break;
> +           }
> +         break;
> +
>         case 's':
>           if ((l & MASK_JALR) == MATCH_JALR)
>             maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index 39da5f84e74..1b2023b96bd 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -154,6 +154,8 @@ const float riscv_fli_numval[32] =
>  #define MASK_VS1 (OP_MASK_VS1 << OP_SH_VS1)
>  #define MASK_VS2 (OP_MASK_VS2 << OP_SH_VS2)
>  #define MASK_VMASK (OP_MASK_VMASK << OP_SH_VMASK)
> +/* Vendor-specific (CORE-V) masks.  */
> +#define MASK_CV_IS3_UIMM5 ENCODE_CV_IS3_UIMM5 (-1U)
>
>  static int
>  match_opcode (const struct riscv_opcode *op, insn_t insn)
> @@ -2039,6 +2041,30 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"hsv.w",       0, INSN_CLASS_H, "t,0(s)", MATCH_HSV_W, MASK_HSV_W,
> match_opcode, INSN_DREF|INSN_4_BYTE },
>  {"hsv.d",      64, INSN_CLASS_H, "t,0(s)", MATCH_HSV_D, MASK_HSV_D,
> match_opcode, INSN_DREF|INSN_8_BYTE },
>
> +/* Vendor-specific (CORE-V) Xcvmac instructions.  */
>

Instructions are named starting with "cv." looks reasonable and good.


> +{"cv.mac",      0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MAC,
>    MASK_CV_MACMSU, match_opcode, 0},
> +{"cv.msu",      0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MSU,
>    MASK_CV_MACMSU, match_opcode, 0},
> +{"cv.mulsn",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULSN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.muls",     0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULSN,
> MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
> +{"cv.mulsrn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULSRN,
>  MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulhhsn",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHSN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulhhs",   0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULHHSN,
> MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
> +{"cv.mulhhsrn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHSRN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulun",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULUN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulu",     0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULUN,
> MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
> +{"cv.mulurn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULURN,
>  MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulhhun",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHUN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.mulhhu",   0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULHHUN,
> MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
> +{"cv.mulhhurn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHURN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.macsn",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACSN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.machhsn",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHSN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.macsrn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACSRN,
>  MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.machhsrn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHSRN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.macun",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACUN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.machhun",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHUN,
> MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.macurn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACURN,
>  MASK_CV_MULMACN, match_opcode, 0},
> +{"cv.machhurn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHURN,
> MASK_CV_MULMACN, match_opcode, 0},
> +
>  /* Vendor-specific (T-Head) XTheadBa instructions.  */
>  {"th.addsl",    0, INSN_CLASS_XTHEADBA,    "d,s,t,Xu2@25",
>  MATCH_TH_ADDSL,    MASK_TH_ADDSL,    match_opcode, 0},
>
> --
> 2.34.1
>
>
  

Patch

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index cb65024beaf..a3c32941866 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1347,6 +1347,8 @@  static struct riscv_supported_ext riscv_supported_std_zxm_ext[] =
 
 static struct riscv_supported_ext riscv_supported_vendor_x_ext[] =
 {
+  /* CORE-V ISA extension spec: https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html */
+  {"xcvmac",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {"xtheadba",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {"xtheadbb",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
   {"xtheadbs",		ISA_SPEC_CLASS_DRAFT,	1, 0, 0 },
@@ -2539,6 +2541,8 @@  riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "svinval");
     case INSN_CLASS_H:
       return riscv_subset_supports (rps, "h");
+    case INSN_CLASS_XCVMAC:
+      return riscv_subset_supports (rps, "xcvmac");
     case INSN_CLASS_XTHEADBA:
       return riscv_subset_supports (rps, "xtheadba");
     case INSN_CLASS_XTHEADBB:
@@ -2779,6 +2783,8 @@  riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "svinval";
     case INSN_CLASS_H:
       return _("h");
+    case INSN_CLASS_XCVMAC:
+      return "xcvmac";
     case INSN_CLASS_XTHEADBA:
       return "xtheadba";
     case INSN_CLASS_XTHEADBB:
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index e49b34fd524..3100a2e135f 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -1470,6 +1470,25 @@  validate_riscv_insn (const struct riscv_opcode *opc, int length)
 	      }
 	  }
 	  break;
+	case 'x': /* Vendor-specific operands.  */
+	  switch (*++oparg)
+	    {
+	      /* Vendor-specific (CORE-V) operands.  */
+	      case 'c':
+		switch (*++oparg)
+		  {
+		    case '3':
+		      used_bits |= ENCODE_CV_IS3_UIMM5 (-1U);
+		      break;
+		    default:
+		      goto unknown_validate_operand;
+		  }
+		break;
+	      default:
+		goto unknown_validate_operand;
+	    }
+	  break;
+
 	default:
 	unknown_validate_operand:
 	  as_bad (_("internal: bad RISC-V opcode "
@@ -3669,6 +3688,32 @@  riscv_ip (char *str, struct riscv_cl_insn *ip, expressionS *imm_expr,
 	      }
 	      break;
 
+	    case 'x': /* Vendor-specific operands.  */
+	      switch (*++oparg)
+		{
+		  /* Vendor-specific (CORE-V) operands.  */
+		  case 'c':
+		    switch (*++oparg)
+		      {
+			case '3':
+			  my_getExpression (imm_expr, asarg);
+			  check_absolute_expr (ip, imm_expr, FALSE);
+			  asarg = expr_parse_end;
+			  if (imm_expr->X_add_number<0
+			      || imm_expr->X_add_number>31)
+			    break;
+			  ip->insn_opcode
+			    |= ENCODE_CV_IS3_UIMM5 (imm_expr->X_add_number);
+			  continue;
+			default:
+			  goto unknown_riscv_ip_operand;
+		      }
+		    break;
+		  default:
+		    goto unknown_riscv_ip_operand;
+		}
+	    break;
+
 	    default:
 	    unknown_riscv_ip_operand:
 	      as_fatal (_("internal: unknown argument type `%s'"),
diff --git a/gas/doc/c-riscv.texi b/gas/doc/c-riscv.texi
index b175ba0a729..1dcdeeb7b36 100644
--- a/gas/doc/c-riscv.texi
+++ b/gas/doc/c-riscv.texi
@@ -745,6 +745,11 @@  extensions supported and provides the location of their
 publicly-released documentation:
 
 @table @r
+@item Xcvmac
+The Xcvmac extension provides instructions for multiply-accumulate operations.
+
+It is documented in @url{https://docs.openhwgroup.org/projects/cv32e40p-user-manual/en/latest/instruction_set_extensions.html}
+
 @item XTheadBa
 The XTheadBa extension provides instructions for address calculations.
 
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.d b/gas/testsuite/gas/riscv/cv-mac-fail-march.d
new file mode 100644
index 00000000000..eb6352f85f2
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.d
@@ -0,0 +1,3 @@ 
+#as: -march=rv32i
+#source: cv-mac-fail-march.s
+#error_output: cv-mac-fail-march.l
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.l b/gas/testsuite/gas/riscv/cv-mac-fail-march.l
new file mode 100644
index 00000000000..d2bc12c804a
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.l
@@ -0,0 +1,23 @@ 
+.*: Assembler messages:
+.*: Error: unrecognized opcode `cv.mac t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.msu t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.muls t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhs t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulsn t4,t2,t0,4', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhsn t4,t2,t0,16', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulsrn t4,t2,t0,10', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhsrn t4,t2,t0,17', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulu t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhu t4,t2,t0', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulun t4,t2,t0,7', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhun t4,t2,t0,16', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulurn t4,t2,t0,11', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.mulhhurn t4,t2,t0,9', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.macsn t4,t2,t0,24', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.machhsn t4,t2,t0,11', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.macsrn t4,t2,t0,9', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.machhsrn t4,t2,t0,24', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.macun t4,t2,t0,27', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.machhun t4,t2,t0,18', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.macurn t4,t2,t0,25', extension `xcvmac' required
+.*: Error: unrecognized opcode `cv.machhurn t4,t2,t0,5', extension `xcvmac' required
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-march.s b/gas/testsuite/gas/riscv/cv-mac-fail-march.s
new file mode 100644
index 00000000000..78b08423a64
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-march.s
@@ -0,0 +1,24 @@ 
+# Absence of the xcvmac march option disables all CORE-V MAC extensions.
+target:
+	cv.mac t4, t2, t0
+	cv.msu t4, t2, t0
+	cv.muls t4, t2, t0
+	cv.mulhhs t4, t2, t0
+	cv.mulsn t4, t2, t0, 4
+	cv.mulhhsn t4, t2, t0, 16
+	cv.mulsrn t4, t2, t0, 10
+	cv.mulhhsrn t4, t2, t0, 17
+	cv.mulu t4, t2, t0
+	cv.mulhhu t4, t2, t0
+	cv.mulun t4, t2, t0, 7
+	cv.mulhhun t4, t2, t0, 16
+	cv.mulurn t4, t2, t0, 11
+	cv.mulhhurn t4, t2, t0, 9
+	cv.macsn t4, t2, t0, 24
+	cv.machhsn t4, t2, t0, 11
+	cv.macsrn t4, t2, t0, 9
+	cv.machhsrn t4, t2, t0, 24
+	cv.macun t4, t2, t0, 27
+	cv.machhun t4, t2, t0, 18
+	cv.macurn t4, t2, t0, 25
+	cv.machhurn t4, t2, t0, 5
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.d b/gas/testsuite/gas/riscv/cv-mac-fail-operand.d
new file mode 100644
index 00000000000..51e1b3052c9
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.d
@@ -0,0 +1,3 @@ 
+#as: -march=rv32i_xcvmac
+#source: cv-mac-fail-operand.s
+#error_output: cv-mac-fail-operand.l
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.l b/gas/testsuite/gas/riscv/cv-mac-fail-operand.l
new file mode 100644
index 00000000000..645949696cb
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.l
@@ -0,0 +1,147 @@ 
+.*: Assembler messages:
+.*: Error: illegal operands `cv.mac 8,t2,t0'
+.*: Error: illegal operands `cv.msu 23,t2,t0'
+.*: Error: illegal operands `cv.muls 43,t2,t0'
+.*: Error: illegal operands `cv.mulhhs 7,t2,t0'
+.*: Error: illegal operands `cv.mulsn 345,t2,t0,4'
+.*: Error: illegal operands `cv.mulhhsn 356,t2,t0,16'
+.*: Error: illegal operands `cv.mulsrn 867,t2,t0,10'
+.*: Error: illegal operands `cv.mulhhsrn 3454,t2,t0,17'
+.*: Error: illegal operands `cv.mulu 9,t2,t0'
+.*: Error: illegal operands `cv.mulhhu 54,t2,t0'
+.*: Error: illegal operands `cv.mulun 965,t2,t0,7'
+.*: Error: illegal operands `cv.mulhhun 35,t2,t0,16'
+.*: Error: illegal operands `cv.mulurn 87,t2,t0,11'
+.*: Error: illegal operands `cv.mulhhurn 38,t2,t0,9'
+.*: Error: illegal operands `cv.macsn 985,t2,t0,24'
+.*: Error: illegal operands `cv.machhsn 83,t2,t0,11'
+.*: Error: illegal operands `cv.macsrn 960,t2,t0,9'
+.*: Error: illegal operands `cv.machhsrn 385,t2,t0,24'
+.*: Error: illegal operands `cv.macun 58,t2,t0,27'
+.*: Error: illegal operands `cv.machhun 6,t2,t0,18'
+.*: Error: illegal operands `cv.macurn 35,t2,t0,25'
+.*: Error: illegal operands `cv.machhurn 67,t2,t0,5'
+.*: Error: illegal operands `cv.mac t4,43,t0'
+.*: Error: illegal operands `cv.msu t4,3,t0'
+.*: Error: illegal operands `cv.muls t4,345,t0'
+.*: Error: illegal operands `cv.mulhhs t4,54,t0'
+.*: Error: illegal operands `cv.mulsn t4,4,t0,4'
+.*: Error: illegal operands `cv.mulhhsn t4,35,t0,16'
+.*: Error: illegal operands `cv.mulsrn t4,53,t0,10'
+.*: Error: illegal operands `cv.mulhhsrn t4,4456,t0,17'
+.*: Error: illegal operands `cv.mulu t4,868,t0'
+.*: Error: illegal operands `cv.mulhhu t4,95,t0'
+.*: Error: illegal operands `cv.mulun t4,584,t0,7'
+.*: Error: illegal operands `cv.mulhhun t4,37545,t0,16'
+.*: Error: illegal operands `cv.mulurn t4,943,t0,11'
+.*: Error: illegal operands `cv.mulhhurn t4,34,t0,9'
+.*: Error: illegal operands `cv.macsn t4,93,t0,24'
+.*: Error: illegal operands `cv.machhsn t4,584,t0,11'
+.*: Error: illegal operands `cv.macsrn t4,28,t0,9'
+.*: Error: illegal operands `cv.machhsrn t4,9,t0,24'
+.*: Error: illegal operands `cv.macun t4,834,t0,27'
+.*: Error: illegal operands `cv.machhun t4,92,t0,18'
+.*: Error: illegal operands `cv.macurn t4,49,t0,25'
+.*: Error: illegal operands `cv.machhurn t4,6,t0,5'
+.*: Error: illegal operands `cv.mac t4,t2,344'
+.*: Error: illegal operands `cv.msu t4,t2,23'
+.*: Error: illegal operands `cv.muls t4,t2,2'
+.*: Error: illegal operands `cv.mulhhs t4,t2,8'
+.*: Error: illegal operands `cv.mulsn t4,t2,45,4'
+.*: Error: illegal operands `cv.mulhhsn t4,t2,655,16'
+.*: Error: illegal operands `cv.mulsrn t4,t2,465,10'
+.*: Error: illegal operands `cv.mulhhsrn t4,t2,3534,17'
+.*: Error: illegal operands `cv.mulu t4,t2,46'
+.*: Error: illegal operands `cv.mulhhu t4,t2,35'
+.*: Error: illegal operands `cv.mulun t4,t2,67,7'
+.*: Error: illegal operands `cv.mulhhun t4,t2,6,16'
+.*: Error: illegal operands `cv.mulurn t4,t2,787,11'
+.*: Error: illegal operands `cv.mulhhurn t4,t2,3545,9'
+.*: Error: illegal operands `cv.macsn t4,t2,6,24'
+.*: Error: illegal operands `cv.machhsn t4,t2,765,11'
+.*: Error: illegal operands `cv.macsrn t4,t2,45,9'
+.*: Error: illegal operands `cv.machhsrn t4,t2,7,24'
+.*: Error: illegal operands `cv.macun t4,t2,98,27'
+.*: Error: illegal operands `cv.machhun t4,t2,654,18'
+.*: Error: illegal operands `cv.macurn t4,t2,900,25'
+.*: Error: illegal operands `cv.machhurn t4,t2,354,5'
+.*: Error: illegal operands `cv.mulsn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulsrn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulun t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulhhun t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulurn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.macsn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.machhsn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.macsrn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.machhsrn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.macun t4,t2,t0,-1'
+.*: Error: illegal operands `cv.machhun t4,t2,t0,-1'
+.*: Error: illegal operands `cv.macurn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.machhurn t4,t2,t0,-1'
+.*: Error: illegal operands `cv.mulsn t4,t2,t0,-43'
+.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,-531'
+.*: Error: illegal operands `cv.mulsrn t4,t2,t0,-4454'
+.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,-32'
+.*: Error: illegal operands `cv.mulun t4,t2,t0,-23'
+.*: Error: illegal operands `cv.mulhhun t4,t2,t0,-459'
+.*: Error: illegal operands `cv.mulurn t4,t2,t0,-549'
+.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,-32'
+.*: Error: illegal operands `cv.macsn t4,t2,t0,-223'
+.*: Error: illegal operands `cv.machhsn t4,t2,t0,-56'
+.*: Error: illegal operands `cv.macsrn t4,t2,t0,-8'
+.*: Error: illegal operands `cv.machhsrn t4,t2,t0,-2'
+.*: Error: illegal operands `cv.macun t4,t2,t0,-432'
+.*: Error: illegal operands `cv.machhun t4,t2,t0,-1245'
+.*: Error: illegal operands `cv.macurn t4,t2,t0,-45'
+.*: Error: illegal operands `cv.machhurn t4,t2,t0,-354'
+.*: Error: illegal operands `cv.mulsn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulsrn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulun t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulhhun t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulurn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,32'
+.*: Error: illegal operands `cv.macsn t4,t2,t0,32'
+.*: Error: illegal operands `cv.machhsn t4,t2,t0,32'
+.*: Error: illegal operands `cv.macsrn t4,t2,t0,32'
+.*: Error: illegal operands `cv.machhsrn t4,t2,t0,32'
+.*: Error: illegal operands `cv.macun t4,t2,t0,32'
+.*: Error: illegal operands `cv.machhun t4,t2,t0,32'
+.*: Error: illegal operands `cv.macurn t4,t2,t0,32'
+.*: Error: illegal operands `cv.machhurn t4,t2,t0,32'
+.*: Error: illegal operands `cv.mulsn t4,t2,t0,325'
+.*: Error: illegal operands `cv.mulhhsn t4,t2,t0,531'
+.*: Error: illegal operands `cv.mulsrn t4,t2,t0,4454'
+.*: Error: illegal operands `cv.mulhhsrn t4,t2,t0,254'
+.*: Error: illegal operands `cv.mulun t4,t2,t0,76'
+.*: Error: illegal operands `cv.mulhhun t4,t2,t0,459'
+.*: Error: illegal operands `cv.mulurn t4,t2,t0,549'
+.*: Error: illegal operands `cv.mulhhurn t4,t2,t0,5364'
+.*: Error: illegal operands `cv.macsn t4,t2,t0,34435'
+.*: Error: illegal operands `cv.machhsn t4,t2,t0,56'
+.*: Error: illegal operands `cv.macsrn t4,t2,t0,3423'
+.*: Error: illegal operands `cv.machhsrn t4,t2,t0,365'
+.*: Error: illegal operands `cv.macun t4,t2,t0,432'
+.*: Error: illegal operands `cv.machhun t4,t2,t0,1245'
+.*: Error: illegal operands `cv.macurn t4,t2,t0,45'
+.*: Error: instruction cv.mulsn requires absolute expression
+.*: Error: instruction cv.mulhhsn requires absolute expression
+.*: Error: instruction cv.mulsrn requires absolute expression
+.*: Error: instruction cv.mulhhsrn requires absolute expression
+.*: Error: instruction cv.mulun requires absolute expression
+.*: Error: instruction cv.mulhhun requires absolute expression
+.*: Error: instruction cv.mulurn requires absolute expression
+.*: Error: instruction cv.mulhhurn requires absolute expression
+.*: Error: instruction cv.macsn requires absolute expression
+.*: Error: instruction cv.machhsn requires absolute expression
+.*: Error: instruction cv.macsrn requires absolute expression
+.*: Error: instruction cv.machhsrn requires absolute expression
+.*: Error: instruction cv.macun requires absolute expression
+.*: Error: instruction cv.machhun requires absolute expression
+.*: Error: instruction cv.macurn requires absolute expression
+.*: Error: instruction cv.machhurn requires absolute expression
+.*: Error: illegal operands `cv.machhurn t4,t2,t0,354'
diff --git a/gas/testsuite/gas/riscv/cv-mac-fail-operand.s b/gas/testsuite/gas/riscv/cv-mac-fail-operand.s
new file mode 100644
index 00000000000..97a29448ebd
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-fail-operand.s
@@ -0,0 +1,156 @@ 
+# Destination must be of type register
+target:
+	cv.mac 8, t2, t0
+	cv.msu 23, t2, t0
+	cv.muls 43, t2, t0
+	cv.mulhhs 7, t2, t0
+	cv.mulsn 345, t2, t0, 4
+	cv.mulhhsn 356, t2, t0, 16
+	cv.mulsrn 867, t2, t0, 10
+	cv.mulhhsrn 3454, t2, t0, 17
+	cv.mulu 9, t2, t0
+	cv.mulhhu 54, t2, t0
+	cv.mulun 965, t2, t0, 7
+	cv.mulhhun 35, t2, t0, 16
+	cv.mulurn 87, t2, t0, 11
+	cv.mulhhurn 38, t2, t0, 9
+	cv.macsn 985, t2, t0, 24
+	cv.machhsn 83, t2, t0, 11
+	cv.macsrn 960, t2, t0, 9
+	cv.machhsrn 385, t2, t0, 24
+	cv.macun 58, t2, t0, 27
+	cv.machhun 6, t2, t0, 18
+	cv.macurn 35, t2, t0, 25
+	cv.machhurn 67, t2, t0, 5
+
+# Source one must be of type register
+	cv.mac t4, 43, t0
+	cv.msu t4, 3, t0
+	cv.muls t4, 345, t0
+	cv.mulhhs t4, 54, t0
+	cv.mulsn t4, 4, t0, 4
+	cv.mulhhsn t4, 35, t0, 16
+	cv.mulsrn t4, 53, t0, 10
+	cv.mulhhsrn t4, 4456, t0, 17
+	cv.mulu t4, 868, t0
+	cv.mulhhu t4, 95, t0
+	cv.mulun t4, 584, t0, 7
+	cv.mulhhun t4, 37545, t0, 16
+	cv.mulurn t4, 943, t0, 11
+	cv.mulhhurn t4, 34, t0, 9
+	cv.macsn t4, 93, t0, 24
+	cv.machhsn t4, 584, t0, 11
+	cv.macsrn t4, 28, t0, 9
+	cv.machhsrn t4, 9, t0, 24
+	cv.macun t4, 834, t0, 27
+	cv.machhun t4, 92, t0, 18
+	cv.macurn t4, 49, t0, 25
+	cv.machhurn t4, 6, t0, 5
+
+# Source two must be of type register
+	cv.mac t4, t2, 344
+	cv.msu t4, t2, 23
+	cv.muls t4, t2, 2
+	cv.mulhhs t4, t2, 8
+	cv.mulsn t4, t2, 45, 4
+	cv.mulhhsn t4, t2, 655, 16
+	cv.mulsrn t4, t2, 465, 10
+	cv.mulhhsrn t4, t2, 3534, 17
+	cv.mulu t4, t2, 46
+	cv.mulhhu t4, t2, 35
+	cv.mulun t4, t2, 67, 7
+	cv.mulhhun t4, t2, 6, 16
+	cv.mulurn t4, t2, 787, 11
+	cv.mulhhurn t4, t2, 3545, 9
+	cv.macsn t4, t2, 6, 24
+	cv.machhsn t4, t2, 765, 11
+	cv.macsrn t4, t2, 45, 9
+	cv.machhsrn t4, t2, 7, 24
+	cv.macun t4, t2, 98, 27
+	cv.machhun t4, t2, 654, 18
+	cv.macurn t4, t2, 900, 25
+	cv.machhurn t4, t2, 354, 5
+
+# Immediate value must be in range [0, 31]
+	cv.mulsn t4, t2, t0, -1
+	cv.mulhhsn t4, t2, t0, -1
+	cv.mulsrn t4, t2, t0, -1
+	cv.mulhhsrn t4, t2, t0, -1
+	cv.mulun t4, t2, t0, -1
+	cv.mulhhun t4, t2, t0, -1
+	cv.mulurn t4, t2, t0, -1
+	cv.mulhhurn t4, t2, t0, -1
+	cv.macsn t4, t2, t0, -1
+	cv.machhsn t4, t2, t0, -1
+	cv.macsrn t4, t2, t0, -1
+	cv.machhsrn t4, t2, t0, -1
+	cv.macun t4, t2, t0, -1
+	cv.machhun t4, t2, t0, -1
+	cv.macurn t4, t2, t0, -1
+	cv.machhurn t4, t2, t0, -1
+	cv.mulsn t4, t2, t0, -43
+	cv.mulhhsn t4, t2, t0, -531
+	cv.mulsrn t4, t2, t0, -4454
+	cv.mulhhsrn t4, t2, t0, -32
+	cv.mulun t4, t2, t0, -23
+	cv.mulhhun t4, t2, t0, -459
+	cv.mulurn t4, t2, t0, -549
+	cv.mulhhurn t4, t2, t0, -32
+	cv.macsn t4, t2, t0, -223
+	cv.machhsn t4, t2, t0, -56
+	cv.macsrn t4, t2, t0, -8
+	cv.machhsrn t4, t2, t0, -2
+	cv.macun t4, t2, t0, -432
+	cv.machhun t4, t2, t0, -1245
+	cv.macurn t4, t2, t0, -45
+	cv.machhurn t4, t2, t0, -354
+	cv.mulsn t4, t2, t0, 32
+	cv.mulhhsn t4, t2, t0, 32
+	cv.mulsrn t4, t2, t0, 32
+	cv.mulhhsrn t4, t2, t0, 32
+	cv.mulun t4, t2, t0, 32
+	cv.mulhhun t4, t2, t0, 32
+	cv.mulurn t4, t2, t0, 32
+	cv.mulhhurn t4, t2, t0, 32
+	cv.macsn t4, t2, t0, 32
+	cv.machhsn t4, t2, t0, 32
+	cv.macsrn t4, t2, t0, 32
+	cv.machhsrn t4, t2, t0, 32
+	cv.macun t4, t2, t0, 32
+	cv.machhun t4, t2, t0, 32
+	cv.macurn t4, t2, t0, 32
+	cv.machhurn t4, t2, t0, 32
+	cv.mulsn t4, t2, t0, 325
+	cv.mulhhsn t4, t2, t0, 531
+	cv.mulsrn t4, t2, t0, 4454
+	cv.mulhhsrn t4, t2, t0, 254
+	cv.mulun t4, t2, t0, 76
+	cv.mulhhun t4, t2, t0, 459
+	cv.mulurn t4, t2, t0, 549
+	cv.mulhhurn t4, t2, t0, 5364
+	cv.macsn t4, t2, t0, 34435
+	cv.machhsn t4, t2, t0, 56
+	cv.macsrn t4, t2, t0, 3423
+	cv.machhsrn t4, t2, t0, 365
+	cv.macun t4, t2, t0, 432
+	cv.machhun t4, t2, t0, 1245
+	cv.macurn t4, t2, t0, 45
+
+# Immediate value must be an absolute expression
+	cv.mulsn t4, t2, t0, t3
+	cv.mulhhsn t4, t2, t0, t1
+	cv.mulsrn t4, t2, t0, t6
+	cv.mulhhsrn t4, t2, t0, t3
+	cv.mulun t4, t2, t0, t1
+	cv.mulhhun t4, t2, t0, t3
+	cv.mulurn t4, t2, t0, t5
+	cv.mulhhurn t4, t2, t0, t1
+	cv.macsn t4, t2, t0, t3
+	cv.machhsn t4, t2, t0, t5
+	cv.macsrn t4, t2, t0, t1
+	cv.machhsrn t4, t2, t0, t6
+	cv.macun t4, t2, t0, t1
+	cv.machhun t4, t2, t0, t3
+	cv.macurn t4, t2, t0, t6
+	cv.machhurn t4, t2, t0, t5
+	cv.machhurn t4, t2, t0, 354
diff --git a/gas/testsuite/gas/riscv/cv-mac-insns.d b/gas/testsuite/gas/riscv/cv-mac-insns.d
new file mode 100644
index 00000000000..9a961051a97
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-insns.d
@@ -0,0 +1,87 @@ 
+#as: -march=rv32i_xcvmac
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+0:[ 	]+907332ab[ 	]+cv.mac[ 	]+t0,t1,t2
+[ 	]+4:[ 	]+9053beab[ 	]+cv.mac[ 	]+t4,t2,t0
+[ 	]+8:[ 	]+906f3e2b[ 	]+cv.mac[ 	]+t3,t5,t1
+[ 	]+c:[ 	]+407362db[ 	]+cv.machhsn[ 	]+t0,t1,t2,0
+[ 	]+10:[ 	]+5653eedb[ 	]+cv.machhsn[ 	]+t4,t2,t0,11
+[ 	]+14:[ 	]+7e6f6e5b[ 	]+cv.machhsn[ 	]+t3,t5,t1,31
+[ 	]+18:[ 	]+c07362db[ 	]+cv.machhsrn[ 	]+t0,t1,t2,0
+[ 	]+1c:[ 	]+f053eedb[ 	]+cv.machhsrn[ 	]+t4,t2,t0,24
+[ 	]+20:[ 	]+fe6f6e5b[ 	]+cv.machhsrn[ 	]+t3,t5,t1,31
+[ 	]+24:[ 	]+407372db[ 	]+cv.machhun[ 	]+t0,t1,t2,0
+[ 	]+28:[ 	]+6453fedb[ 	]+cv.machhun[ 	]+t4,t2,t0,18
+[ 	]+2c:[ 	]+7e6f7e5b[ 	]+cv.machhun[ 	]+t3,t5,t1,31
+[ 	]+30:[ 	]+c07372db[ 	]+cv.machhurn[ 	]+t0,t1,t2,0
+[ 	]+34:[ 	]+ca53fedb[ 	]+cv.machhurn[ 	]+t4,t2,t0,5
+[ 	]+38:[ 	]+fe6f7e5b[ 	]+cv.machhurn[ 	]+t3,t5,t1,31
+[ 	]+3c:[ 	]+007362db[ 	]+cv.macsn[ 	]+t0,t1,t2,0
+[ 	]+40:[ 	]+3053eedb[ 	]+cv.macsn[ 	]+t4,t2,t0,24
+[ 	]+44:[ 	]+3e6f6e5b[ 	]+cv.macsn[ 	]+t3,t5,t1,31
+[ 	]+48:[ 	]+807362db[ 	]+cv.macsrn[ 	]+t0,t1,t2,0
+[ 	]+4c:[ 	]+9253eedb[ 	]+cv.macsrn[ 	]+t4,t2,t0,9
+[ 	]+50:[ 	]+be6f6e5b[ 	]+cv.macsrn[ 	]+t3,t5,t1,31
+[ 	]+54:[ 	]+007372db[ 	]+cv.macun[ 	]+t0,t1,t2,0
+[ 	]+58:[ 	]+3653fedb[ 	]+cv.macun[ 	]+t4,t2,t0,27
+[ 	]+5c:[ 	]+3e6f7e5b[ 	]+cv.macun[ 	]+t3,t5,t1,31
+[ 	]+60:[ 	]+807372db[ 	]+cv.macurn[ 	]+t0,t1,t2,0
+[ 	]+64:[ 	]+b253fedb[ 	]+cv.macurn[ 	]+t4,t2,t0,25
+[ 	]+68:[ 	]+be6f7e5b[ 	]+cv.macurn[ 	]+t3,t5,t1,31
+[ 	]+6c:[ 	]+927332ab[ 	]+cv.msu[ 	]+t0,t1,t2
+[ 	]+70:[ 	]+9253beab[ 	]+cv.msu[ 	]+t4,t2,t0
+[ 	]+74:[ 	]+926f3e2b[ 	]+cv.msu[ 	]+t3,t5,t1
+[ 	]+78:[ 	]+407342db[ 	]+cv.mulhhsn[ 	]+t0,t1,t2,0
+[ 	]+7c:[ 	]+4053cedb[ 	]+cv.mulhhsn[ 	]+t4,t2,t0,0
+[ 	]+80:[ 	]+406f4e5b[ 	]+cv.mulhhsn[ 	]+t3,t5,t1,0
+[ 	]+84:[ 	]+407342db[ 	]+cv.mulhhsn[ 	]+t0,t1,t2,0
+[ 	]+88:[ 	]+6053cedb[ 	]+cv.mulhhsn[ 	]+t4,t2,t0,16
+[ 	]+8c:[ 	]+7e6f4e5b[ 	]+cv.mulhhsn[ 	]+t3,t5,t1,31
+[ 	]+90:[ 	]+c07342db[ 	]+cv.mulhhsrn[ 	]+t0,t1,t2,0
+[ 	]+94:[ 	]+e253cedb[ 	]+cv.mulhhsrn[ 	]+t4,t2,t0,17
+[ 	]+98:[ 	]+fe6f4e5b[ 	]+cv.mulhhsrn[ 	]+t3,t5,t1,31
+[ 	]+9c:[ 	]+407352db[ 	]+cv.mulhhun[ 	]+t0,t1,t2,0
+[ 	]+a0:[ 	]+4053dedb[ 	]+cv.mulhhun[ 	]+t4,t2,t0,0
+[ 	]+a4:[ 	]+406f5e5b[ 	]+cv.mulhhun[ 	]+t3,t5,t1,0
+[ 	]+a8:[ 	]+407352db[ 	]+cv.mulhhun[ 	]+t0,t1,t2,0
+[ 	]+ac:[ 	]+6053dedb[ 	]+cv.mulhhun[ 	]+t4,t2,t0,16
+[ 	]+b0:[ 	]+7e6f5e5b[ 	]+cv.mulhhun[ 	]+t3,t5,t1,31
+[ 	]+b4:[ 	]+c07352db[ 	]+cv.mulhhurn[ 	]+t0,t1,t2,0
+[ 	]+b8:[ 	]+d253dedb[ 	]+cv.mulhhurn[ 	]+t4,t2,t0,9
+[ 	]+bc:[ 	]+fe6f5e5b[ 	]+cv.mulhhurn[ 	]+t3,t5,t1,31
+[ 	]+c0:[ 	]+007342db[ 	]+cv.mulsn[ 	]+t0,t1,t2,0
+[ 	]+c4:[ 	]+0053cedb[ 	]+cv.mulsn[ 	]+t4,t2,t0,0
+[ 	]+c8:[ 	]+006f4e5b[ 	]+cv.mulsn[ 	]+t3,t5,t1,0
+[ 	]+cc:[ 	]+007342db[ 	]+cv.mulsn[ 	]+t0,t1,t2,0
+[ 	]+d0:[ 	]+0853cedb[ 	]+cv.mulsn[ 	]+t4,t2,t0,4
+[ 	]+d4:[ 	]+3e6f4e5b[ 	]+cv.mulsn[ 	]+t3,t5,t1,31
+[ 	]+d8:[ 	]+807342db[ 	]+cv.mulsrn[ 	]+t0,t1,t2,0
+[ 	]+dc:[ 	]+9453cedb[ 	]+cv.mulsrn[ 	]+t4,t2,t0,10
+[ 	]+e0:[ 	]+be6f4e5b[ 	]+cv.mulsrn[ 	]+t3,t5,t1,31
+[ 	]+e4:[ 	]+007352db[ 	]+cv.mulun[ 	]+t0,t1,t2,0
+[ 	]+e8:[ 	]+0053dedb[ 	]+cv.mulun[ 	]+t4,t2,t0,0
+[ 	]+ec:[ 	]+006f5e5b[ 	]+cv.mulun[ 	]+t3,t5,t1,0
+[ 	]+f0:[ 	]+007352db[ 	]+cv.mulun[ 	]+t0,t1,t2,0
+[ 	]+f4:[ 	]+0e53dedb[ 	]+cv.mulun[ 	]+t4,t2,t0,7
+[ 	]+f8:[ 	]+3e6f5e5b[ 	]+cv.mulun[ 	]+t3,t5,t1,31
+[ 	]+fc:[ 	]+807352db[ 	]+cv.mulurn[ 	]+t0,t1,t2,0
+[ 	]+100:[ 	]+9653dedb[ 	]+cv.mulurn[ 	]+t4,t2,t0,11
+[ 	]+104:[ 	]+be6f5e5b[ 	]+cv.mulurn[ 	]+t3,t5,t1,31
+[ 	]+108:[ 	]+407342db[ 	]+cv.mulhhsn[ 	]+t0,t1,t2,0
+[ 	]+10c:[ 	]+4053cedb[ 	]+cv.mulhhsn[ 	]+t4,t2,t0,0
+[ 	]+110:[ 	]+406f4e5b[ 	]+cv.mulhhsn[ 	]+t3,t5,t1,0
+[ 	]+114:[ 	]+407352db[ 	]+cv.mulhhun[ 	]+t0,t1,t2,0
+[ 	]+118:[ 	]+4053dedb[ 	]+cv.mulhhun[ 	]+t4,t2,t0,0
+[ 	]+11c:[ 	]+406f5e5b[ 	]+cv.mulhhun[ 	]+t3,t5,t1,0
+[ 	]+120:[ 	]+007342db[ 	]+cv.mulsn[ 	]+t0,t1,t2,0
+[ 	]+124:[ 	]+0053cedb[ 	]+cv.mulsn[ 	]+t4,t2,t0,0
+[ 	]+128:[ 	]+006f4e5b[ 	]+cv.mulsn[ 	]+t3,t5,t1,0
+[ 	]+12c:[ 	]+007352db[ 	]+cv.mulun[ 	]+t0,t1,t2,0
+[ 	]+130:[ 	]+0053dedb[ 	]+cv.mulun[ 	]+t4,t2,t0,0
+[ 	]+134:[ 	]+006f5e5b[ 	]+cv.mulun[ 	]+t3,t5,t1,0
diff --git a/gas/testsuite/gas/riscv/cv-mac-insns.s b/gas/testsuite/gas/riscv/cv-mac-insns.s
new file mode 100644
index 00000000000..a699a3ba461
--- /dev/null
+++ b/gas/testsuite/gas/riscv/cv-mac-insns.s
@@ -0,0 +1,81 @@ 
+target:
+	cv.mac t0, t1, t2
+	cv.mac t4, t2, t0
+	cv.mac t3, t5, t1
+	cv.machhsn t0, t1, t2, 0
+	cv.machhsn t4, t2, t0, 11
+	cv.machhsn t3, t5, t1, 31
+	cv.machhsrn t0, t1, t2, 0
+	cv.machhsrn t4, t2, t0, 24
+	cv.machhsrn t3, t5, t1, 31
+	cv.machhun t0, t1, t2, 0
+	cv.machhun t4, t2, t0, 18
+	cv.machhun t3, t5, t1, 31
+	cv.machhurn t0, t1, t2, 0
+	cv.machhurn t4, t2, t0, 5
+	cv.machhurn t3, t5, t1, 31
+	cv.macsn t0, t1, t2, 0
+	cv.macsn t4, t2, t0, 24
+	cv.macsn t3, t5, t1, 31
+	cv.macsrn t0, t1, t2, 0
+	cv.macsrn t4, t2, t0, 9
+	cv.macsrn t3, t5, t1, 31
+	cv.macun t0, t1, t2, 0
+	cv.macun t4, t2, t0, 27
+	cv.macun t3, t5, t1, 31
+	cv.macurn t0, t1, t2, 0
+	cv.macurn t4, t2, t0, 25
+	cv.macurn t3, t5, t1, 31
+	cv.msu t0, t1, t2
+	cv.msu t4, t2, t0
+	cv.msu t3, t5, t1
+	cv.mulhhs t0, t1, t2
+	cv.mulhhs t4, t2, t0
+	cv.mulhhs t3, t5, t1
+	cv.mulhhsn t0, t1, t2, 0
+	cv.mulhhsn t4, t2, t0, 16
+	cv.mulhhsn t3, t5, t1, 31
+	cv.mulhhsrn t0, t1, t2, 0
+	cv.mulhhsrn t4, t2, t0, 17
+	cv.mulhhsrn t3, t5, t1, 31
+	cv.mulhhu t0, t1, t2
+	cv.mulhhu t4, t2, t0
+	cv.mulhhu t3, t5, t1
+	cv.mulhhun t0, t1, t2, 0
+	cv.mulhhun t4, t2, t0, 16
+	cv.mulhhun t3, t5, t1, 31
+	cv.mulhhurn t0, t1, t2, 0
+	cv.mulhhurn t4, t2, t0, 9
+	cv.mulhhurn t3, t5, t1, 31
+	cv.muls t0, t1, t2
+	cv.muls t4, t2, t0
+	cv.muls t3, t5, t1
+	cv.mulsn t0, t1, t2, 0
+	cv.mulsn t4, t2, t0, 4
+	cv.mulsn t3, t5, t1, 31
+	cv.mulsrn t0, t1, t2, 0
+	cv.mulsrn t4, t2, t0, 10
+	cv.mulsrn t3, t5, t1, 31
+	cv.mulu t0, t1, t2
+	cv.mulu t4, t2, t0
+	cv.mulu t3, t5, t1
+	cv.mulun t0, t1, t2, 0
+	cv.mulun t4, t2, t0, 7
+	cv.mulun t3, t5, t1, 31
+	cv.mulurn t0, t1, t2, 0
+	cv.mulurn t4, t2, t0, 11
+	cv.mulurn t3, t5, t1, 31
+
+  # Pseudo-instructions
+	cv.mulhhsn t0, t1, t2, 0
+	cv.mulhhsn t4, t2, t0, 0
+	cv.mulhhsn t3, t5, t1, 0
+	cv.mulhhun t0, t1, t2, 0
+	cv.mulhhun t4, t2, t0, 0
+	cv.mulhhun t3, t5, t1, 0
+	cv.mulsn t0, t1, t2, 0
+	cv.mulsn t4, t2, t0, 0
+	cv.mulsn t3, t5, t1, 0
+	cv.mulun t0, t1, t2, 0
+	cv.mulun t4, t2, t0, 0
+	cv.mulun t3, t5, t1, 0
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 26d2c04bf24..199ae63585f 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2320,6 +2320,27 @@ 
 #define MASK_WRS_NTO 0xffffffff
 #define MATCH_WRS_STO 0x01d00073
 #define MASK_WRS_STO 0xffffffff
+/* Vendor-specific (CORE-V) Xcvmac instructions.  */
+#define MATCH_CV_MAC       0x9000302b
+#define MATCH_CV_MSU       0x9200302b
+#define MASK_CV_MACMSU     0xfe00707f
+#define MATCH_CV_MULSN     0x405b
+#define MATCH_CV_MULHHSN   0x4000405b
+#define MATCH_CV_MULSRN    0x8000405b
+#define MATCH_CV_MULHHSRN  0xc000405b
+#define MATCH_CV_MULUN     0x505b
+#define MATCH_CV_MULHHUN   0x4000505b
+#define MATCH_CV_MULURN    0x8000505b
+#define MATCH_CV_MULHHURN  0xc000505b
+#define MATCH_CV_MACSN     0x605b
+#define MATCH_CV_MACHHSN   0x4000605b
+#define MATCH_CV_MACSRN    0x8000605b
+#define MATCH_CV_MACHHSRN  0xc000605b
+#define MATCH_CV_MACUN     0x705b
+#define MATCH_CV_MACHHUN   0x4000705b
+#define MATCH_CV_MACURN    0x8000705b
+#define MATCH_CV_MACHHURN  0xc000705b
+#define MASK_CV_MULMACN    0xc000707f
 /* Vendor-specific (T-Head) XTheadBa instructions.  */
 #define MATCH_TH_ADDSL 0x0000100b
 #define MASK_TH_ADDSL 0xf800707f
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 38927bd0c74..5097d2cf6c1 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -112,6 +112,9 @@  static inline unsigned int riscv_insn_length (insn_t insn)
   (RV_X(x, 6, 1) | (RV_X(x, 5, 1) << 1))
 #define EXTRACT_ZCB_HALFWORD_UIMM(x) \
   (RV_X(x, 5, 1) << 1)
+/* Vendor-specific (CORE-V) extract macros.  */
+#define EXTRACT_CV_IS3_UIMM5(x) \
+  (RV_X(x, 25, 5))
 
 #define ENCODE_ITYPE_IMM(x) \
   (RV_X(x, 0, 12) << 20)
@@ -163,6 +166,9 @@  static inline unsigned int riscv_insn_length (insn_t insn)
   ((RV_X(x, 0, 1) << 6) | (RV_X(x, 1, 1) << 5))
 #define ENCODE_ZCB_HALFWORD_UIMM(x) \
   (RV_X(x, 1, 1) << 5)
+/* Vendor-specific (CORE-V) encode macros.  */
+#define ENCODE_CV_IS3_UIMM5(x) \
+  (RV_X(x, 0, 5) << 25)
 
 #define VALID_ITYPE_IMM(x) (EXTRACT_ITYPE_IMM(ENCODE_ITYPE_IMM(x)) == (x))
 #define VALID_STYPE_IMM(x) (EXTRACT_STYPE_IMM(ENCODE_STYPE_IMM(x)) == (x))
@@ -443,6 +449,7 @@  enum riscv_insn_class
   INSN_CLASS_ZICBOP,
   INSN_CLASS_ZICBOZ,
   INSN_CLASS_H,
+  INSN_CLASS_XCVMAC,
   INSN_CLASS_XTHEADBA,
   INSN_CLASS_XTHEADBB,
   INSN_CLASS_XTHEADBS,
diff --git a/opcodes/riscv-dis.c b/opcodes/riscv-dis.c
index 90f0fea1692..b16db5113b1 100644
--- a/opcodes/riscv-dis.c
+++ b/opcodes/riscv-dis.c
@@ -429,6 +429,22 @@  print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
 	    print (info->stream, dis_style_immediate, "0");
 	  break;
 
+	case 'x': /* Vendor-specific operands.  */
+	  switch (*++oparg)
+	    {
+	      /* Vendor-specific (CORE-V) operands.  */
+	      case 'c':
+		switch (*++oparg)
+		  {
+		    case '3':
+		      print (info->stream, dis_style_immediate, "%d",
+			     ((int) EXTRACT_CV_IS3_UIMM5 (l)));
+		      break;
+		  }
+		break;
+	    }
+	  break;
+
 	case 's':
 	  if ((l & MASK_JALR) == MATCH_JALR)
 	    maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0);
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 39da5f84e74..1b2023b96bd 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -154,6 +154,8 @@  const float riscv_fli_numval[32] =
 #define MASK_VS1 (OP_MASK_VS1 << OP_SH_VS1)
 #define MASK_VS2 (OP_MASK_VS2 << OP_SH_VS2)
 #define MASK_VMASK (OP_MASK_VMASK << OP_SH_VMASK)
+/* Vendor-specific (CORE-V) masks.  */
+#define MASK_CV_IS3_UIMM5 ENCODE_CV_IS3_UIMM5 (-1U)
 
 static int
 match_opcode (const struct riscv_opcode *op, insn_t insn)
@@ -2039,6 +2041,30 @@  const struct riscv_opcode riscv_opcodes[] =
 {"hsv.w",       0, INSN_CLASS_H, "t,0(s)", MATCH_HSV_W, MASK_HSV_W, match_opcode, INSN_DREF|INSN_4_BYTE },
 {"hsv.d",      64, INSN_CLASS_H, "t,0(s)", MATCH_HSV_D, MASK_HSV_D, match_opcode, INSN_DREF|INSN_8_BYTE },
 
+/* Vendor-specific (CORE-V) Xcvmac instructions.  */
+{"cv.mac",      0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MAC,	     MASK_CV_MACMSU, match_opcode, 0},
+{"cv.msu",      0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MSU,	     MASK_CV_MACMSU, match_opcode, 0},
+{"cv.mulsn",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULSN,    MASK_CV_MULMACN, match_opcode, 0},
+{"cv.muls",     0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULSN,    MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
+{"cv.mulsrn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULSRN,   MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulhhsn",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHSN,  MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulhhs",   0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULHHSN,  MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
+{"cv.mulhhsrn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHSRN, MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulun",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULUN,    MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulu",     0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULUN,    MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
+{"cv.mulurn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULURN,   MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulhhun",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHUN,  MASK_CV_MULMACN, match_opcode, 0},
+{"cv.mulhhu",   0, INSN_CLASS_XCVMAC, "d,s,t",    MATCH_CV_MULHHUN,  MASK_CV_MULMACN|MASK_CV_IS3_UIMM5, match_opcode, INSN_ALIAS},
+{"cv.mulhhurn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MULHHURN, MASK_CV_MULMACN, match_opcode, 0},
+{"cv.macsn",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACSN,    MASK_CV_MULMACN, match_opcode, 0},
+{"cv.machhsn",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHSN,  MASK_CV_MULMACN, match_opcode, 0},
+{"cv.macsrn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACSRN,   MASK_CV_MULMACN, match_opcode, 0},
+{"cv.machhsrn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHSRN, MASK_CV_MULMACN, match_opcode, 0},
+{"cv.macun",    0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACUN,    MASK_CV_MULMACN, match_opcode, 0},
+{"cv.machhun",  0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHUN,  MASK_CV_MULMACN, match_opcode, 0},
+{"cv.macurn",   0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACURN,   MASK_CV_MULMACN, match_opcode, 0},
+{"cv.machhurn", 0, INSN_CLASS_XCVMAC, "d,s,t,xc3", MATCH_CV_MACHHURN, MASK_CV_MULMACN, match_opcode, 0},
+
 /* Vendor-specific (T-Head) XTheadBa instructions.  */
 {"th.addsl",    0, INSN_CLASS_XTHEADBA,    "d,s,t,Xu2@25",   MATCH_TH_ADDSL,    MASK_TH_ADDSL,    match_opcode, 0},