Please note: This is a draft specification and this patch should not be
merged at this time.
This implements the Zacas (Atomic Compare-and-Swap) extension, as of
version 0.1, 4/2023.
The Zacas extension introduces 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.
See https://github.com/riscv/riscv-zacas for the proposed
specification.
Thank you,
Gianluca
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:
* testsuite/gas/riscv/zacas-32.d: New test (RV32).
* testsuite/gas/riscv/zacas-64.d: New test (RV64).
* testsuite/gas/riscv/zacas.s: New test source.
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 (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.
Signed-off-by: Gianluca Guida <gianluca@rivosinc.com>
---
bfd/elfxx-riscv.c | 6 ++++++
gas/testsuite/gas/riscv/zacas-32.d | 26 +++++++++++++++++++++++
gas/testsuite/gas/riscv/zacas-64.d | 34 ++++++++++++++++++++++++++++++
gas/testsuite/gas/riscv/zacas.s | 27 ++++++++++++++++++++++++
include/opcode/riscv-opc.h | 11 ++++++++++
include/opcode/riscv.h | 1 +
opcodes/riscv-opc.c | 14 ++++++++++++
7 files changed, 119 insertions(+)
create mode 100644 gas/testsuite/gas/riscv/zacas-32.d
create mode 100644 gas/testsuite/gas/riscv/zacas-64.d
create mode 100644 gas/testsuite/gas/riscv/zacas.s
+{"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", 0, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_D|MASK_RL, MASK_AMOCAS_D|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_BYTE },
+{"amocas.q.rl", 64, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_Q|MASK_RL, MASK_AMOCAS_Q|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_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", 0, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_D|MASK_AQRL, MASK_AMOCAS_D|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_BYTE },
+{"amocas.q.aqrl", 64, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_Q|MASK_AQRL, MASK_AMOCAS_Q|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_BYTE },
+
/* RVV instructions. */
{"vsetvl", 0, INSN_CLASS_V, "d,s,t", MATCH_VSETVL, MASK_VSETVL,
match_opcode, 0},
{"vsetvli", 0, INSN_CLASS_V, "d,s,Vc", MATCH_VSETVLI,
MASK_VSETVLI, match_opcode, 0},
On 12.05.2023 05:44, Gianluca Guida wrote:
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -1053,6 +1053,20 @@ const struct riscv_opcode riscv_opcodes[] =
> {"sm3p0", 0, INSN_CLASS_ZKSH, "d,s", MATCH_SM3P0, MASK_SM3P0,
> match_opcode, 0 },
> {"sm3p1", 0, INSN_CLASS_ZKSH, "d,s", MATCH_SM3P1, MASK_SM3P1,
> match_opcode, 0 },
> +/* Zacas instructions. */
> +{"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", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D,
> MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
> +{"amocas.q", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q,
> MASK_AMOCAS_Q|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
There are constraints on the usable registers for the 2*XLEN operations.
You neither reject invalid input during assembly, nor do you flag bad
encodings as such during disassembly. (Both aspects would also want to
have respective testcases, imo.)
As an aside please be aware that your patch came through slightly
mangled. If you can't change your mailer suitably, please attach the
patch (besides inlining it, which makes commenting easier).
Jan
@@ -1108,6 +1108,7 @@ static struct riscv_implicit_subset
riscv_implicit_subsets[] =
{"sscofpmf", "zicsr", check_implicit_always},
{"ssstateen", "zicsr", check_implicit_always},
{"sstc", "zicsr", check_implicit_always},
+ {"zacas", "a", check_implicit_always},
{NULL, NULL, NULL}
};
@@ -1218,6 +1219,7 @@ static struct riscv_supported_ext
riscv_supported_std_z_ext[] =
{"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 },
{"ztso", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
+ {"zacas", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 },
{NULL, 0, 0, 0, 0}
};
@@ -2361,6 +2363,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_ZACAS:
+ return riscv_subset_supports (rps, "zacas");
case INSN_CLASS_XTHEADBA:
return riscv_subset_supports (rps, "xtheadba");
case INSN_CLASS_XTHEADBB:
@@ -2521,6 +2525,8 @@ riscv_multi_subset_supports_ext
(riscv_parse_subset_t *rps,
return "svinval";
case INSN_CLASS_H:
return _("h");
+ case INSN_CLASS_ZACAS:
+ return _("zacas");
case INSN_CLASS_XTHEADBA:
return "xtheadba";
case INSN_CLASS_XTHEADBB:
b/gas/testsuite/gas/riscv/zacas-32.d
new file mode 100644
@@ -0,0 +1,26 @@
+#as: -march=rv32ia_zacas
+#source: zacas.s
+#objdump: -d
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ ]+0:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
+[ ]+4:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
+[ ]+8:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
+[ ]+c:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
+[ ]+10:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
+[ ]+14:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
+[ ]+18:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
+[ ]+1c:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
+[ ]+20:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
+[ ]+24:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
+[ ]+28:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
+[ ]+2c:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
+[ ]+30:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
+[ ]+34:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
+[ ]+38:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
+[ ]+3c:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
b/gas/testsuite/gas/riscv/zacas-64.d
new file mode 100644
@@ -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:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
+[ ]+4:[ ]+28a5252f[ ]+amocas.w[ ]+a0,a0,\(a0\)
+[ ]+8:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
+[ ]+c:[ ]+2ca5252f[ ]+amocas.w.aq[ ]+a0,a0,\(a0\)
+[ ]+10:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
+[ ]+14:[ ]+2aa5252f[ ]+amocas.w.rl[ ]+a0,a0,\(a0\)
+[ ]+18:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
+[ ]+1c:[ ]+2ea5252f[ ]+amocas.w.aqrl[ ]+a0,a0,\(a0\)
+[ ]+20:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
+[ ]+24:[ ]+28a5352f[ ]+amocas.d[ ]+a0,a0,\(a0\)
+[ ]+28:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
+[ ]+2c:[ ]+2ca5352f[ ]+amocas.d.aq[ ]+a0,a0,\(a0\)
+[ ]+30:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
+[ ]+34:[ ]+2aa5352f[ ]+amocas.d.rl[ ]+a0,a0,\(a0\)
+[ ]+38:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
+[ ]+3c:[ ]+2ea5352f[ ]+amocas.d.aqrl[ ]+a0,a0,\(a0\)
+[ ]+40:[ ]+28a5452f[ ]+amocas.q[ ]+a0,a0,\(a0\)
+[ ]+44:[ ]+28a5452f[ ]+amocas.q[ ]+a0,a0,\(a0\)
+[ ]+48:[ ]+2ca5452f[ ]+amocas.q.aq[ ]+a0,a0,\(a0\)
+[ ]+4c:[ ]+2ca5452f[ ]+amocas.q.aq[ ]+a0,a0,\(a0\)
+[ ]+50:[ ]+2aa5452f[ ]+amocas.q.rl[ ]+a0,a0,\(a0\)
+[ ]+54:[ ]+2aa5452f[ ]+amocas.q.rl[ ]+a0,a0,\(a0\)
+[ ]+58:[ ]+2ea5452f[ ]+amocas.q.aqrl[ ]+a0,a0,\(a0\)
+[ ]+5c:[ ]+2ea5452f[ ]+amocas.q.aqrl[ ]+a0,a0,\(a0\)
b/gas/testsuite/gas/riscv/zacas.s
new file mode 100644
@@ -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
@@ -2118,6 +2118,13 @@
#define MASK_WRS_NTO 0xffffffff
#define MATCH_WRS_STO 0x01d00073
#define MASK_WRS_STO 0xffffffff
+/* 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
/* Vendor-specific (T-Head) XTheadBa instructions. */
#define MATCH_TH_ADDSL 0x0000100b
#define MASK_TH_ADDSL 0xf800707f
@@ -3120,6 +3127,10 @@ DECLARE_INSN(cbo_clean, MATCH_CBO_CLEAN,
MASK_CBO_CLEAN);
DECLARE_INSN(cbo_flush, MATCH_CBO_FLUSH, MASK_CBO_FLUSH);
DECLARE_INSN(cbo_inval, MATCH_CBO_INVAL, MASK_CBO_INVAL);
DECLARE_INSN(cbo_zero, MATCH_CBO_ZERO, MASK_CBO_ZERO);
+/* 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)
@@ -410,6 +410,7 @@ enum riscv_insn_class
INSN_CLASS_ZICBOP,
INSN_CLASS_ZICBOZ,
INSN_CLASS_H,
+ INSN_CLASS_ZACAS,
INSN_CLASS_XTHEADBA,
INSN_CLASS_XTHEADBB,
INSN_CLASS_XTHEADBS,
@@ -1053,6 +1053,20 @@ const struct riscv_opcode riscv_opcodes[] =
{"sm3p0", 0, INSN_CLASS_ZKSH, "d,s", MATCH_SM3P0, MASK_SM3P0,
match_opcode, 0 },
{"sm3p1", 0, INSN_CLASS_ZKSH, "d,s", MATCH_SM3P1, MASK_SM3P1,
match_opcode, 0 },
+/* Zacas instructions. */
+{"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", 0, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D,
MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_BYTE },
+{"amocas.q", 64, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_Q,
MASK_AMOCAS_Q|MASK_AQRL, match_opcode, INSN_DREF|INSN_4_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", 0, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_D|MASK_AQ, MASK_AMOCAS_D|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_BYTE },
+{"amocas.q.aq", 64, INSN_CLASS_ZACAS, "d,t,0(s)",
MATCH_AMOCAS_Q|MASK_AQ, MASK_AMOCAS_Q|MASK_AQRL, match_opcode,
INSN_DREF|INSN_4_BYTE },