[RFC PATCH] RISC-V: Support Zacas extension.

Gianluca Guida gianluca@rivosinc.com
Fri May 12 03:44:43 GMT 2023


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

diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index bd0c7c81329..88285fe7fa2 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -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:
diff --git a/gas/testsuite/gas/riscv/zacas-32.d 
b/gas/testsuite/gas/riscv/zacas-32.d
new file mode 100644
index 00000000000..31b0e905861
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-32.d
@@ -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\)
diff --git a/gas/testsuite/gas/riscv/zacas-64.d 
b/gas/testsuite/gas/riscv/zacas-64.d
new file mode 100644
index 00000000000..37e93bce15e
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-64.d
@@ -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\)
diff --git a/gas/testsuite/gas/riscv/zacas.s 
b/gas/testsuite/gas/riscv/zacas.s
new file mode 100644
index 00000000000..c374ba149d1
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas.s
@@ -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
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 91e56c03191..1c51f340353 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -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)
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index e86a1bd0824..0ef85cd7516 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -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,
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 1c3d9b0903e..a9e604396e6 100644
--- 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 },
+{"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 },
+{"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},
-- 
2.34.1


More information about the Binutils mailing list