diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 682826c0e34..dd318144274 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -95,6 +95,7 @@ static const riscv_implied_info_t riscv_implied_info[] =
    }},
 
   {"zabha", "zaamo"},
+  {"zacas", "zaamo"},
 
   {"b", "zba"},
   {"b", "zbb"},
@@ -283,6 +284,7 @@ static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zaamo", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zalrsc", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zabha", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zacas", ISA_SPEC_CLASS_NONE, 1, 0},
 
   {"zba", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -856,6 +858,7 @@ riscv_subset_list::to_string (bool version_p) const
   bool skip_zifencei = false;
   bool skip_zaamo_zalrsc = false;
   bool skip_zabha = false;
+  bool skip_zacas = false;
   bool skip_zicsr = false;
   bool i2p0 = false;
 
@@ -891,6 +894,10 @@ riscv_subset_list::to_string (bool version_p) const
   /* Skip since binutils 2.42 and earlier don't recognize zabha.  */
   skip_zabha = true;
 #endif
+#ifndef HAVE_AS_MARCH_ZACAS
+  /* Skip since binutils 2.42 and earlier don't recognize zacas.  */
+  skip_zacas = true;
+#endif
 
   for (subset = m_head; subset != NULL; subset = subset->next)
     {
@@ -911,6 +918,9 @@ riscv_subset_list::to_string (bool version_p) const
       if (skip_zabha && subset->name == "zabha")
 	continue;
 
+      if (skip_zacas && subset->name == "zacas")
+	continue;
+
       /* For !version_p, we only separate extension with underline for
 	 multi-letter extension.  */
       if (!first &&
@@ -1590,6 +1600,7 @@ static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zaamo",   &gcc_options::x_riscv_za_subext, MASK_ZAAMO},
   {"zalrsc",  &gcc_options::x_riscv_za_subext, MASK_ZALRSC},
   {"zabha",   &gcc_options::x_riscv_za_subext, MASK_ZABHA},
+  {"zacas",   &gcc_options::x_riscv_za_subext, MASK_ZACAS},
 
   {"zba",    &gcc_options::x_riscv_zb_subext, MASK_ZBA},
   {"zbb",    &gcc_options::x_riscv_zb_subext, MASK_ZBB},
diff --git a/gcc/config.in b/gcc/config.in
index bc819005bd6..4468fa70fd3 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -641,6 +641,12 @@
 #endif
 
 
+/* Define if the assembler understands -march=rv*_zacas. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZACAS
+#endif
+
+
 /* Define if the assembler understands -march=rv*_zifencei. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_MARCH_ZIFENCEI
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
index 2ea514dd986..35e0f46b6bd 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -43,6 +43,7 @@ IMPLIED_EXT = {
 
   "a" : ["zaamo", "zalrsc"],
   "zabha" : ["zaamo"],
+  "zacas" : ["zaamo"],
 
   "f" : ["zicsr"],
   "b" : ["zba", "zbb", "zbs"],
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index edf1c6d85f3..2e340e5324f 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -264,6 +264,8 @@ Mask(ZALRSC) Var(riscv_za_subext)
 
 Mask(ZABHA) Var(riscv_za_subext)
 
+Mask(ZACAS) Var(riscv_za_subext)
+
 Mask(ZA64RS)  Var(riscv_za_subext)
 
 Mask(ZA128RS) Var(riscv_za_subext)
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index 0470e2ca457..2dd9fd1ea85 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -503,7 +503,7 @@
 
 ; Atomic CAS ops
 
-(define_insn "atomic_cas_value_strong<mode>"
+(define_insn "zalrsc_atomic_cas_value_strong<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
 	(match_operand:GPR 1 "memory_operand" "+A"))
    (set (match_dup 1)
@@ -530,16 +530,47 @@
   [(set_attr "type" "multi")
    (set (attr "length") (const_int 16))])
 
+;; Implement compare_exchange with a conservative leading fence when
+;; model_failure is seq_cst.
+;; This allows us to be compatible with the ISA manual Table A.6 and Table A.7
+;; (A6C and A7).
+;; More details: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/444
+(define_insn "zacas_atomic_cas_value_strong<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=&r")			    ;; val output
+	(match_operand:GPR 1 "memory_operand" "+A"))			    ;; memory
+   (set (match_dup 1)
+	(unspec_volatile:GPR [(match_operand:GPR 2 "register_operand" "0")  ;; expected val
+			      (match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; desired val
+			      (match_operand:SI 4 "const_int_operand")	    ;; mod_s
+			      (match_operand:SI 5 "const_int_operand")]	    ;; mod_f
+	 UNSPEC_COMPARE_AND_SWAP))]
+  "TARGET_ZACAS"
+  {
+    enum memmodel model_success = (enum memmodel) INTVAL (operands[4]);
+    enum memmodel model_failure = (enum memmodel) INTVAL (operands[5]);
+    /* Find the union of the two memory models so we can satisfy both success
+       and failure memory models.  */
+    operands[4] = GEN_INT (riscv_union_memmodels (model_success, model_failure));
+
+    if (model_failure == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+	     "amocas.<amo>%A4\t%0,%z3,%1";
+    else
+      return "amocas.<amo>%A4\t%0,%z3,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "atomic_compare_and_swap<mode>"
   [(match_operand:SI 0 "register_operand" "")   ;; bool output
    (match_operand:GPR 1 "register_operand" "")  ;; val output
    (match_operand:GPR 2 "memory_operand" "")    ;; memory
-   (match_operand:GPR 3 "reg_or_0_operand" "")  ;; expected value
+   (match_operand:GPR 3 "register_operand" "")  ;; expected value
    (match_operand:GPR 4 "reg_or_0_operand" "")  ;; desired value
    (match_operand:SI 5 "const_int_operand" "")  ;; is_weak
    (match_operand:SI 6 "const_int_operand" "")  ;; mod_s
    (match_operand:SI 7 "const_int_operand" "")] ;; mod_f
-  "TARGET_ZALRSC"
+  "TARGET_ZALRSC || TARGET_ZACAS"
 {
   if (word_mode != <MODE>mode && operands[3] != const0_rtx)
     {
@@ -550,9 +581,20 @@
       operands[3] = simplify_gen_subreg (<MODE>mode, tmp0, word_mode, 0);
     }
 
-  emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
-						operands[3], operands[4],
-						operands[6], operands[7]));
+  if (TARGET_ZACAS)
+    emit_insn (gen_zacas_atomic_cas_value_strong<mode> (operands[1],
+							operands[2],
+							operands[3],
+							operands[4],
+							operands[6],
+							operands[7]));
+  else
+    emit_insn (gen_zalrsc_atomic_cas_value_strong<mode> (operands[1],
+							 operands[2],
+							 operands[3],
+							 operands[4],
+							 operands[6],
+							 operands[7]));
 
   rtx compare = operands[1];
   if (operands[3] != const0_rtx)
@@ -573,20 +615,63 @@
   DONE;
 })
 
+;; Implement compare_exchange with a conservative leading fence when
+;; model_failure is seq_cst.
+;; This allows us to be compatible with the ISA manual Table A.6 and Table A.7
+;; (A6C and A7).
+;; More details: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/444
+(define_insn "zacas_atomic_cas_value_strong<mode>"
+  [(set (match_operand:SHORT 0 "register_operand" "=&r")			;; val output
+	(match_operand:SHORT 1 "memory_operand" "+A"))				;; memory
+   (set (match_dup 1)
+	(unspec_volatile:SHORT [(match_operand:SHORT 2 "register_operand" "0")  ;; expected_val
+				(match_operand:SHORT 3 "register_operand" "rJ") ;; desired_val
+				(match_operand:SI 4 "const_int_operand")	;; mod_s
+				(match_operand:SI 5 "const_int_operand")]	;; mod_f
+	 UNSPEC_COMPARE_AND_SWAP))]
+  "TARGET_ZACAS && TARGET_ZABHA"
+  {
+    enum memmodel model_success = (enum memmodel) INTVAL (operands[4]);
+    enum memmodel model_failure = (enum memmodel) INTVAL (operands[5]);
+    /* Find the union of the two memory models so we can satisfy both success
+       and failure memory models.  */
+    operands[4] = GEN_INT (riscv_union_memmodels (model_success, model_failure));
+
+    if (model_failure == MEMMODEL_SEQ_CST)
+      return "fence\trw,rw\;"
+	     "amocas.<amobh>%A4\t%0,%z3,%1";
+    else
+      return "amocas.<amobh>%A4\t%0,%z3,%1";
+  }
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "atomic_compare_and_swap<mode>"
   [(match_operand:SI 0 "register_operand")    ;; bool output
    (match_operand:SHORT 1 "register_operand") ;; val output
    (match_operand:SHORT 2 "memory_operand")   ;; memory
-   (match_operand:SHORT 3 "reg_or_0_operand") ;; expected value
+   (match_operand:SHORT 3 "register_operand") ;; expected value
    (match_operand:SHORT 4 "reg_or_0_operand") ;; desired value
    (match_operand:SI 5 "const_int_operand")   ;; is_weak
    (match_operand:SI 6 "const_int_operand")   ;; mod_s
    (match_operand:SI 7 "const_int_operand")]  ;; mod_f
-  "TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
+  "(TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC) || (TARGET_ZACAS && TARGET_ZABHA)"
 {
-  emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
-						operands[3], operands[4],
-						operands[6], operands[7]));
+
+  if (TARGET_ZACAS && TARGET_ZABHA)
+    emit_insn (gen_zacas_atomic_cas_value_strong<mode> (operands[1],
+							operands[2],
+							operands[3],
+							operands[4],
+							operands[6],
+							operands[7]));
+  else
+    emit_insn (gen_zalrsc_atomic_cas_value_strong<mode> (operands[1],
+							 operands[2],
+							 operands[3],
+							 operands[4],
+							 operands[6],
+							 operands[7]));
 
   rtx val = gen_reg_rtx (SImode);
   if (operands[1] != const0_rtx)
@@ -619,7 +704,7 @@
   DONE;
 })
 
-(define_expand "atomic_cas_value_strong<mode>"
+(define_expand "zalrsc_atomic_cas_value_strong<mode>"
   [(match_operand:SHORT 0 "register_operand") ;; val output
    (match_operand:SHORT 1 "memory_operand")   ;; memory
    (match_operand:SHORT 2 "reg_or_0_operand") ;; expected value
diff --git a/gcc/configure b/gcc/configure
index 01acca7fb5c..24fe92d55d3 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -30913,6 +30913,37 @@ if test $gcc_cv_as_riscv_march_zabha = yes; then
 
 $as_echo "#define HAVE_AS_MARCH_ZABHA 1" >>confdefs.h
 
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zacas support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zacas support... " >&6; }
+if ${gcc_cv_as_riscv_march_zacas+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_march_zacas=no
+  if test x$gcc_cv_as != x; then
+    $as_echo '' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags -march=rv32i_zacas -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+	gcc_cv_as_riscv_march_zacas=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_riscv_march_zacas" >&5
+$as_echo "$gcc_cv_as_riscv_march_zacas" >&6; }
+if test $gcc_cv_as_riscv_march_zacas = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZACAS 1" >>confdefs.h
+
 fi
 
     ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 3f20c107b6a..28de7aa175a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5466,6 +5466,11 @@ configured with --enable-newlib-nano-formatted-io.])
       [-march=rv32i_zabha],,,
       [AC_DEFINE(HAVE_AS_MARCH_ZABHA, 1,
 		 [Define if the assembler understands -march=rv*_zabha.])])
+    gcc_GAS_CHECK_FEATURE([-march=rv32i_zacas support],
+      gcc_cv_as_riscv_march_zacas,
+      [-march=rv32i_zacas],,,
+      [AC_DEFINE(HAVE_AS_MARCH_ZACAS, 1,
+		 [Define if the assembler understands -march=rv*_zacas.])])
     ;;
     loongarch*-*-*)
     gcc_GAS_CHECK_FEATURE([.dtprelword support],
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 66c4206bfc2..d5c48e67b71 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2530,6 +2530,9 @@ Test target architecture has support for the zaamo extension.
 @item riscv_zabha
 Test target architecture has support for the zabha extension.
 
+@item riscv_zacas
+Test target architecture has support for the zacas extension.
+
 @item riscv_zalrsc
 Test target architecture has support for the zalrsc extension.
 
@@ -3298,6 +3301,9 @@ Add the zaamo extension to the -march string on RISC-V targets.
 @item riscv_zabha
 Add the zabha extension to the -march string on RISC-V targets.
 
+@item riscv_zacas
+Add the zacas extension to the -march string on RISC-V targets.
+
 @item riscv_zalrsc
 Add the zalrsc extension to the -march string on RISC-V targets.
 
@@ -3345,6 +3351,10 @@ extension is present downgrade it to zalrsc.
 Remove the zabha extension and implied zaamo extension from the -march string
 on RISC-V.
 
+@item riscv_zacas
+Remove the zacas extension and implied zaamo extension from the -march string
+on RISC-V.
+
 @item riscv_zalrsc
 Remove the zalrsc extension from the -march string on RISC-V. If the 'A'
 extension is present downgrade it to zaamo.
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c
new file mode 100644
index 00000000000..a06e195c6d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-zacas-preferred-over-zalrsc.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* Ensure that AMO ops are emitted for subword cas when both zalrsc and
+   zacas/zabha are enabled.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zalrsc } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c
new file mode 100644
index 00000000000..c7d6e7c578b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zabha.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Ensure subword zacas is not emitted unless both zacas and zabha are
+   present.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_zabha } */
+/* { dg-remove-options riscv_zalrsc } */
+/* { dg-final { scan-assembler "\tcall\t" } } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-not "amocas\.b\t" } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c
new file mode 100644
index 00000000000..d0cf14432fe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-char-requires-zacas.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* Ensure subword zacas is not emitted unless both zacas and zabha are
+   present.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_zacas } */
+/* { dg-remove-options riscv_zalrsc } */
+/* { dg-final { scan-assembler "\tcall\t" } } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-not "amocas\.b\t" } } */
+
+
+void atomic_compare_exchange_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-preferred-over-zalrsc.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-preferred-over-zalrsc.c
new file mode 100644
index 00000000000..9a995cca37f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-preferred-over-zalrsc.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* Ensure that AMO ops are emitted for subword cas when both zalrsc and
+   zacas/zabha are enabled.  */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zalrsc } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
new file mode 100644
index 00000000000..b76385b4d26
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acq-rel.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
new file mode 100644
index 00000000000..62ecf7b5fff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-acquire.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aq\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
new file mode 100644
index 00000000000..21c960c893b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-relaxed.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
new file mode 100644
index 00000000000..6b4083376ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-release.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.rl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
new file mode 100644
index 00000000000..289bdf44e9f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-char-seq-cst.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping-no-fence.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping-no-fence.c
new file mode 100644
index 00000000000..99fd7577a48
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping-no-fence.c
@@ -0,0 +1,30 @@
+/*
+** Verify that atomic op mappings match the PSABI doc's recommended mapping.
+** compare_exchange ops without a seq_cst failure ordering do *not* need a
+** leading fence.
+*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tfence" } } */
+
+void atomic_compare_exchange_weak_int_seq_cst_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_int_seq_cst_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping.cc b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping.cc
new file mode 100644
index 00000000000..c8d81299197
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-compatability-mapping.cc
@@ -0,0 +1,58 @@
+/*
+** Verify that atomic op mappings match the PSABI doc's recommended mapping.
+** compare_exchange ops with seq_cst failure ordering need a leading fence
+** to remain compatible with Table A.6 (A6C).
+*/
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c++17" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_compare_exchange_weak_int_relaxed_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\.aqrl\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_weak_int_relaxed_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_weak_int_seq_cst_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\.aqrl\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_weak_int_seq_cst_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_strong_int_relaxed_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\.aqrl\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_strong_int_relaxed_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_strong_int_seq_cst_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\.aqrl\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_strong_int_seq_cst_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c
new file mode 100644
index 00000000000..1b55c934962
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acq-rel.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c
new file mode 100644
index 00000000000..8182360f244
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-acquire.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aq\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c
new file mode 100644
index 00000000000..fb2a7b4f55a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-relaxed.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c
new file mode 100644
index 00000000000..756f5cbe7d1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-release.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.rl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c
new file mode 100644
index 00000000000..1c5b4ac0e2f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-int-seq-cst.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
new file mode 100644
index 00000000000..2987eb3615d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acq-rel.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
new file mode 100644
index 00000000000..505791090be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-acquire.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aq\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
new file mode 100644
index 00000000000..a85694e26c8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-relaxed.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
new file mode 100644
index 00000000000..e8e9aae0265
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-release.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.rl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
new file mode 100644
index 00000000000..d676d378e06
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-rvwmo-compare-exchange-short-seq-cst.c
@@ -0,0 +1,20 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\.aqrl\t" 2 } } */
+
+
+void atomic_compare_exchange_weak_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c
new file mode 100644
index 00000000000..e219bd14b15
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char-seq-cst.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 2 } } */
+
+void atomic_compare_exchange_weak_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_char_seq_cst (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c
new file mode 100644
index 00000000000..183dc4020c7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-char.c
@@ -0,0 +1,49 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.b\t" 8 } } */
+
+void atomic_compare_exchange_weak_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_relaxed (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_char_acquire (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_weak_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_release (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_char_acq_rel (char *bar, char *baz, char qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping-no-fence.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping-no-fence.c
new file mode 100644
index 00000000000..2712eff5107
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping-no-fence.c
@@ -0,0 +1,30 @@
+/*
+** Verify that atomic op mappings match the PSABI doc's recommended mapping.
+** compare_exchange ops without a seq_cst failure ordering do *not* need a
+** leading fence.
+*/
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tfence" } } */
+
+void atomic_compare_exchange_weak_int_seq_cst_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_int_seq_cst_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_ACQUIRE);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping.cc b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping.cc
new file mode 100644
index 00000000000..560172bfbed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-compatability-mapping.cc
@@ -0,0 +1,58 @@
+/*
+** Verify that atomic op mappings match the PSABI doc's recommended mapping.
+** compare_exchange ops with seq_cst failure ordering need a leading fence
+** to remain compatible with Table A.6 (A6C).
+*/
+/* { dg-do compile } */
+/* { dg-options "-O3 -std=c++17" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_compare_exchange_weak_int_relaxed_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_weak_int_relaxed_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_weak_int_seq_cst_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_weak_int_seq_cst_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_strong_int_relaxed_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_strong_int_relaxed_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_SEQ_CST);
+}
+
+/*
+** atomic_compare_exchange_strong_int_seq_cst_seq_cst:
+**	...
+**	fence\trw,rw
+**	amoadd\.w\t[atx][0-9]+,a2,0\(a0\)
+**	...
+*/
+void atomic_compare_exchange_strong_int_seq_cst_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c
new file mode 100644
index 00000000000..1ee6cc20218
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int-seq-cst.c
@@ -0,0 +1,18 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 2 } } */
+
+void atomic_compare_exchange_weak_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_int_seq_cst (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c
new file mode 100644
index 00000000000..2c332623a95
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-int.c
@@ -0,0 +1,48 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.w\t" 8 } } */
+
+void atomic_compare_exchange_weak_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_relaxed (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_int_acquire (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_weak_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_release (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_int_acq_rel (int *bar, int *baz, int qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
new file mode 100644
index 00000000000..1938448183c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short-seq-cst.c
@@ -0,0 +1,19 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 2 } } */
+
+void atomic_compare_exchange_weak_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
+
+void atomic_compare_exchange_strong_short_seq_cst (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c
new file mode 100644
index 00000000000..69fe5ae3eac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zacas-ztso-compare-exchange-short.c
@@ -0,0 +1,49 @@
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-add-options riscv_zacas } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-final { scan-assembler-not "\tlr\.w" } } */
+/* { dg-final { scan-assembler-not "\tsc\.w" } } */
+/* { dg-final { scan-assembler-times "amocas\.h\t" 8 } } */
+
+void atomic_compare_exchange_weak_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_relaxed (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_strong_short_acquire (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE);
+}
+
+void atomic_compare_exchange_weak_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_release (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_weak_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 0, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
+
+void atomic_compare_exchange_strong_short_acq_rel (short *bar, short *baz, short qux)
+{
+  __atomic_compare_exchange_n(bar, baz, qux, 1, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
index 49eeda9cb33..9a5616f8916 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire-release.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* Mixed mappings need to be unioned.  */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
index b9e3adece8d..a24234855e9 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-acquire.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
index 11839d84f14..18f53c83a38 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-consume.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aq\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
index 852ec99df76..c7a43ecd323 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-relaxed.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
index 9c51a082d0b..302fca2ca17 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-release.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
index d985e2cef8b..e62002d267a 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst-relaxed.c
@@ -3,6 +3,7 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
index 6efd232ce21..c047d509aaf 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-compare-exchange-int-seq-cst.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
index 9761a955ede..496af8bfd7d 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire-release.c
@@ -3,6 +3,7 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
index 3303f8021e1..737e3eb3d68 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-acquire.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
index 7474e832bb1..51b3b5a8dc7 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-consume.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
index e43193820f2..9a41410a57b 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-relaxed.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
index a0d5872e1bd..ee778a760d1 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-release.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
index fc464ab1ff5..6fbe943b316 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst-relaxed.c
@@ -3,6 +3,7 @@
 /* Mixed mappings need to be unioned.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
 
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
index 152806cfde3..a361c10086d 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-compare-exchange-int-seq-cst.c
@@ -2,6 +2,7 @@
 /* Verify that compare exchange mappings match the PSABI doc's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zacas } */
 /* { dg-final { scan-assembler-times "lr.w.aqrl\t" 1 } } */
 /* { dg-final { scan-assembler-times "sc.w.rl\t" 1 } } */
 
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index d368251ef9a..f8e5f5f36d0 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1922,6 +1922,17 @@ proc check_effective_target_riscv_zabha { } {
     }]
 }
 
+# Return 1 if the target arch supports the atomic CAS extension, 0 otherwise.
+# Cache the result.
+
+proc check_effective_target_riscv_zacas { } {
+    return [check_no_compiler_messages riscv_ext_zacas assembly {
+       #ifndef __riscv_zacas
+       #error "Not __riscv_zacas"
+       #endif
+    }]
+}
+
 # Return 1 if the target arch supports the double precision floating point
 # extension, 0 otherwise.  Cache the result.
 
@@ -2140,7 +2151,7 @@ proc check_effective_target_riscv_v_misalign_ok { } {
 proc riscv_get_arch { } {
     set gcc_march ""
     # ??? do we neeed to add more extensions to the list below?
-    foreach ext { i m a f d q c b v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh ztso zaamo zalrsc zabha } {
+    foreach ext { i m a f d q c b v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh ztso zaamo zalrsc zabha zacas } {
 	if { [check_no_compiler_messages  riscv_ext_$ext assembly [string map [list DEF __riscv_$ext] {
 		#ifndef DEF
 		#error "Not DEF"
@@ -2308,6 +2319,9 @@ proc remove_options_for_riscv_zaamo { flags } {
     # If zabha is set then zaamo will be implied. We need to remove zabha
     # as well.
     set modified_flags [remove_options_for_riscv_z_ext zabha $modified_flags]
+    # If zacas is set then zaamo will be implied. We need to remove zacas
+    # as well.
+    set modified_flags [remove_options_for_riscv_z_ext zacas $modified_flags]
     # If 'a' is set then zaamo will be implied. We need to downgrade instances
     # of 'a' to 'zalrsc'
     set no_a_flags [remove_options_for_riscv_a_only $modified_flags]
@@ -2343,6 +2357,15 @@ proc remove_options_for_riscv_zabha { flags } {
     return [remove_options_for_riscv_z_ext zabha $modified_flags]
 }
 
+proc add_options_for_riscv_zacas { flags } {
+    return [add_options_for_riscv_z_ext zacas $flags]
+}
+
+proc remove_options_for_riscv_zacas { flags } {
+    set modified_flags [remove_options_for_riscv_zaamo $flags]
+    return [remove_options_for_riscv_z_ext zacas $modified_flags]
+}
+
 proc add_options_for_riscv_zfh { flags } {
     return [add_options_for_riscv_z_ext zfh $flags]
 }
