diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 7f453246449..6d5c4f2efbd 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1162,6 +1162,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}
 };
 
@@ -1272,6 +1273,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}
 };
 
@@ -2415,6 +2417,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:
@@ -2575,6 +2579,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-fail-32.d b/gas/testsuite/gas/riscv/zacas-fail-32.d
new file mode 100644
index 00000000000..f9cee1cdae7
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-fail-32.d
@@ -0,0 +1,3 @@
+#as: -march=rv32ia_zacas
+#source: zacas-fail.s
+#error_output: zacas-fail-32.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/riscv/zacas-fail-32.l b/gas/testsuite/gas/riscv/zacas-fail-32.l
new file mode 100644
index 00000000000..270e033629a
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-fail-32.l
@@ -0,0 +1,17 @@
+.*: Assembler messages:
+.*:1: Error: illegal operands `amocas.d a1,a0,\(a0\)'
+.*:2: Error: illegal operands `amocas.d a0,a1,\(a0\)'
+.*:3: Error: illegal operands `amocas.d.aq a1,a0,\(a0\)'
+.*:4: Error: illegal operands `amocas.d.aq a0,a1,\(a0\)'
+.*:5: Error: illegal operands `amocas.d.rl a1,a0,\(a0\)'
+.*:6: Error: illegal operands `amocas.d.rl a0,a1,\(a0\)'
+.*:7: Error: illegal operands `amocas.d.aqrl a1,a0,\(a0\)'
+.*:8: Error: illegal operands `amocas.d.aqrl a0,a1,\(a0\)'
+.*:9: Error: unrecognized opcode `amocas.q a1,a0,\(a0\)'
+.*:10: Error: unrecognized opcode `amocas.q a0,a1,\(a0\)'
+.*:11: Error: unrecognized opcode `amocas.q.aq a1,a0,\(a0\)'
+.*:12: Error: unrecognized opcode `amocas.q.aq a0,a1,\(a0\)'
+.*:13: Error: unrecognized opcode `amocas.q.rl a1,a0,\(a0\)'
+.*:14: Error: unrecognized opcode `amocas.q.rl a0,a1,\(a0\)'
+.*:15: Error: unrecognized opcode `amocas.q.aqrl a1,a0,\(a0\)'
+.*:16: Error: unrecognized opcode `amocas.q.aqrl a0,a1,\(a0\)'
diff --git a/gas/testsuite/gas/riscv/zacas-fail-64.d b/gas/testsuite/gas/riscv/zacas-fail-64.d
new file mode 100644
index 00000000000..d8413e0a457
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-fail-64.d
@@ -0,0 +1,3 @@
+#as: -march=rv64ia_zacas
+#source: zacas-fail.s
+#error_output: zacas-fail-64.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/riscv/zacas-fail-64.l b/gas/testsuite/gas/riscv/zacas-fail-64.l
new file mode 100644
index 00000000000..2b44c2470d6
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-fail-64.l
@@ -0,0 +1,9 @@
+.*: Assembler messages:
+.*:9: Error: illegal operands `amocas.q a1,a0,\(a0\)'
+.*:10: Error: illegal operands `amocas.q a0,a1,\(a0\)'
+.*:11: Error: illegal operands `amocas.q.aq a1,a0,\(a0\)'
+.*:12: Error: illegal operands `amocas.q.aq a0,a1,\(a0\)'
+.*:13: Error: illegal operands `amocas.q.rl a1,a0,\(a0\)'
+.*:14: Error: illegal operands `amocas.q.rl a0,a1,\(a0\)'
+.*:15: Error: illegal operands `amocas.q.aqrl a1,a0,\(a0\)'
+.*:16: Error: illegal operands `amocas.q.aqrl a0,a1,\(a0\)'
diff --git a/gas/testsuite/gas/riscv/zacas-fail.s b/gas/testsuite/gas/riscv/zacas-fail.s
new file mode 100644
index 00000000000..b3fd184e32d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas-fail.s
@@ -0,0 +1,16 @@
+	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)
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..0e7b8b3c446 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -165,6 +165,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)
 {
@@ -1053,6 +1061,24 @@ 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",        32, INSN_CLASS_ZACAS, "d,t,0(s)", MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_rs2_rd_even, INSN_DREF|INSN_4_BYTE },
+{"amocas.d",        64, 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_rs2_rd_even, 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",     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_4_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_4_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_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",     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_4_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_4_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_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",   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_4_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_4_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_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},
