[PATCH v5 2/3] RISC-V: Add 'Zmmul' extension

Tsukasa OI research_trasio@irq.a4lg.com
Mon Aug 29 01:58:17 GMT 2022


This commit adds 'Zmmul' (multiply-only subset of 'M') extension and
changes so that multiply instructions a part of 'Zmmul'.

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_implicit_subsets): Add 'Zmmul' extension
	implied by 'M'. (riscv_supported_std_z_ext) Add 'Zmmul'
	extension. (riscv_multi_subset_supports): Add handling for
	new instruction class.

gas/ChangeLog:

	* testsuite/gas/riscv/attribute-09.d: Include implied 'Zmmul'
	extension to expected output.
	* testsuite/gas/riscv/option-arch-02.d: Include implied 'Zmmul'
	extension to expected output.
	* testsuite/gas/riscv/zmmul-32.d: New expected output.
	* testsuite/gas/riscv/zmmul-64.d: Likewise.

include/ChangeLog:

	* opcode/riscv.h (enum riscv_insn_class): Add new instruction
	class INSN_CLASS_ZMMUL.

opcodes/ChangeLog:

	* riscv-opc.c (riscv_opcodes): Change multiply instructions so
	that a part of 'Zmmul' extension.

sim/ChangeLog:

	* riscv/sim-main.c (execute_one): Add INSN_CLASS_ZMMUL
	to run multiply instructions correctly.
	* testsuite/riscv/m-ext.s: New test.
---
 bfd/elfxx-riscv.c                        |  6 ++++++
 gas/testsuite/gas/riscv/attribute-09.d   |  2 +-
 gas/testsuite/gas/riscv/option-arch-02.d |  2 +-
 gas/testsuite/gas/riscv/zmmul-32.d       | 14 +++++++++++++
 gas/testsuite/gas/riscv/zmmul-64.d       | 15 ++++++++++++++
 include/opcode/riscv.h                   |  1 +
 opcodes/riscv-opc.c                      | 26 ++++++++++++------------
 sim/riscv/sim-main.c                     |  1 +
 sim/testsuite/riscv/m-ext.s              | 18 ++++++++++++++++
 9 files changed, 70 insertions(+), 15 deletions(-)
 create mode 100644 gas/testsuite/gas/riscv/zmmul-32.d
 create mode 100644 gas/testsuite/gas/riscv/zmmul-64.d
 create mode 100644 sim/testsuite/riscv/m-ext.s

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index c9636bcbdc8..8cb3c8d4930 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1039,6 +1039,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"e", "i",		check_implicit_always},
   {"i", "zicsr",	check_implicit_for_i},
   {"i", "zifencei",	check_implicit_for_i},
+  {"m", "zmmul",	check_implicit_always},
   {"g", "i",		check_implicit_always},
   {"g", "m",		check_implicit_always},
   {"g", "a",		check_implicit_always},
@@ -1160,6 +1161,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zifencei",		ISA_SPEC_CLASS_20191213,	2, 0,  0 },
   {"zifencei",		ISA_SPEC_CLASS_20190608,	2, 0,  0 },
   {"zihintpause",	ISA_SPEC_CLASS_DRAFT,		2, 0,  0 },
+  {"zmmul",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfh",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfhmin",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfinx",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
@@ -2287,6 +2289,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "zihintpause");
     case INSN_CLASS_M:
       return riscv_subset_supports (rps, "m");
+    case INSN_CLASS_ZMMUL:
+      return riscv_subset_supports (rps, "zmmul");
     case INSN_CLASS_A:
       return riscv_subset_supports (rps, "a");
     case INSN_CLASS_F:
@@ -2402,6 +2406,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return "zihintpause";
     case INSN_CLASS_M:
       return "m";
+    case INSN_CLASS_ZMMUL:
+      return _ ("m' or `zmmul");
     case INSN_CLASS_A:
       return "a";
     case INSN_CLASS_F:
diff --git a/gas/testsuite/gas/riscv/attribute-09.d b/gas/testsuite/gas/riscv/attribute-09.d
index fc87f82c554..c92dc970eea 100644
--- a/gas/testsuite/gas/riscv/attribute-09.d
+++ b/gas/testsuite/gas/riscv/attribute-09.d
@@ -3,4 +3,4 @@
 #source: empty.s
 Attribute Section: riscv
 File Attributes
-  Tag_RISCV_arch: "rv32i2p2_m2p0_zicsr2p0"
+  Tag_RISCV_arch: "rv32i2p2_m2p0_zicsr2p0_zmmul1p0"
diff --git a/gas/testsuite/gas/riscv/option-arch-02.d b/gas/testsuite/gas/riscv/option-arch-02.d
index 9ca013e507e..3c27419f9d3 100644
--- a/gas/testsuite/gas/riscv/option-arch-02.d
+++ b/gas/testsuite/gas/riscv/option-arch-02.d
@@ -4,5 +4,5 @@
 
 Attribute Section: riscv
 File Attributes
-  Tag_RISCV_arch: "rv64i2p0_m3p0_f2p0_d3p0_c2p0_xvendor32x3p0"
+  Tag_RISCV_arch: "rv64i2p0_m3p0_f2p0_d3p0_c2p0_zmmul1p0_xvendor32x3p0"
 #...
diff --git a/gas/testsuite/gas/riscv/zmmul-32.d b/gas/testsuite/gas/riscv/zmmul-32.d
new file mode 100644
index 00000000000..c9cf56ab33f
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zmmul-32.d
@@ -0,0 +1,14 @@
+#as: -march=rv32im -defsym zmmul=1
+#source: m-ext.s
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+02c58533[ 	]+mul[  	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c59533[ 	]+mulh[ 	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c5a533[ 	]+mulhsu[ 	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c5b533[ 	]+mulhu[ 	]+a0,a1,a2
diff --git a/gas/testsuite/gas/riscv/zmmul-64.d b/gas/testsuite/gas/riscv/zmmul-64.d
new file mode 100644
index 00000000000..67ef3604755
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zmmul-64.d
@@ -0,0 +1,15 @@
+#as: -march=rv64im -defsym zmmul=1 -defsym rv64=1
+#source: m-ext.s
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+02c58533[ 	]+mul[  	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c59533[ 	]+mulh[ 	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c5a533[ 	]+mulhsu[ 	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c5b533[ 	]+mulhu[ 	]+a0,a1,a2
+[ 	]+[0-9a-f]+:[ 	]+02c5853b[ 	]+mulw[ 	]+a0,a1,a2
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index b115e338a05..f1dabeaab8e 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -367,6 +367,7 @@ enum riscv_insn_class
   INSN_CLASS_ZICSR,
   INSN_CLASS_ZIFENCEI,
   INSN_CLASS_ZIHINTPAUSE,
+  INSN_CLASS_ZMMUL,
   INSN_CLASS_F_OR_ZFINX,
   INSN_CLASS_D_OR_ZDINX,
   INSN_CLASS_Q_OR_ZQINX,
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 2f9945aa930..79be78eb367 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -558,19 +558,19 @@ const struct riscv_opcode riscv_opcodes[] =
 {"amominu.d.aqrl", 64, INSN_CLASS_A, "d,t,0(s)", MATCH_AMOMINU_D|MASK_AQRL, MASK_AMOMINU_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
 
 /* Multiply/Divide instruction subset.  */
-{"mul",        0, INSN_CLASS_M,   "d,s,t",     MATCH_MUL, MASK_MUL, match_opcode, 0 },
-{"mulh",       0, INSN_CLASS_M,   "d,s,t",     MATCH_MULH, MASK_MULH, match_opcode, 0 },
-{"mulhu",      0, INSN_CLASS_M,   "d,s,t",     MATCH_MULHU, MASK_MULHU, match_opcode, 0 },
-{"mulhsu",     0, INSN_CLASS_M,   "d,s,t",     MATCH_MULHSU, MASK_MULHSU, match_opcode, 0 },
-{"div",        0, INSN_CLASS_M,   "d,s,t",     MATCH_DIV, MASK_DIV, match_opcode, 0 },
-{"divu",       0, INSN_CLASS_M,   "d,s,t",     MATCH_DIVU, MASK_DIVU, match_opcode, 0 },
-{"rem",        0, INSN_CLASS_M,   "d,s,t",     MATCH_REM, MASK_REM, match_opcode, 0 },
-{"remu",       0, INSN_CLASS_M,   "d,s,t",     MATCH_REMU, MASK_REMU, match_opcode, 0 },
-{"mulw",      64, INSN_CLASS_M,   "d,s,t",     MATCH_MULW, MASK_MULW, match_opcode, 0 },
-{"divw",      64, INSN_CLASS_M,   "d,s,t",     MATCH_DIVW, MASK_DIVW, match_opcode, 0 },
-{"divuw",     64, INSN_CLASS_M,   "d,s,t",     MATCH_DIVUW, MASK_DIVUW, match_opcode, 0 },
-{"remw",      64, INSN_CLASS_M,   "d,s,t",     MATCH_REMW, MASK_REMW, match_opcode, 0 },
-{"remuw",     64, INSN_CLASS_M,   "d,s,t",     MATCH_REMUW, MASK_REMUW, match_opcode, 0 },
+{"mul",        0, INSN_CLASS_ZMMUL, "d,s,t",     MATCH_MUL, MASK_MUL, match_opcode, 0 },
+{"mulh",       0, INSN_CLASS_ZMMUL, "d,s,t",     MATCH_MULH, MASK_MULH, match_opcode, 0 },
+{"mulhu",      0, INSN_CLASS_ZMMUL, "d,s,t",     MATCH_MULHU, MASK_MULHU, match_opcode, 0 },
+{"mulhsu",     0, INSN_CLASS_ZMMUL, "d,s,t",     MATCH_MULHSU, MASK_MULHSU, match_opcode, 0 },
+{"div",        0, INSN_CLASS_M,     "d,s,t",     MATCH_DIV, MASK_DIV, match_opcode, 0 },
+{"divu",       0, INSN_CLASS_M,     "d,s,t",     MATCH_DIVU, MASK_DIVU, match_opcode, 0 },
+{"rem",        0, INSN_CLASS_M,     "d,s,t",     MATCH_REM, MASK_REM, match_opcode, 0 },
+{"remu",       0, INSN_CLASS_M,     "d,s,t",     MATCH_REMU, MASK_REMU, match_opcode, 0 },
+{"mulw",      64, INSN_CLASS_ZMMUL, "d,s,t",     MATCH_MULW, MASK_MULW, match_opcode, 0 },
+{"divw",      64, INSN_CLASS_M,     "d,s,t",     MATCH_DIVW, MASK_DIVW, match_opcode, 0 },
+{"divuw",     64, INSN_CLASS_M,     "d,s,t",     MATCH_DIVUW, MASK_DIVUW, match_opcode, 0 },
+{"remw",      64, INSN_CLASS_M,     "d,s,t",     MATCH_REMW, MASK_REMW, match_opcode, 0 },
+{"remuw",     64, INSN_CLASS_M,     "d,s,t",     MATCH_REMUW, MASK_REMUW, match_opcode, 0 },
 
 /* Half-precision floating-point instruction subset.  */
 {"flh",        0, INSN_CLASS_ZFHMIN,   "D,o(s)",    MATCH_FLH, MASK_FLH, match_opcode, INSN_DREF|INSN_2_BYTE },
diff --git a/sim/riscv/sim-main.c b/sim/riscv/sim-main.c
index 62f475671c9..ea88103098a 100644
--- a/sim/riscv/sim-main.c
+++ b/sim/riscv/sim-main.c
@@ -936,6 +936,7 @@ execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
     case INSN_CLASS_I:
       return execute_i (cpu, iw, op);
     case INSN_CLASS_M:
+    case INSN_CLASS_ZMMUL:
       return execute_m (cpu, iw, op);
     default:
       TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
diff --git a/sim/testsuite/riscv/m-ext.s b/sim/testsuite/riscv/m-ext.s
new file mode 100644
index 00000000000..b85397a32a0
--- /dev/null
+++ b/sim/testsuite/riscv/m-ext.s
@@ -0,0 +1,18 @@
+# check that the RV32M instructions run without any fault.
+# mach: riscv
+
+.include "testutils.inc"
+
+	start
+
+	.option	arch, +m
+	mul	x0, x1, x2
+	mulh	x0, x1, x2
+	mulhu	x0, x1, x2
+	mulhsu	x0, x1, x2
+	div	x0, x1, x2
+	divu	x0, x1, x2
+	rem	x0, x1, x2
+	remu	x0, x1, x2
+
+	pass
-- 
2.34.1



More information about the Binutils mailing list