RISC-V: Add 'Zmmul' extension in assembler.

Three-part patch set from Tsukasa OI to support zmmul in assembler.

The 'Zmmul' is a RISC-V extension consisting of only multiply instructions
(a subset of 'M' which has multiply and divide instructions).

bfd/
	* elfxx-riscv.c (riscv_implicit_subsets): Add 'Zmmul' implied by 'M'.
	(riscv_supported_std_z_ext): Add 'Zmmul' extension.
	(riscv_multi_subset_supports): Add handling for new instruction class.
gas/
	* testsuite/gas/riscv/attribute-09.d: Updated implicit 'Zmmul' by 'M'.
	* testsuite/gas/riscv/option-arch-02.d: Likewise.
	* testsuite/gas/riscv/m-ext.s: New test.
	* testsuite/gas/riscv/m-ext-32.d: New test (RV32).
	* testsuite/gas/riscv/m-ext-64.d: New test (RV64).
	* testsuite/gas/riscv/zmmul-32.d: New expected output.
	* testsuite/gas/riscv/zmmul-64.d: Likewise.
	* testsuite/gas/riscv/m-ext-fail-xlen-32.d: New test (failure
	by using RV64-only instructions in RV32).
	* testsuite/gas/riscv/m-ext-fail-xlen-32.l: Likewise.
	* testsuite/gas/riscv/m-ext-fail-zmmul-32.d: New failure test
	(RV32 + Zmmul but with no M).
	* testsuite/gas/riscv/m-ext-fail-zmmul-32.l: Likewise.
	* testsuite/gas/riscv/m-ext-fail-zmmul-64.d: New failure test
	(RV64 + Zmmul but with no M).
	* testsuite/gas/riscv/m-ext-fail-zmmul-64.l: Likewise.
	* testsuite/gas/riscv/m-ext-fail-noarch-64.d: New failure test
	(no Zmmul or M).
	* testsuite/gas/riscv/m-ext-fail-noarch-64.l: Likewise.
include/
	* opcode/riscv.h (enum riscv_insn_class): Added INSN_CLASS_ZMMUL.
ld/
	* testsuite/ld-riscv-elf/attr-merge-arch-01.d: We don't care zmmul in
	these testcases, so just replaced m by a.
	* testsuite/ld-riscv-elf/attr-merge-arch-01a.s: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-arch-01b.s: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-arch-02.d: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-arch-02a.s: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-arch-03.d: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-arch-03a.s: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-user-ext-01.d: Likewise.
	* testsuite/ld-riscv-elf/attr-merge-user-ext-rv32i2p1_a2p0.s: Renamed.
	* testsuite/ld-riscv-elf/attr-merge-user-ext-rv32i2p1_a2p1.s: Renamed.
opcodes/
	* riscv-opc.c (riscv_opcodes): Updated multiply instructions to zmmul.
This commit is contained in:
Tsukasa OI 2022-02-02 10:06:15 +09:00 committed by Nelson Chu
parent 1c04f72368
commit 0938b032da
30 changed files with 175 additions and 27 deletions

View File

@ -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:

View File

@ -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"

View File

@ -0,0 +1,18 @@
#as: -march=rv32im
#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]+:[ ]+02c5c533[ ]+div[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5d533[ ]+divu[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5e533[ ]+rem[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5f533[ ]+remu[ ]+a0,a1,a2

View File

@ -0,0 +1,23 @@
#as: -march=rv64im -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]+:[ ]+02c5c533[ ]+div[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5d533[ ]+divu[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5e533[ ]+rem[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5f533[ ]+remu[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5853b[ ]+mulw[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5c53b[ ]+divw[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5d53b[ ]+divuw[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5e53b[ ]+remw[ ]+a0,a1,a2
[ ]+[0-9a-f]+:[ ]+02c5f53b[ ]+remuw[ ]+a0,a1,a2

View File

@ -0,0 +1,4 @@
#as: -march=rv64i -defsym rv64=1
#source: m-ext.s
#objdump: -d
#error_output: m-ext-fail-noarch-64.l

View File

@ -0,0 +1,14 @@
.*Assembler messages:
.*: Error: unrecognized opcode `mul a0,a1,a2', extension `m' or `zmmul' required
.*: Error: unrecognized opcode `mulh a0,a1,a2', extension `m' or `zmmul' required
.*: Error: unrecognized opcode `mulhsu a0,a1,a2', extension `m' or `zmmul' required
.*: Error: unrecognized opcode `mulhu a0,a1,a2', extension `m' or `zmmul' required
.*: Error: unrecognized opcode `div a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divu a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `rem a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remu a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `mulw a0,a1,a2', extension `m' or `zmmul' required
.*: Error: unrecognized opcode `divw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divuw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remuw a0,a1,a2', extension `m' required

View File

@ -0,0 +1,4 @@
#as: -march=rv32im -defsym rv64=1
#source: m-ext.s
#objdump: -d
#error_output: m-ext-fail-xlen-32.l

View File

@ -0,0 +1,6 @@
.*Assembler messages:
.*: Error: unrecognized opcode `mulw a0,a1,a2'
.*: Error: unrecognized opcode `divw a0,a1,a2'
.*: Error: unrecognized opcode `divuw a0,a1,a2'
.*: Error: unrecognized opcode `remw a0,a1,a2'
.*: Error: unrecognized opcode `remuw a0,a1,a2'

View File

@ -0,0 +1,4 @@
#as: -march=rv32i_zmmul
#source: m-ext.s
#objdump: -d
#error_output: m-ext-fail-zmmul-32.l

View File

@ -0,0 +1,5 @@
.*Assembler messages:
.*: Error: unrecognized opcode `div a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divu a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `rem a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remu a0,a1,a2', extension `m' required

View File

@ -0,0 +1,4 @@
#as: -march=rv64i_zmmul -defsym rv64=1
#source: m-ext.s
#objdump: -d
#error_output: m-ext-fail-zmmul-64.l

View File

@ -0,0 +1,9 @@
.*Assembler messages:
.*: Error: unrecognized opcode `div a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divu a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `rem a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remu a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `divuw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remw a0,a1,a2', extension `m' required
.*: Error: unrecognized opcode `remuw a0,a1,a2', extension `m' required

View File

@ -0,0 +1,21 @@
target:
mul a0, a1, a2
mulh a0, a1, a2
mulhsu a0, a1, a2
mulhu a0, a1, a2
.ifndef zmmul
div a0, a1, a2
divu a0, a1, a2
rem a0, a1, a2
remu a0, a1, a2
.endif
.ifdef rv64
mulw a0, a1, a2
.ifndef zmmul
divw a0, a1, a2
divuw a0, a1, a2
remw a0, a1, a2
remuw a0, a1, a2
.endif
.endif

View File

@ -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"
#...

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -6,4 +6,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_m2p0"
Tag_RISCV_arch: "rv32i2p1_a2p0"

View File

@ -1 +1 @@
.attribute arch, "rv32i2p1_m2p0"
.attribute arch, "rv32i2p1_a2p0"

View File

@ -1 +1 @@
.attribute arch, "rv32i2p1_m2p0"
.attribute arch, "rv32i2p1_a2p0"

View File

@ -6,4 +6,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_m2p0"
Tag_RISCV_arch: "rv32i2p1_a2p0"

View File

@ -1 +1 @@
.attribute arch, "rv32i2p1_m2p0"
.attribute arch, "rv32i2p1_a2p0"

View File

@ -6,4 +6,4 @@
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_m2p0_xbar2p0_xfoo2p0"
Tag_RISCV_arch: "rv32i2p1_a2p0_xbar2p0_xfoo2p0"

View File

@ -1 +1 @@
.attribute arch, "rv32i2p1_m2p0_xfoo2p0"
.attribute arch, "rv32i2p1_a2p0_xfoo2p0"

View File

@ -1,9 +1,9 @@
#source: attr-merge-user-ext-rv32i2p1_m2p0.s
#source: attr-merge-user-ext-rv32i2p1_m2p1.s
#source: attr-merge-user-ext-rv32i2p1_a2p0.s
#source: attr-merge-user-ext-rv32i2p1_a2p1.s
#as:
#ld: -r -m[riscv_choose_ilp32_emul]
#readelf: -A
Attribute Section: riscv
File Attributes
Tag_RISCV_arch: "rv32i2p1_m2p1"
Tag_RISCV_arch: "rv32i2p1_a2p1"

View File

@ -0,0 +1 @@
.attribute arch, "rv32i2p1_a2p0"

View File

@ -0,0 +1 @@
.attribute arch, "rv32i2p1_a2p1"

View File

@ -1 +0,0 @@
.attribute arch, "rv32i2p1_m2p0"

View File

@ -1 +0,0 @@
.attribute arch, "rv32i2p1_m2p1"

View File

@ -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 },