diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index ee96608358e..46b91087fc6 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -1171,6 +1171,7 @@ static struct riscv_implicit_subset riscv_implicit_subsets[] =
   {"zvksg", "zvkg",	check_implicit_always},
   {"zvksc", "zvks",	check_implicit_always},
   {"zvksc", "zvbc",	check_implicit_always},
+  {"zacas", "a",	check_implicit_always},
   {"zcf", "zca",	check_implicit_always},
   {"zcd", "zca",	check_implicit_always},
   {"zcb", "zca",	check_implicit_always},
@@ -1248,6 +1249,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] =
   {"zifencei",		ISA_SPEC_CLASS_20190608,	2, 0,  0 },
   {"zihintpause",	ISA_SPEC_CLASS_DRAFT,		2, 0,  0 },
   {"zmmul",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
+  {"zacas",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zawrs",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
   {"zfa",		ISA_SPEC_CLASS_DRAFT,		0, 1,  0 },
   {"zfh",		ISA_SPEC_CLASS_DRAFT,		1, 0,  0 },
@@ -2382,6 +2384,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps,
       return riscv_subset_supports (rps, "zmmul");
     case INSN_CLASS_A:
       return riscv_subset_supports (rps, "a");
+    case INSN_CLASS_ZACAS:
+      return riscv_subset_supports (rps, "zacas");
     case INSN_CLASS_ZAWRS:
       return riscv_subset_supports (rps, "zawrs");
     case INSN_CLASS_F:
@@ -2575,6 +2579,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps,
       return _ ("m' or `zmmul");
     case INSN_CLASS_A:
       return "a";
+    case INSN_CLASS_ZACAS:
+      return "zacas";
     case INSN_CLASS_ZAWRS:
       return "zawrs";
     case INSN_CLASS_F:
diff --git a/gas/testsuite/gas/riscv/zacas.d b/gas/testsuite/gas/riscv/zacas.d
new file mode 100644
index 00000000000..2f65a9bcbe4
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas.d
@@ -0,0 +1,20 @@
+#as: -march=rv64i_zacas
+#objdump: -d
+
+.*:[ 	]+file format .*
+
+Disassembly of section .text:
+
+0+000 <target>:
+[ 	]+[0-9a-f]+:[ 	]+28e5262f[ 	]+amocas.w[ 	]+a2,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ce5262f[ 	]+amocas.w.aq[ 	]+a2,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ae5262f[ 	]+amocas.w.rl[ 	]+a2,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ee5262f[ 	]+amocas.w.aqrl[ 	]+a2,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+28e5372f[ 	]+amocas.d[ 	]+a4,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ce5372f[ 	]+amocas.d.aq[ 	]+a4,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ae5372f[ 	]+amocas.d.rl[ 	]+a4,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ee5372f[ 	]+amocas.d.aqrl[ 	]+a4,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+28e5482f[ 	]+amocas.q[ 	]+a6,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ce5482f[ 	]+amocas.q.aq[ 	]+a6,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ae5482f[ 	]+amocas.q.rl[ 	]+a6,a4,\(a0\)
+[ 	]+[0-9a-f]+:[ 	]+2ee5482f[ 	]+amocas.q.aqrl[ 	]+a6,a4,\(a0\)
diff --git a/gas/testsuite/gas/riscv/zacas.s b/gas/testsuite/gas/riscv/zacas.s
new file mode 100644
index 00000000000..441284455a2
--- /dev/null
+++ b/gas/testsuite/gas/riscv/zacas.s
@@ -0,0 +1,13 @@
+target:
+	amocas.w a2, a4, (a0)
+	amocas.w.aq a2, a4, (a0)
+	amocas.w.rl a2, a4, (a0)
+	amocas.w.aqrl a2, a4, (a0)
+	amocas.d a4, a4, (a0)
+	amocas.d.aq a4, a4, (a0)
+	amocas.d.rl a4, a4, (a0)
+	amocas.d.aqrl a4, a4, (a0)
+	amocas.q a6, a4, (a0)
+	amocas.q.aq a6, a4, (a0)
+	amocas.q.rl a6, a4, (a0)
+	amocas.q.aqrl a6, a4, (a0)
diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h
index 53f5f200508..750e31a337d 100644
--- a/include/opcode/riscv-opc.h
+++ b/include/opcode/riscv-opc.h
@@ -2298,6 +2298,13 @@
 #define MASK_CZERO_EQZ 0xfe00707f
 #define MATCH_CZERO_NEZ 0xe007033
 #define MASK_CZERO_NEZ 0xfe00707f
+/* Zacas intructions.  */
+#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 intructions.  */
 #define MATCH_WRS_NTO 0x00d00073
 #define MASK_WRS_NTO 0xffffffff
diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h
index 808f3657303..e06f9819d6e 100644
--- a/include/opcode/riscv.h
+++ b/include/opcode/riscv.h
@@ -394,6 +394,7 @@ enum riscv_insn_class
   INSN_CLASS_ZIFENCEI,
   INSN_CLASS_ZIHINTPAUSE,
   INSN_CLASS_ZMMUL,
+  INSN_CLASS_ZACAS,
   INSN_CLASS_ZAWRS,
   INSN_CLASS_F_INX,
   INSN_CLASS_D_INX,
diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
index 6a854736fec..ef57850d4e6 100644
--- a/opcodes/riscv-opc.c
+++ b/opcodes/riscv-opc.c
@@ -633,6 +633,20 @@ const struct riscv_opcode riscv_opcodes[] =
 {"amomin.d.aqrl",  64, INSN_CLASS_A, "d,t,0(s)", MATCH_AMOMIN_D|MASK_AQRL, MASK_AMOMIN_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_BYTE },
 {"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 },
 
+/* Atomic compare-and-swap 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.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.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.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",        0, INSN_CLASS_ZACAS, "d,t,0(s)",   MATCH_AMOCAS_D, MASK_AMOCAS_D|MASK_AQRL, match_opcode, INSN_DREF|INSN_8_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_8_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_8_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_8_BYTE },
+{"amocas.q",       64, INSN_CLASS_ZACAS, "d,t,0(s)",   MATCH_AMOCAS_Q, MASK_AMOCAS_Q|MASK_AQRL, match_opcode, INSN_DREF|INSN_16_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_16_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_16_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_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 },
