RISC-V: Add Zvdota extension classes

Zvfqwdota8f: dot product of 8-bit floating-point numbers with 32-bit accumulation.

Zvdota also uses the vtype alternative format bit, altfmt, which is bit 8 of the vtype CSR. This patch adds symbolic e8alt and e16alt vsew constants for vsetvli/vsetivli so that assembly code can select the alternative element formats required by these dot-product instructions.

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

bfd/ChangeLog:

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

gas/ChangeLog:

	* NEWS: Add zvqwdota8i, zvqwdota16i, zvfwdota16bf and
	zvfqwdota8f extensions.
	* config/tc-riscv.c (riscv_vsew_altfmt): New vsew altfmt
	constants array for e8alt and e16alt.
	(riscv_vtype_altfmt_supported): New function.
	(my_getVsetvliExpression): Ditto.
	* testsuite/gas/riscv/march-help.l: New test.
	* testsuite/gas/riscv/vector-vtype-altfmt.d: Ditto.
	* testsuite/gas/riscv/vector-vtype-altfmt.s: Ditto.
	* testsuite/gas/riscv/zvdota.d: Ditto.
	* testsuite/gas/riscv/zvdota.s: Ditto.

include/ChangeLog:

	* opcode/riscv-opc.h (MATCH_VQWDOTAU_VV, MASK_VQWDOTAU_VV): New encoding.
	(MATCH_VQWDOTAS_VV, MASK_VQWDOTAS_VV): Ditto.
	(MATCH_VFWDOTA_VV, MASK_VFWDOTA_VV): Ditto.
	(MATCH_VFQWDOTA_VV, MASK_VFQWDOTA_VV): Ditto.
	(MATCH_VFQWDOTA_ALT_VV, MASK_VFQWDOTA_ALT_VV): Ditto.
	(DECLARE_INSN): New declarations.
	* opcode/riscv.h (OP_MASK_VTYPE_ALTFMT, OP_SH_VTYPE_ALTFMT): New vtype altfmt.
	(enum riscv_insn_class): New extension classes.

opcodes/ChangeLog:

	* riscv-dis.c (print_insn_args): Add altfmt support.
	* riscv-opc.c (riscv_opcodes): New instructions.
This commit is contained in:
Jiawei 2026-06-30 07:54:21 -06:00 committed by Jeff Law
parent 4f54c79267
commit 89d59bf712
12 changed files with 162 additions and 6 deletions

View file

@ -1239,6 +1239,10 @@ static const struct riscv_implicit_subset riscv_implicit_subsets[] =
{"zvfhmin", "+zve32f", check_implicit_always},
{"zvfbfwma", "+zve32f,+zfbfmin", check_implicit_always},
{"zvfbfmin", "+zve32f", check_implicit_always},
{"zvfqwdota8f", "+zve32f", check_implicit_always},
{"zvfwdota16bf", "+zve32f", check_implicit_always},
{"zvqwdota8i", "+zve32x", check_implicit_always},
{"zvqwdota16i", "+zve64x", check_implicit_always},
{"zve64d", "+d,+zve64f", check_implicit_always},
{"zve64f", "+zve32f,+zve64x,+zvl64b", check_implicit_always},
{"zve32f", "+f,+zve32x,+zvl32b", check_implicit_always},
@ -1524,6 +1528,8 @@ static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zvfbfwma", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvfqwdota8f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvfwdota16bf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvkg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@ -1538,6 +1544,8 @@ static const struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zvksg", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvksc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvqwdota8i", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvqwdota16i", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@ -2985,6 +2993,10 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zvfbfmin");
case INSN_CLASS_ZVFBFWMA:
return riscv_subset_supports (rps, "zvfbfwma");
case INSN_CLASS_ZVFQWDOTA8F:
return riscv_subset_supports (rps, "zvfqwdota8f");
case INSN_CLASS_ZVFWDOTA16BF:
return riscv_subset_supports (rps, "zvfwdota16bf");
case INSN_CLASS_ZVKB:
return riscv_subset_supports (rps, "zvkb");
case INSN_CLASS_ZVKG:
@ -2998,6 +3010,13 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zvksed");
case INSN_CLASS_ZVKSH:
return riscv_subset_supports (rps, "zvksh");
case INSN_CLASS_ZVQWDOTA8I:
return riscv_subset_supports (rps, "zvqwdota8i");
case INSN_CLASS_ZVQWDOTA16I:
return riscv_subset_supports (rps, "zvqwdota16i");
case INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I:
return (riscv_subset_supports (rps, "zvqwdota8i")
|| riscv_subset_supports (rps, "zvqwdota16i"));
case INSN_CLASS_ZCB:
return riscv_subset_supports (rps, "zcb");
case INSN_CLASS_ZCB_AND_ZBB:
@ -3312,6 +3331,10 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "zvfbfmin";
case INSN_CLASS_ZVFBFWMA:
return "zvfbfwma";
case INSN_CLASS_ZVFQWDOTA8F:
return "zvfqwdota8f";
case INSN_CLASS_ZVFWDOTA16BF:
return "zvfwdota16bf";
case INSN_CLASS_ZVKB:
return _("zvkb");
case INSN_CLASS_ZVKG:
@ -3324,6 +3347,12 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return _("zvksed");
case INSN_CLASS_ZVKSH:
return _("zvksh");
case INSN_CLASS_ZVQWDOTA8I:
return "zvqwdota8i";
case INSN_CLASS_ZVQWDOTA16I:
return "zvqwdota16i";
case INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I:
return _("zvqwdota8i' or `zvqwdota16i");
case INSN_CLASS_ZCB:
return "zcb";
case INSN_CLASS_ZCB_AND_ZBA:

View file

@ -6,7 +6,8 @@
and will be removed in a future release.
* Add support for RISC-V standard extensions:
zalasr v1.0, svrsw60t59b v1.0, zvabd v1.0, smpmpmt v1.0.
zalasr v1.0, svrsw60t59b v1.0, zvabd v1.0, smpmpmt v1.0,
zvqwdota8i, zvqwdota16i, zvfwdota16bf and zvfqwdota8f v1.0.
* Add support for RISC-V vendor extensions:
SpacemiT: xsmtvdot v1.0, xsmtvdotii v1.0.

View file

@ -2692,15 +2692,40 @@ my_getOpcodeExpression (expressionS *ep, bfd_reloc_code_real_type *reloc,
On exit, EXPR_PARSE_END points to the first character after the
expression. */
static bool
riscv_vtype_altfmt_supported (void)
{
return (riscv_subset_supports (&riscv_rps_as, "zvfbfa")
|| riscv_subset_supports (&riscv_rps_as, "zvfofp8min")
|| riscv_subset_supports (&riscv_rps_as, "zvfqwdota8f")
|| riscv_subset_supports (&riscv_rps_as, "zvfwdota16bf")
|| riscv_subset_supports (&riscv_rps_as, "zvqwdota8i")
|| riscv_subset_supports (&riscv_rps_as, "zvqwdota16i"));
}
static void
my_getVsetvliExpression (expressionS *ep, char *str)
{
unsigned int vsew_value = 0, vlmul_value = 0;
unsigned int vta_value = 0, vma_value = 0;
unsigned int vta_value = 0, vma_value = 0, altfmt_value = 0;
bool vsew_found = false, vlmul_found = false;
bool vta_found = false, vma_found = false;
if (arg_lookup (&str, riscv_vsew, ARRAY_SIZE (riscv_vsew), &vsew_value))
if (arg_lookup (&str, riscv_vsew_altfmt,
ARRAY_SIZE (riscv_vsew_altfmt), &vsew_value))
{
if (*str == ',')
++str;
if (vsew_found)
as_bad (_("multiple vsew constants"));
if (!riscv_vtype_altfmt_supported ())
as_bad (_("symbolic vtype altfmt requires `zvfbfa', "
"`zvfofp8min' or a `zvdota' extension"));
altfmt_value = 1 << OP_SH_VTYPE_ALTFMT;
vsew_found = true;
}
if (!vsew_found
&& arg_lookup (&str, riscv_vsew, ARRAY_SIZE (riscv_vsew), &vsew_value))
{
if (*str == ',')
++str;
@ -2739,7 +2764,8 @@ my_getVsetvliExpression (expressionS *ep, char *str)
ep->X_add_number = (vlmul_value << OP_SH_VLMUL)
| (vsew_value << OP_SH_VSEW)
| (vta_value << OP_SH_VTA)
| (vma_value << OP_SH_VMA);
| (vma_value << OP_SH_VMA)
| altfmt_value;
expr_parse_end = str;
}
else

View file

@ -76,6 +76,8 @@ All available -march extensions for RISC-V:
zvfbfwma 1.0
zvfh 1.0
zvfhmin 1.0
zvfqwdota8f 1.0
zvfwdota16bf 1.0
zvkb 1.0
zvkg 1.0
zvkn 1.0
@ -90,6 +92,8 @@ All available -march extensions for RISC-V:
zvksg 1.0
zvksc 1.0
zvkt 1.0
zvqwdota8i 1.0
zvqwdota16i 1.0
zvl32b 1.0
zvl64b 1.0
zvl128b 1.0

View file

@ -0,0 +1,15 @@
#as: -march=rv64gc_zvfqwdota8f
#objdump: -dr
.*:[ ]+file format .*
Disassembly of section .text:
0+000 <target>:
[ ]+[0-9a-f]+:[ ]+10707057[ ]+vsetvli[ ]+zero,zero,e8alt,mf2,tu,mu
[ ]+[0-9a-f]+:[ ]+10707057[ ]+vsetvli[ ]+zero,zero,e8alt,mf2,tu,mu
[ ]+[0-9a-f]+:[ ]+10707057[ ]+vsetvli[ ]+zero,zero,e8alt,mf2,tu,mu
[ ]+[0-9a-f]+:[ ]+10f07057[ ]+vsetvli[ ]+zero,zero,e16alt,mf2,tu,mu
[ ]+[0-9a-f]+:[ ]+10f07057[ ]+vsetvli[ ]+zero,zero,e16alt,mf2,tu,mu
[ ]+[0-9a-f]+:[ ]+10f07057[ ]+vsetvli[ ]+zero,zero,e16alt,mf2,tu,mu

View file

@ -0,0 +1,7 @@
target:
vsetvli zero, zero, e8alt, mf2, tu, mu
vsetvli zero, zero, e8alt, mf2, tu, mu
vsetvli zero, zero, e8alt, mf2, tu, mu
vsetvli zero, zero, e16alt, mf2, tu, mu
vsetvli zero, zero, e16alt, mf2, tu, mu
vsetvli zero, zero, e16alt, mf2, tu, mu

View file

@ -0,0 +1,19 @@
#as: -march=rv64gc_zvqwdota8i_zvqwdota16i_zvfwdota16bf_zvfqwdota8f
#objdump: -dr
.*:[ ]+file format .*
Disassembly of section .text:
0+000 <target>:
[ ]+[0-9a-f]+:[ ]+9a8f8877[ ]+vqwdotau.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+9e8f8877[ ]+vqwdotas.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+928f9877[ ]+vfwdota.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+9a8f9877[ ]+vfqwdota.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+9e8f9877[ ]+vfqwdota.alt.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+988f8877[ ]+vqwdotau.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+9c8f8877[ ]+vqwdotas.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+928f9877[ ]+vfwdota.vv[ ]+v16,v8,v31
[ ]+[0-9a-f]+:[ ]+980f9877[ ]+vfqwdota.vv[ ]+v16,v0,v31,v0.t
[ ]+[0-9a-f]+:[ ]+9c0f9877[ ]+vfqwdota.alt.vv[ ]+v16,v0,v31,v0.t

View file

@ -0,0 +1,11 @@
target:
vqwdotau.vv v16, v8, v31
vqwdotas.vv v16, v8, v31
vfwdota.vv v16, v8, v31
vfqwdota.vv v16, v8, v31
vfqwdota.alt.vv v16, v8, v31
vqwdotau.vv v16, v8, v31, v0.t
vqwdotas.vv v16, v8, v31, v0.t
vfwdota.vv v16, v8, v31, v0.t
vfqwdota.vv v16, v0, v31, v0.t
vfqwdota.alt.vv v16, v0, v31, v0.t

View file

@ -2577,6 +2577,17 @@
#define MASK_VFWMACCBF16_VF 0xfc00707f
#define MATCH_VFWMACCBF16_VV 0xec001057
#define MASK_VFWMACCBF16_VV 0xfc00707f
/* Zvdota instructions. */
#define MATCH_VQWDOTAU_VV 0x98000077
#define MASK_VQWDOTAU_VV 0xfc00707f
#define MATCH_VQWDOTAS_VV 0x9c000077
#define MASK_VQWDOTAS_VV 0xfc00707f
#define MATCH_VFWDOTA_VV 0x90001077
#define MASK_VFWDOTA_VV 0xfc00707f
#define MATCH_VFQWDOTA_VV 0x98001077
#define MASK_VFQWDOTA_VV 0xfc00707f
#define MATCH_VFQWDOTA_ALT_VV 0x9c001077
#define MASK_VFQWDOTA_ALT_VV 0xfc00707f
/* Vendor-specific (CORE-V) Xcvmac instructions. */
#define MATCH_CV_MAC 0x9000302b
#define MASK_CV_MAC 0xfe00707f
@ -4902,6 +4913,12 @@ DECLARE_INSN(VFWCVTBF16_F_F_V, MATCH_VFWCVTBF16_F_F_V, MASK_VFWCVTBF16_F_F_V)
/* Zvfbfwma instructions. */
DECLARE_INSN(VFWMACCBF16_VF, MATCH_VFWMACCBF16_VF, MASK_VFWMACCBF16_VF)
DECLARE_INSN(VFWMACCBF16_VV, MATCH_VFWMACCBF16_VV, MASK_VFWMACCBF16_VV)
/* Zvdota instructions. */
DECLARE_INSN(vqwdotau_vv, MATCH_VQWDOTAU_VV, MASK_VQWDOTAU_VV)
DECLARE_INSN(vqwdotas_vv, MATCH_VQWDOTAS_VV, MASK_VQWDOTAS_VV)
DECLARE_INSN(vfwdota_vv, MATCH_VFWDOTA_VV, MASK_VFWDOTA_VV)
DECLARE_INSN(vfqwdota_vv, MATCH_VFQWDOTA_VV, MASK_VFQWDOTA_VV)
DECLARE_INSN(vfqwdota_alt_vv, MATCH_VFQWDOTA_ALT_VV, MASK_VFQWDOTA_ALT_VV)
/* Zvbb/Zvkb instructions. */
DECLARE_INSN(vandn_vv, MATCH_VANDN_VV, MASK_VANDN_VV)
DECLARE_INSN(vandn_vx, MATCH_VANDN_VX, MASK_VANDN_VX)

View file

@ -374,6 +374,8 @@ static inline unsigned int riscv_insn_length (insn_t insn)
#define OP_SH_VTA 6
#define OP_MASK_VMA 0x1
#define OP_SH_VMA 7
#define OP_MASK_VTYPE_ALTFMT 0x1
#define OP_SH_VTYPE_ALTFMT 8
#define OP_MASK_VWD 0x1
#define OP_SH_VWD 26
@ -560,6 +562,8 @@ enum riscv_insn_class
INSN_CLASS_ZVBC,
INSN_CLASS_ZVFBFMIN,
INSN_CLASS_ZVFBFWMA,
INSN_CLASS_ZVFQWDOTA8F,
INSN_CLASS_ZVFWDOTA16BF,
INSN_CLASS_ZVKB,
INSN_CLASS_ZVKG,
INSN_CLASS_ZVKNED,
@ -567,6 +571,9 @@ enum riscv_insn_class
INSN_CLASS_ZVKSED,
INSN_CLASS_ZVKSH,
INSN_CLASS_ZVABD,
INSN_CLASS_ZVQWDOTA8I,
INSN_CLASS_ZVQWDOTA16I,
INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I,
INSN_CLASS_ZICFISS,
INSN_CLASS_ZICFISS_AND_ZCMOP,
INSN_CLASS_ZICFILP,
@ -737,6 +744,7 @@ extern const char * const riscv_pred_succ[16];
extern const char riscv_vecr_names_numeric[NVECR][NRC];
extern const char riscv_vecm_names_numeric[NVECM][NRC];
extern const char * const riscv_vsew[8];
extern const char * const riscv_vsew_altfmt[2];
extern const char * const riscv_vlmul[8];
extern const char * const riscv_vta[2];
extern const char * const riscv_vma[2];

View file

@ -453,17 +453,23 @@ print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info
unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm);
unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm);
unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm);
unsigned int imm_vtype_res = (imm >> 8);
unsigned int imm_vtype_altfmt
= EXTRACT_OPERAND (VTYPE_ALTFMT, imm);
unsigned int imm_vtype_res = (imm >> 9);
if (imm_vsew < ARRAY_SIZE (riscv_vsew)
&& imm_vlmul < ARRAY_SIZE (riscv_vlmul)
&& imm_vta < ARRAY_SIZE (riscv_vta)
&& imm_vma < ARRAY_SIZE (riscv_vma)
&& !imm_vtype_res
&& (imm_vtype_altfmt == 0
|| imm_vsew < ARRAY_SIZE (riscv_vsew_altfmt))
&& riscv_vsew[imm_vsew] != NULL
&& riscv_vlmul[imm_vlmul] != NULL)
print (info->stream, dis_style_text, "%s,%s,%s,%s",
riscv_vsew[imm_vsew],
imm_vtype_altfmt
? riscv_vsew_altfmt[imm_vsew]
: riscv_vsew[imm_vsew],
riscv_vlmul[imm_vlmul], riscv_vta[imm_vta],
riscv_vma[imm_vma]);
else

View file

@ -93,6 +93,12 @@ const char * const riscv_vsew[8] =
"e8", "e16", "e32", "e64", NULL, NULL, NULL, NULL
};
/* The vsetvli/vsetivli vsew altfmt constants. */
const char * const riscv_vsew_altfmt[2] =
{
"e8alt", "e16alt"
};
/* The vsetvli vlmul constants. */
const char * const riscv_vlmul[8] =
{
@ -2244,6 +2250,13 @@ const struct riscv_opcode riscv_opcodes[] =
{"vfwmaccbf16.vf", 0, INSN_CLASS_ZVFBFWMA, "Vd,S,VtVm", MATCH_VFWMACCBF16_VF, MASK_VFWMACCBF16_VF, match_opcode, 0},
{"vfwmaccbf16.vv", 0, INSN_CLASS_ZVFBFWMA, "Vd,Vs,VtVm", MATCH_VFWMACCBF16_VV, MASK_VFWMACCBF16_VV, match_opcode, 0},
/* Zvdota instructions. */
{"vqwdotau.vv", 0, INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I, "Vd,Vt,VsVm", MATCH_VQWDOTAU_VV, MASK_VQWDOTAU_VV, match_opcode, 0},
{"vqwdotas.vv", 0, INSN_CLASS_ZVQWDOTA8I_OR_ZVQWDOTA16I, "Vd,Vt,VsVm", MATCH_VQWDOTAS_VV, MASK_VQWDOTAS_VV, match_opcode, 0},
{"vfwdota.vv", 0, INSN_CLASS_ZVFWDOTA16BF, "Vd,Vt,VsVm", MATCH_VFWDOTA_VV, MASK_VFWDOTA_VV, match_opcode, 0},
{"vfqwdota.vv", 0, INSN_CLASS_ZVFQWDOTA8F, "Vd,Vt,VsVm", MATCH_VFQWDOTA_VV, MASK_VFQWDOTA_VV, match_opcode, 0},
{"vfqwdota.alt.vv", 0, INSN_CLASS_ZVFQWDOTA8F, "Vd,Vt,VsVm", MATCH_VFQWDOTA_ALT_VV, MASK_VFQWDOTA_ALT_VV, match_opcode, 0},
/* Zvbb/Zvkb instructions. */
{"vandn.vv", 0, INSN_CLASS_ZVKB, "Vd,Vt,VsVm", MATCH_VANDN_VV, MASK_VANDN_VV, match_opcode, 0},
{"vandn.vx", 0, INSN_CLASS_ZVKB, "Vd,Vt,sVm", MATCH_VANDN_VX, MASK_VANDN_VX, match_opcode, 0},