RISC-V: Support Zacas extension.

https://github.com/riscvarchive/riscv-zacas/releases/tag/v1.0

The Zacas extension introduce compare-and-swap instructions to operate
on 32-bit, 64-bit and 128-bit (RV64 only) data values.

It introduces three new instructions:
  - amocas.w (32-bit CAS)
  - amocas.d (64-bit CAS)
  - amocas.q (128-bit CAS, RV64 only)

Like other AMOs in the A extension, Zacas instructions have '.aq',
'.rl' and '.aqrl' variations.

bfd/ChangeLog:

	* elfxx-riscv.c (riscv_implicit_subsets): 'A' implied by 'Zacas'.
	(riscv_supported_std_z_ext): Add 'Zacas' extension.
	(riscv_multi_subset_supports, riscv_multi_subset_supports_ext):
	Handle INSN_CLASS_ZACAS case.

gas/ChangeLog:

	* NEWS: Updated.
	* testsuite/gas/riscv/march-help.l: Updated.
	* testsuite/gas/riscv/zacas-32.d: New test (RV32).
        * testsuite/gas/riscv/zacas-fail-32.d: Likewise.
	* testsuite/gas/riscv/zacas-64.d: New test (RV64).
        * testsuite/gas/riscv/zacas-fail-64.d: Likewise.
	* testsuite/gas/riscv/zacas.s: New test source.
	* testsuite/gas/riscv/zacas-fail.s: Likewise.
	* testsuite/gas/riscv/zacas-fail-32.l: New file.
	* testsuite/gas/riscv/zacas-fail-64.l: Likewise.

include/ChangeLog:

	* include/opcode/riscv.h (INSN_CLASS_ZACAS): New definition.
	* include/opcode/riscv-opc.h (MATCH_AMOCAS_W, MASK_AMOCAS_W)
	(MATCH_AMOCAS_D, MASK_AMOCAS_D, MATCH_AMOCAS_Q, MASK_AMOCAS_Q):
	Likewise.
	(amocas_w, amocas_d, amocas_q): Declare instructions.

opcodes/ChangeLog:

	* riscv-opc.c (match_rs2_rd_even): New function.
	(amocas_w, amocas_d, amocas_q, amocas_w.aq)
	(amocas_d.aq, amocas_q.aq, amocas_w.rl, amocas_d.rl, amocas_q.rl)
	(amocas_w.aqrl, amocas_d.aqrl, amocas_q.aqrl): Add instructions.
This commit is contained in:
Gianluca Guida 2023-05-31 17:28:56 +01:00 committed by Nelson Chu
parent 0915235d34
commit 88729e9616
14 changed files with 183 additions and 0 deletions

View File

@ -1192,6 +1192,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
{"v", "zve64d", check_implicit_always},
{"v", "zvl128b", check_implicit_always},
{"zabha", "a", check_implicit_always},
{"zacas", "a", check_implicit_always},
{"zvfbfmin", "zve32f", check_implicit_always},
{"zvfbfwma", "zve32f", check_implicit_always},
{"zvfbfwma", "zfbfmin", check_implicit_always},
@ -1363,6 +1364,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
{"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zaamo", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zabha", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zacas", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zalrsc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zfbfmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
@ -2545,6 +2547,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
return riscv_subset_supports (rps, "zaamo");
case INSN_CLASS_ZABHA:
return riscv_subset_supports (rps, "zabha");
case INSN_CLASS_ZACAS:
return riscv_subset_supports (rps, "zacas");
case INSN_CLASS_ZALRSC:
return riscv_subset_supports (rps, "zalrsc");
case INSN_CLASS_ZAWRS:
@ -2785,6 +2789,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
return "zaamo";
case INSN_CLASS_ZABHA:
return "zabha";
case INSN_CLASS_ZACAS:
return "zacas";
case INSN_CLASS_ZALRSC:
return "zalrsc";
case INSN_CLASS_ZAWRS:

View File

@ -19,6 +19,8 @@
* Remove support for RISC-V privileged spec 1.9.1, but linker can still
recognize it in case of linking old objects.
* Add support for RISC-V Zacas extension with version 1.0.
* Add support for RISC-V Zcmp extension with version 1.0.
* Add support for RISC-V Zfbfmin extension with version 1.0.

View File

@ -23,6 +23,7 @@ All available -march extensions for RISC-V:
zmmul 1.0
zaamo 1.0
zabha 1.0
zacas 1.0
zalrsc 1.0
zawrs 1.0
zfbfmin 1.0

View File

@ -0,0 +1,26 @@
#as: -march=rv32ia_zacas
#source: zacas.s
#objdump: -d
.*:[ ]+file format .*
Disassembly of section .text:
0+000 <target>:
[ ]+[0-9a-f]+:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)

View File

@ -0,0 +1,34 @@
#as: -march=rv64ia_zacas -defsym rv64=1
#source: zacas.s
#objdump: -d
.*:[ ]+file format .*
Disassembly of section .text:
0+000 <target>:
[ ]+[0-9a-f]+:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5452f[ ]+amocas.q[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+28a5452f[ ]+amocas.q[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5452f[ ]+amocas.q.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ca5452f[ ]+amocas.q.aq[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5452f[ ]+amocas.q.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2aa5452f[ ]+amocas.q.rl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5452f[ ]+amocas.q.aqrl[ ]+a0,a0,\(a0\)
[ ]+[0-9a-f]+:[ ]+2ea5452f[ ]+amocas.q.aqrl[ ]+a0,a0,\(a0\)

View File

@ -0,0 +1,3 @@
#as: -march=rv32ia_zacas
#source: zacas-fail.s
#error_output: zacas-fail-32.l

View File

@ -0,0 +1,17 @@
.*: Assembler messages:
.*: Error: illegal operands `amocas.d a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.d a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.d.aq a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.d.aq a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.d.rl a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.d.rl a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.d.aqrl a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.d.aqrl a0,a1,\(a0\)'
.*: Error: unrecognized opcode `amocas.q a1,a0,\(a0\)'
.*: Error: unrecognized opcode `amocas.q a0,a1,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.aq a1,a0,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.aq a0,a1,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.rl a1,a0,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.rl a0,a1,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.aqrl a1,a0,\(a0\)'
.*: Error: unrecognized opcode `amocas.q.aqrl a0,a1,\(a0\)'

View File

@ -0,0 +1,3 @@
#as: -march=rv64ia_zacas
#source: zacas-fail.s
#error_output: zacas-fail-64.l

View File

@ -0,0 +1,9 @@
.*: Assembler messages:
.*: Error: illegal operands `amocas.q a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.q a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.q.aq a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.q.aq a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.q.rl a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.q.rl a0,a1,\(a0\)'
.*: Error: illegal operands `amocas.q.aqrl a1,a0,\(a0\)'
.*: Error: illegal operands `amocas.q.aqrl a0,a1,\(a0\)'

View File

@ -0,0 +1,17 @@
# rd and rs2 must be even
amocas.d a1, a0, (a0)
amocas.d a0, a1, (a0)
amocas.d.aq a1, a0, (a0)
amocas.d.aq a0, a1, (a0)
amocas.d.rl a1, a0, (a0)
amocas.d.rl a0, a1, (a0)
amocas.d.aqrl a1, a0, (a0)
amocas.d.aqrl a0, a1, (a0)
amocas.q a1, a0, (a0)
amocas.q a0, a1, (a0)
amocas.q.aq a1, a0, (a0)
amocas.q.aq a0, a1, (a0)
amocas.q.rl a1, a0, (a0)
amocas.q.rl a0, a1, (a0)
amocas.q.aqrl a1, a0, (a0)
amocas.q.aqrl a0, a1, (a0)

View File

@ -0,0 +1,27 @@
target:
amocas.w a0, a0, 0(a0)
amocas.w a0, a0, (a0)
amocas.w.aq a0, a0, 0(a0)
amocas.w.aq a0, a0, (a0)
amocas.w.rl a0, a0, 0(a0)
amocas.w.rl a0, a0, (a0)
amocas.w.aqrl a0, a0, 0(a0)
amocas.w.aqrl a0, a0, (a0)
amocas.d a0, a0, 0(a0)
amocas.d a0, a0, (a0)
amocas.d.aq a0, a0, 0(a0)
amocas.d.aq a0, a0, (a0)
amocas.d.rl a0, a0, 0(a0)
amocas.d.rl a0, a0, (a0)
amocas.d.aqrl a0, a0, 0(a0)
amocas.d.aqrl a0, a0, (a0)
.ifdef rv64
amocas.q a0, a0, 0(a0)
amocas.q a0, a0, (a0)
amocas.q.aq a0, a0, 0(a0)
amocas.q.aq a0, a0, (a0)
amocas.q.rl a0, a0, 0(a0)
amocas.q.rl a0, a0, (a0)
amocas.q.aqrl a0, a0, 0(a0)
amocas.q.aqrl a0, a0, (a0)
.endif

View File

@ -2360,6 +2360,13 @@
#define MASK_C_NTL_S1 0xffff
#define MATCH_C_NTL_ALL 0x9016
#define MASK_C_NTL_ALL 0xffff
/* Zacas instructions. */
#define MATCH_AMOCAS_W 0x2800202f
#define MASK_AMOCAS_W 0xf800707f
#define MATCH_AMOCAS_D 0x2800302f
#define MASK_AMOCAS_D 0xf800707f
#define MATCH_AMOCAS_Q 0x2800402f
#define MASK_AMOCAS_Q 0xf800707f
/* Zawrs instructions. */
#define MATCH_WRS_NTO 0x00d00073
#define MASK_WRS_NTO 0xffffffff
@ -3998,6 +4005,10 @@ DECLARE_INSN(c_ntl_p1, MATCH_C_NTL_P1, MASK_C_NTL_P1)
DECLARE_INSN(c_ntl_pall, MATCH_C_NTL_PALL, MASK_C_NTL_PALL)
DECLARE_INSN(c_ntl_s1, MATCH_C_NTL_S1, MASK_C_NTL_S1)
DECLARE_INSN(c_ntl_all, MATCH_C_NTL_ALL, MASK_C_NTL_ALL)
/* Zacas instructions. */
DECLARE_INSN(amocas_w, MATCH_AMOCAS_W, MASK_AMOCAS_W)
DECLARE_INSN(amocas_d, MATCH_AMOCAS_D, MASK_AMOCAS_D)
DECLARE_INSN(amocas_q, MATCH_AMOCAS_Q, MASK_AMOCAS_Q)
/* Zawrs instructions. */
DECLARE_INSN(wrs_nto, MATCH_WRS_NTO, MASK_WRS_NTO)
DECLARE_INSN(wrs_sto, MATCH_WRS_STO, MASK_WRS_STO)

View File

@ -492,6 +492,7 @@ enum riscv_insn_class
INSN_CLASS_ZICBOP,
INSN_CLASS_ZICBOZ,
INSN_CLASS_ZABHA,
INSN_CLASS_ZACAS,
INSN_CLASS_H,
INSN_CLASS_XCVMAC,
INSN_CLASS_XCVALU,

View File

@ -197,6 +197,14 @@ match_rs1_eq_rs2 (const struct riscv_opcode *op, insn_t insn)
return match_opcode (op, insn) && rs1 == rs2;
}
static int
match_rs2_rd_even (const struct riscv_opcode *op, insn_t insn)
{
int rs2 = (insn & MASK_RS2) >> OP_SH_RS2;
int rd = (insn & MASK_RD) >> OP_SH_RD;
return ((rs2 & 1) == 0) && ((rd & 1) == 0) && match_opcode (op, insn);
}
static int
match_rd_nonzero (const struct riscv_opcode *op, insn_t insn)
{
@ -748,6 +756,24 @@ const struct riscv_opcode riscv_opcodes[] =
{"amomin.h.aqrl", 0, INSN_CLASS_ZABHA, "d,t,0(s)", MATCH_AMOMIN_H|MASK_AQRL, MASK_AMOMIN_H|MASK_AQRL, match_opcode, INSN_DREF|INSN_2_BYTE },
{"amominu.h.aqrl", 0, INSN_CLASS_ZABHA, "d,t,0(s)", MATCH_AMOMINU_H|MASK_AQRL, MASK_AMOMINU_H|MASK_AQRL, match_opcode, INSN_DREF|INSN_2_BYTE },
/* Zacas instruction subset. */
{"amocas.w", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
{"amocas.d", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_8_BYTE },
{"amocas.d", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
{"amocas.q", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q, MASK_AMOCAS_Q|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_16_BYTE },
{"amocas.w.aq", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_AQ, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
{"amocas.d.aq", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQ, MASK_AMOCAS_D|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_8_BYTE },
{"amocas.d.aq", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQ, MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
{"amocas.q.aq", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_AQ, MASK_AMOCAS_Q|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_16_BYTE },
{"amocas.w.rl", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_RL, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
{"amocas.d.rl", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_RL, MASK_AMOCAS_D|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_8_BYTE },
{"amocas.d.rl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_RL, MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
{"amocas.q.rl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_RL, MASK_AMOCAS_Q|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_16_BYTE },
{"amocas.w.aqrl", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_W|MASK_AQRL, MASK_AMOCAS_W|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
{"amocas.d.aqrl", 32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQRL, MASK_AMOCAS_D|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_8_BYTE },
{"amocas.d.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D|MASK_AQRL, MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
{"amocas.q.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q|MASK_AQRL, MASK_AMOCAS_Q|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_16_BYTE },
/* Multiply/Divide instruction subset. */
{"mul", 0, INSN_CLASS_ZCB_AND_ZMMUL, "Cs,Cw,Ct", MATCH_C_MUL, MASK_C_MUL, match_opcode, INSN_ALIAS },
{"mul", 0, INSN_CLASS_ZMMUL, "d,s,t", MATCH_MUL, MASK_MUL, match_opcode, 0 },