diff mbox series

RISC-V: Add support for Zabha extension

Message ID 20240625220655.2363638-1-patrick@rivosinc.com
State New
Headers show
Series RISC-V: Add support for Zabha extension | expand

Commit Message

Patrick O'Neill June 25, 2024, 10:06 p.m. UTC
From: Gianluca Guida <gianluca@rivosinc.com>

The Zabha extension adds support for subword Zaamo ops.

Extension: https://github.com/riscv/riscv-zabha.git
Ratification: https://jira.riscv.org/browse/RVS-1685

gcc/ChangeLog:

	* common/config/riscv/riscv-common.cc
	(riscv_subset_list::to_string): Skip zabha when not supported by
	the assembler.
	* config.in: Regenerate.
	* config/riscv/arch-canonicalize: Make zabha imply zaamo.
	* config/riscv/iterators.md (amobh): Add iterator for amo
	byte/halfword.
	* config/riscv/riscv.opt: Add zabha.
	* config/riscv/sync.md (atomic_<atomic_optab><mode>): Add
	subword atomic op pattern.
	(zabha_atomic_fetch_<atomic_optab><mode>): Add subword
	atomic_fetch op pattern.
	(lrsc_atomic_fetch_<atomic_optab><mode>): Prefer zabha over lrsc
	for subword atomic ops.
	(zabha_atomic_exchange<mode>): Add subword atomic exchange
	pattern.
	(lrsc_atomic_exchange<mode>): Prefer zabha over lrsc for subword
	atomic exchange ops.
	* configure: Regenerate.
	* configure.ac: Add zabha assembler check.
	* doc/sourcebuild.texi: Add zabha documentation.

gcc/testsuite/ChangeLog:

	* lib/target-supports.exp: Add zabha testsuite infra support.
	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-1.c: Remove zabha
	to continue to test the lr/sc subword patterns.
	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-2.c: Ditto.
	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-3.c: Ditto.
	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-4.c: Ditto.
	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-5.c: Ditto.
	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-1.c: Ditto.
	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-2.c: Ditto.
	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-3.c: Ditto.
	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-4.c: Ditto.
	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-5.c: Ditto.
	* gcc.target/riscv/amo/inline-atomics-1.c: Ditto.
	* gcc.target/riscv/amo/inline-atomics-2.c: Ditto.
	* gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c: New test.
	* gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c: New test.
	* gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c: New test.
	* gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c: New test.
	* gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c: New test.
	* gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c: New test.
	* gcc.target/riscv/amo/zabha-ztso-amo-add-char.c: New test.
	* gcc.target/riscv/amo/zabha-ztso-amo-add-short.c: New test.

Co-Authored-By: Patrick O'Neill <patrick@rivosinc.com>
---
Gianluca Guida created the initial patch. Rebased and added more
testcases/docs/etc.

This will trivially conflict with the testsuite cleanup [1] I sent but
I'll rebase as needed.

Tested using amo.exp with rv64gc_zalrsc, rv64id_zaamo, rv64id_zalrsc,
rv64id_zabha (using tip-of-tree qemu w/ zabha patches [2] applied for
execution tests).
Relying on precommit for full testing.

[1] https://inbox.sourceware.org/gcc-patches/42eae510-1804-40d2-8b6c-6f4c9c170688@gmail.com/T/#t
[2] https://lore.kernel.org/all/fed99165-58da-458c-b68f-a9717fc15034@linux.alibaba.com/T/
---
 gcc/common/config/riscv/riscv-common.cc       | 12 +++
 gcc/config.in                                 |  6 ++
 gcc/config/riscv/arch-canonicalize            |  3 +
 gcc/config/riscv/iterators.md                 |  3 +
 gcc/config/riscv/riscv.opt                    |  2 +
 gcc/config/riscv/sync.md                      | 81 ++++++++++++++++++-
 gcc/configure                                 | 31 +++++++
 gcc/configure.ac                              |  5 ++
 gcc/doc/sourcebuild.texi                      | 12 ++-
 .../amo/amo-table-a-6-subword-amo-add-1.c     |  1 +
 .../amo/amo-table-a-6-subword-amo-add-2.c     |  1 +
 .../amo/amo-table-a-6-subword-amo-add-3.c     |  1 +
 .../amo/amo-table-a-6-subword-amo-add-4.c     |  1 +
 .../amo/amo-table-a-6-subword-amo-add-5.c     |  1 +
 .../amo/amo-table-ztso-subword-amo-add-1.c    |  1 +
 .../amo/amo-table-ztso-subword-amo-add-2.c    |  1 +
 .../amo/amo-table-ztso-subword-amo-add-3.c    |  1 +
 .../amo/amo-table-ztso-subword-amo-add-4.c    |  1 +
 .../amo/amo-table-ztso-subword-amo-add-5.c    |  1 +
 .../gcc.target/riscv/amo/inline-atomics-1.c   |  1 +
 .../gcc.target/riscv/amo/inline-atomics-2.c   |  1 +
 .../riscv/amo/zabha-all-amo-ops-char-run.c    |  5 ++
 .../riscv/amo/zabha-all-amo-ops-short-run.c   |  5 ++
 .../riscv/amo/zabha-rvwmo-all-amo-ops-char.c  | 23 ++++++
 .../riscv/amo/zabha-rvwmo-all-amo-ops-short.c | 23 ++++++
 .../riscv/amo/zabha-rvwmo-amo-add-char.c      | 57 +++++++++++++
 .../riscv/amo/zabha-rvwmo-amo-add-short.c     | 57 +++++++++++++
 .../riscv/amo/zabha-ztso-amo-add-char.c       | 57 +++++++++++++
 .../riscv/amo/zabha-ztso-amo-add-short.c      | 57 +++++++++++++
 gcc/testsuite/lib/target-supports.exp         | 33 ++++++--
 30 files changed, 476 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-char.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-short.c

--
2.34.1

Comments

Andrea Parri June 26, 2024, 3:50 p.m. UTC | #1
> Tested using amo.exp with rv64gc_zalrsc, rv64id_zaamo, rv64id_zalrsc,
> rv64id_zabha (using tip-of-tree qemu w/ zabha patches [2] applied for
> execution tests).

My interpretation of the Zabha specification, in particular of "The Zabha
extension depends upon the Zaamo standard extension", is that rv64id_zabha
should result in a dependency violation (some compiler warning).

The changes at stake seem instead to make the Zabha extension "select" the
Zaamo extension; IOW, these changes seem to make rv64id_zabha an alias of
rv64id_zaamo_zabha: I am wondering whether this was intentional?

  Andrea
Patrick O'Neill June 26, 2024, 4:12 p.m. UTC | #2
On 6/26/24 08:50, Andrea Parri wrote:
>> Tested using amo.exp with rv64gc_zalrsc, rv64id_zaamo, rv64id_zalrsc,
>> rv64id_zabha (using tip-of-tree qemu w/ zabha patches [2] applied for
>> execution tests).
> My interpretation of the Zabha specification, in particular of "The Zabha
> extension depends upon the Zaamo standard extension", is that rv64id_zabha
> should result in a dependency violation (some compiler warning).
>
> The changes at stake seem instead to make the Zabha extension "select" the
> Zaamo extension; IOW, these changes seem to make rv64id_zabha an alias of
> rv64id_zaamo_zabha: I am wondering whether this was intentional?

Hi Andrea,

Thanks for highlighting this.

This is intentional - my understanding is that GCC adds extensions if 
the specified extensions depend upon them.

For example in the Zvfh spec: "The Zvfh extension depends on the Zve32f 
and Zfhmin extensions."

In riscv_implied_info zve32f and zfhmin are implied by zvfh: {"zvfh", 
"zve32f"}, {"zvfh", "zfhmin"}

This can be seen here: https://godbolt.org/z/63518Wrcj in the .attribute 
arch string: ...zfhmin1p0_zve32f1p0_...

Side tangent: oddly enough it looks like zvfh does not require/imply the 
v extension?

Patrick

>    Andrea
Andrea Parri June 26, 2024, 4:33 p.m. UTC | #3
> > My interpretation of the Zabha specification, in particular of "The Zabha
> > extension depends upon the Zaamo standard extension", is that rv64id_zabha
> > should result in a dependency violation (some compiler warning).
> > 
> > The changes at stake seem instead to make the Zabha extension "select" the
> > Zaamo extension; IOW, these changes seem to make rv64id_zabha an alias of
> > rv64id_zaamo_zabha: I am wondering whether this was intentional?
> 
> Hi Andrea,
> 
> Thanks for highlighting this.
> 
> This is intentional - my understanding is that GCC adds extensions if the
> specified extensions depend upon them.

Thanks for the clarification.

For the patch at stake,

Tested-by: Andrea Parri <andrea@rivosinc.com>

  Andrea
Palmer Dabbelt June 26, 2024, 4:45 p.m. UTC | #4
On Wed, 26 Jun 2024 08:50:57 PDT (-0700), Andrea Parri wrote:
>> Tested using amo.exp with rv64gc_zalrsc, rv64id_zaamo, rv64id_zalrsc,
>> rv64id_zabha (using tip-of-tree qemu w/ zabha patches [2] applied for
>> execution tests).
>
> My interpretation of the Zabha specification, in particular of "The Zabha
> extension depends upon the Zaamo standard extension", is that rv64id_zabha
> should result in a dependency violation (some compiler warning).
>
> The changes at stake seem instead to make the Zabha extension "select" the
> Zaamo extension; IOW, these changes seem to make rv64id_zabha an alias of
> rv64id_zaamo_zabha: I am wondering whether this was intentional?

I think your interpretation of "depends on" is reasonable, but it's not 
the way we've handled it for other extension dependencies.  For the 
others we're treating "depends on" the way this code does, ie enabling 
the dependant extensions implicitly.  IIRC that's how the RISC-V specs 
want it to be.

That said, we do call it "implied" in the sources because that's really 
the right word for it.  So we should probably add something to the docs 
that describes how/why things are this way, as I don't think it's the 
first time someone's been confused.

Maybe just something like

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 23d90db2925..429275d56df 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -31037,6 +31037,10 @@ If both @option{-march} and @option{-mcpu=} are not specified, the default for
 this argument is system dependent, users who want a specific architecture
 extensions should specify one explicitly.

+When the RISC-V specifications define an extension as depending on other
+extensions, GCC will implicitly add the dependant extensions to the enabled
+extension set if they weren't added explicitly.
+
 @opindex mcpu
 @item -mcpu=@var{processor-string}
 Use architecture of and optimize the output for the given processor, specified

would do it?

>
>   Andrea
Andrea Parri June 26, 2024, 5:04 p.m. UTC | #5
> I think your interpretation of "depends on" is reasonable, but it's not the
> way we've handled it for other extension dependencies.  For the others we're
> treating "depends on" the way this code does, ie enabling the dependant
> extensions implicitly.  IIRC that's how the RISC-V specs want it to be.
> 
> That said, we do call it "implied" in the sources because that's really the
> right word for it.  So we should probably add something to the docs that
> describes how/why things are this way, as I don't think it's the first time
> someone's been confused.
> 
> Maybe just something like
> 
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 23d90db2925..429275d56df 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -31037,6 +31037,10 @@ If both @option{-march} and @option{-mcpu=} are not specified, the default for
> this argument is system dependent, users who want a specific architecture
> extensions should specify one explicitly.
> 
> +When the RISC-V specifications define an extension as depending on other
> +extensions, GCC will implicitly add the dependant extensions to the enabled
> +extension set if they weren't added explicitly.
> +
> @opindex mcpu
> @item -mcpu=@var{processor-string}
> Use architecture of and optimize the output for the given processor, specified
> 
> would do it?

Makes sense to me.  Thanks!

  Andrea
Jeff Law July 3, 2024, 12:39 a.m. UTC | #6
On 6/25/24 4:06 PM, Patrick O'Neill wrote:
> From: Gianluca Guida <gianluca@rivosinc.com>
> 
> The Zabha extension adds support for subword Zaamo ops.
> 
> Extension: https://github.com/riscv/riscv-zabha.git
> Ratification: https://jira.riscv.org/browse/RVS-1685
> 
> gcc/ChangeLog:
> 
> 	* common/config/riscv/riscv-common.cc
> 	(riscv_subset_list::to_string): Skip zabha when not supported by
> 	the assembler.
> 	* config.in: Regenerate.
> 	* config/riscv/arch-canonicalize: Make zabha imply zaamo.
> 	* config/riscv/iterators.md (amobh): Add iterator for amo
> 	byte/halfword.
> 	* config/riscv/riscv.opt: Add zabha.
> 	* config/riscv/sync.md (atomic_<atomic_optab><mode>): Add
> 	subword atomic op pattern.
> 	(zabha_atomic_fetch_<atomic_optab><mode>): Add subword
> 	atomic_fetch op pattern.
> 	(lrsc_atomic_fetch_<atomic_optab><mode>): Prefer zabha over lrsc
> 	for subword atomic ops.
> 	(zabha_atomic_exchange<mode>): Add subword atomic exchange
> 	pattern.
> 	(lrsc_atomic_exchange<mode>): Prefer zabha over lrsc for subword
> 	atomic exchange ops.
> 	* configure: Regenerate.
> 	* configure.ac: Add zabha assembler check.
> 	* doc/sourcebuild.texi: Add zabha documentation.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* lib/target-supports.exp: Add zabha testsuite infra support.
> 	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-1.c: Remove zabha
> 	to continue to test the lr/sc subword patterns.
> 	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-2.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-3.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-4.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-5.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-1.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-2.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-3.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-4.c: Ditto.
> 	* gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-5.c: Ditto.
> 	* gcc.target/riscv/amo/inline-atomics-1.c: Ditto.
> 	* gcc.target/riscv/amo/inline-atomics-2.c: Ditto.
> 	* gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c: New test.
> 	* gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c: New test.
> 	* gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c: New test.
> 	* gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c: New test.
> 	* gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c: New test.
> 	* gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c: New test.
> 	* gcc.target/riscv/amo/zabha-ztso-amo-add-char.c: New test.
> 	* gcc.target/riscv/amo/zabha-ztso-amo-add-short.c: New test.
OK.  And Palmer's doc update is also OK.  I assume he'll be offline for 
a while, so if you wanted to commit that for him, it'd be appreciated.

jeff
diff mbox series

Patch

diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 410e673f5e0..16bdb3fd225 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -82,6 +82,8 @@  static const riscv_implied_info_t riscv_implied_info[] =
   {"a", "zaamo"},
   {"a", "zalrsc"},

+  {"zabha", "zaamo"},
+
   {"zdinx", "zfinx"},
   {"zfinx", "zicsr"},
   {"zdinx", "zicsr"},
@@ -260,6 +262,7 @@  static const struct riscv_ext_version riscv_ext_version_table[] =
   {"zawrs", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zaamo", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zalrsc", ISA_SPEC_CLASS_NONE, 1, 0},
+  {"zabha", ISA_SPEC_CLASS_NONE, 1, 0},

   {"zba", ISA_SPEC_CLASS_NONE, 1, 0},
   {"zbb", ISA_SPEC_CLASS_NONE, 1, 0},
@@ -918,6 +921,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_zicsr = false;
   bool i2p0 = false;

@@ -949,6 +953,10 @@  riscv_subset_list::to_string (bool version_p) const
   /* Skip since binutils 2.42 and earlier don't recognize zaamo/zalrsc.  */
   skip_zaamo_zalrsc = true;
 #endif
+#ifndef HAVE_AS_MARCH_ZABHA
+  /* Skip since binutils 2.42 and earlier don't recognize zabha.  */
+  skip_zabha = true;
+#endif

   for (subset = m_head; subset != NULL; subset = subset->next)
     {
@@ -966,6 +974,9 @@  riscv_subset_list::to_string (bool version_p) const
       if (skip_zaamo_zalrsc && subset->name == "zalrsc")
 	continue;

+      if (skip_zabha && subset->name == "zabha")
+	continue;
+
       /* For !version_p, we only separate extension with underline for
 	 multi-letter extension.  */
       if (!first &&
@@ -1638,6 +1649,7 @@  static const riscv_ext_flag_table_t riscv_ext_flag_table[] =
   {"zawrs",   &gcc_options::x_riscv_za_subext, MASK_ZAWRS},
   {"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},

   {"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 acab3c0f126..ae41596596f 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -635,6 +635,12 @@ 
 #endif


+/* Define if the assembler understands -march=rv*_zabha. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_MARCH_ZABHA
+#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 6c10d1aa81b..35a7fe4455a 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -40,7 +40,10 @@  LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
 #
 IMPLIED_EXT = {
   "d" : ["f", "zicsr"],
+
   "a" : ["zaamo", "zalrsc"],
+  "zabha" : ["zaamo"],
+
   "f" : ["zicsr"],
   "zdinx" : ["zfinx", "zicsr"],
   "zfinx" : ["zicsr"],
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 20745faa55e..d61ed53a8b1 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -122,6 +122,9 @@ 
 ;; This attribute gives the format suffix for atomic memory operations.
 (define_mode_attr amo [(SI "w") (DI "d")])

+;; This attribute gives the format suffix for byte and halfword atomic memory operations.
+(define_mode_attr amobh [(QI "b") (HI "h")])
+
 ;; This attribute gives the upper-case mode name for one unit of a
 ;; floating-point mode.
 (define_mode_attr UNITMODE [(HF "HF") (SF "SF") (DF "DF")])
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index b13e993c47a..32a0dda5843 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -262,6 +262,8 @@  Mask(ZAAMO)  Var(riscv_za_subext)

 Mask(ZALRSC) Var(riscv_za_subext)

+Mask(ZABHA) 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 4784375449f..0470e2ca457 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -24,8 +24,10 @@ 
   UNSPEC_COMPARE_AND_SWAP_SUBWORD
   UNSPEC_SYNC_OLD_OP
   UNSPEC_SYNC_OLD_OP_SUBWORD
+  UNSPEC_SYNC_OLD_OP_ZABHA
   UNSPEC_SYNC_EXCHANGE
   UNSPEC_SYNC_EXCHANGE_SUBWORD
+  UNSPEC_SYNC_EXCHANGE_ZABHA
   UNSPEC_ATOMIC_LOAD
   UNSPEC_ATOMIC_STORE
   UNSPEC_MEMORY_BARRIER
@@ -88,6 +90,18 @@ 

 ;; AMO ops

+(define_insn "atomic_<atomic_optab><mode>"
+  [(set (match_operand:SHORT 0 "memory_operand" "+A")
+	(unspec_volatile:SHORT
+	  [(any_atomic:SHORT (match_dup 0)
+		     (match_operand:SHORT 1 "reg_or_0_operand" "rJ"))
+	   (match_operand:SI 2 "const_int_operand")] ;; model
+	 UNSPEC_SYNC_OLD_OP_ZABHA))]
+  "TARGET_ZABHA"
+  "amo<insn>.<amobh>%A2\tzero,%z1,%0"
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
 (define_expand "atomic_<atomic_optab><mode>"
   [(any_atomic:GPR (match_operand:GPR 0 "memory_operand")    ;; mem location
 		   (match_operand:GPR 1 "reg_or_0_operand")) ;; value for op
@@ -287,7 +301,37 @@ 
    (any_atomic:SHORT (match_operand:SHORT 1 "memory_operand")	 ;; mem location
 		     (match_operand:SHORT 2 "reg_or_0_operand")) ;; value for op
    (match_operand:SI 3 "const_int_operand")]			 ;; model
-  "TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
+  "(TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC) || TARGET_ZABHA"
+{
+  if (TARGET_ZABHA)
+    emit_insn(gen_zabha_atomic_fetch_<atomic_optab><mode> (operands[0], operands[1],
+							   operands[2], operands[3]));
+  else
+    emit_insn(gen_lrsc_atomic_fetch_<atomic_optab><mode> (operands[0], operands[1],
+							  operands[2], operands[3]));
+  DONE;
+})
+
+(define_insn "zabha_atomic_fetch_<atomic_optab><mode>"
+  [(set (match_operand:SHORT 0 "register_operand" "=&r")
+	(match_operand:SHORT 1 "memory_operand" "+A"))
+   (set (match_dup 1)
+	(unspec_volatile:SHORT
+	  [(any_atomic:SHORT (match_dup 1)
+		     (match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
+	   (match_operand:SI 3 "const_int_operand")] ;; model
+	 UNSPEC_SYNC_OLD_OP_ZABHA))]
+   "TARGET_ZABHA"
+   "amo<insn>.<amobh>%A3\t%0,%z2,%1"
+   [(set_attr "type" "atomic")
+    (set (attr "length") (const_int 4))])
+
+(define_expand "lrsc_atomic_fetch_<atomic_optab><mode>"
+  [(match_operand:SHORT 0 "register_operand")			 ;; old value at mem
+   (any_atomic:SHORT (match_operand:SHORT 1 "memory_operand")	 ;; mem location
+		     (match_operand:SHORT 2 "reg_or_0_operand")) ;; value for op
+   (match_operand:SI 3 "const_int_operand")]			 ;; model
+  "!TARGET_ZABHA && TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
 {
   /* We have no QImode/HImode atomics, so form a mask, then use
      subword_atomic_fetch_strong_<mode> to implement a LR/SC version of the
@@ -323,6 +367,8 @@ 
   DONE;
 })

+; Atomic exchange ops
+
 (define_expand "atomic_exchange<mode>"
   [(match_operand:GPR 0 "register_operand")  ;; old value at mem
    (match_operand:GPR 1 "memory_operand")    ;; mem location
@@ -377,7 +423,36 @@ 
    (match_operand:SHORT 1 "memory_operand")   ;; mem location
    (match_operand:SHORT 2 "register_operand") ;; value
    (match_operand:SI 3 "const_int_operand")]  ;; model
-  "TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
+  "(TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC) || TARGET_ZABHA"
+{
+ if (TARGET_ZABHA)
+    emit_insn(gen_zabha_atomic_exchange<mode>(operands[0], operands[1],
+					      operands[2], operands[3]));
+ else
+    emit_insn(gen_lrsc_atomic_exchange<mode>(operands[0], operands[1],
+					     operands[2], operands[3]));
+  DONE;
+})
+
+(define_insn "zabha_atomic_exchange<mode>"
+  [(set (match_operand:SHORT 0 "register_operand" "=&r")
+	(unspec_volatile:SHORT
+	  [(match_operand:SHORT 1 "memory_operand" "+A")
+	   (match_operand:SI 3 "const_int_operand")] ;; model
+	  UNSPEC_SYNC_EXCHANGE_ZABHA))
+   (set (match_dup 1)
+	(match_operand:SHORT 2 "register_operand" "0"))]
+  "TARGET_ZABHA"
+  "amoswap.<amobh>%A3\t%0,%z2,%1"
+  [(set_attr "type" "atomic")
+   (set (attr "length") (const_int 4))])
+
+(define_expand "lrsc_atomic_exchange<mode>"
+  [(match_operand:SHORT 0 "register_operand") ;; old value at mem
+   (match_operand:SHORT 1 "memory_operand")   ;; mem location
+   (match_operand:SHORT 2 "register_operand") ;; value
+   (match_operand:SI 3 "const_int_operand")]  ;; model
+  "!TARGET_ZABHA && TARGET_ZALRSC && TARGET_INLINE_SUBWORD_ATOMIC"
 {
   rtx old = gen_reg_rtx (SImode);
   rtx mem = operands[1];
@@ -426,6 +501,8 @@ 
   [(set_attr "type" "multi")
    (set (attr "length") (const_int 20))])

+; Atomic CAS ops
+
 (define_insn "atomic_cas_value_strong<mode>"
   [(set (match_operand:GPR 0 "register_operand" "=&r")
 	(match_operand:GPR 1 "memory_operand" "+A"))
diff --git a/gcc/configure b/gcc/configure
index ad998105da3..1335db2d4d2 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -30853,6 +30853,37 @@  if test $gcc_cv_as_riscv_march_zaamo_zalrsc = yes; then

 $as_echo "#define HAVE_AS_MARCH_ZAAMO_ZALRSC 1" >>confdefs.h

+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for -march=rv32i_zabha support" >&5
+$as_echo_n "checking assembler for -march=rv32i_zabha support... " >&6; }
+if ${gcc_cv_as_riscv_march_zabha+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_riscv_march_zabha=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_zabha -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_zabha=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_zabha" >&5
+$as_echo "$gcc_cv_as_riscv_march_zabha" >&6; }
+if test $gcc_cv_as_riscv_march_zabha = yes; then
+
+$as_echo "#define HAVE_AS_MARCH_ZABHA 1" >>confdefs.h
+
 fi

     ;;
diff --git a/gcc/configure.ac b/gcc/configure.ac
index c51d3ca5f1b..eb72f65865a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -5459,6 +5459,11 @@  configured with --enable-newlib-nano-formatted-io.])
       [-march=rv32i_zaamo_zalrsc],,,
       [AC_DEFINE(HAVE_AS_MARCH_ZAAMO_ZALRSC, 1,
 		 [Define if the assembler understands -march=rv*_zaamo_zalrsc.])])
+    gcc_GAS_CHECK_FEATURE([-march=rv32i_zabha support],
+      gcc_cv_as_riscv_march_zabha,
+      [-march=rv32i_zabha],,,
+      [AC_DEFINE(HAVE_AS_MARCH_ZABHA, 1,
+		 [Define if the assembler understands -march=rv*_zabha.])])
     ;;
     loongarch*-*-*)
     gcc_GAS_CHECK_FEATURE([.dtprelword support],
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index c6bb41d1d23..66c4206bfc2 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -2527,7 +2527,10 @@  Test target architecture has support for the A extension.
 @item riscv_zaamo
 Test target architecture has support for the zaamo extension.

-@item riscv_zlrsc
+@item riscv_zabha
+Test target architecture has support for the zabha extension.
+
+@item riscv_zalrsc
 Test target architecture has support for the zalrsc extension.

 @item riscv_ztso
@@ -3292,6 +3295,9 @@  Add the 'A' extension to the -march string on RISC-V targets.
 @item riscv_zaamo
 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_zalrsc
 Add the zalrsc extension to the -march string on RISC-V targets.

@@ -3335,6 +3341,10 @@  RISC-V targets.
 Remove the zaamo extension from the -march string on RISC-V. If the 'A'
 extension is present downgrade it to zalrsc.

+@item riscv_zabha
+Remove the zabha 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/amo-table-a-6-subword-amo-add-1.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-1.c
index 50009f021dc..ce5773e5496 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-1.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-1.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match Table A.6's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-a-6-subword-amo-add-2.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-2.c
index 782ffcb0a70..5ca1ab027ce 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-2.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-2.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match Table A.6's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-a-6-subword-amo-add-3.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-3.c
index 76ec8a81d1f..3378156f3d7 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-3.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-3.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match Table A.6's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-a-6-subword-amo-add-4.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-4.c
index 3f5fa20c87c..797f88538ce 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-4.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-4.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match Table A.6's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-a-6-subword-amo-add-5.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-5.c
index 7417a67f692..d54127ca867 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-5.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-a-6-subword-amo-add-5.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match Table A.6's recommended mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-remove-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-ztso-subword-amo-add-1.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-1.c
index a44d6980ece..292d61ea2a9 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-1.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-1.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-ztso-subword-amo-add-2.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-2.c
index 8d28569c79c..3e61b19ffa2 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-2.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-2.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-ztso-subword-amo-add-3.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-3.c
index fb803ab9cbf..6ed85aebd21 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-3.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-3.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-ztso-subword-amo-add-4.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-4.c
index a88e409063a..b48ab1d2bfe 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-4.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-4.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/amo-table-ztso-subword-amo-add-5.c b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-5.c
index d851e5e5944..0d5c4f224e7 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-5.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/amo-table-ztso-subword-amo-add-5.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the Ztso suggested mapping.  */
 /* { dg-add-options riscv_zalrsc } */
 /* { dg-add-options riscv_ztso } */
+/* { dg-remove-options riscv_zabha } */
 /* { 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/inline-atomics-1.c b/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-1.c
index 5c5623d9b2f..8556637d17d 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-1.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-1.c
@@ -1,5 +1,6 @@ 
 /* { dg-do compile } */
 /* { dg-options "-mno-inline-atomics" } */
+/* { dg-remove-options riscv_zabha } */
 /* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
 /* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_add_1" } } */
 /* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_nand_1" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-2.c b/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-2.c
index 76c99829f33..8ec07b0e0e4 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-2.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/inline-atomics-2.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomics do not generate calls.  */
 /* { dg-options "-minline-atomics" } */
 /* { dg-add-options riscv_a } */
+/* { dg-remove-options riscv_zabha } */
 /* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
 /* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_add_1" } } */
 /* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_nand_1" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c
new file mode 100644
index 00000000000..039318b6ca7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-char-run.c
@@ -0,0 +1,5 @@ 
+/* Test __atomic routines for existence on 1 byte values with each valid memory model.  */
+/* { dg-do run { target { riscv_zabha } } } */
+/* { dg-options "-Wno-address-of-packed-member" } */
+
+#include "inline-atomics-3.c"
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c
new file mode 100644
index 00000000000..7639537893c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-all-amo-ops-short-run.c
@@ -0,0 +1,5 @@ 
+/* Test __atomic routines for execution on 2 byte values with each valid memory model.  */
+/* { dg-do run { target { riscv_zabha } } } */
+/* { dg-options "-Wno-address-of-packed-member" } */
+
+#include "inline-atomics-4.c"
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c
new file mode 100644
index 00000000000..85841fd7036
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-char.c
@@ -0,0 +1,23 @@ 
+/* Test __atomic routines for existence on 2 byte values with each valid memory model.  */
+/* { dg-compile } */
+/* { dg-options "-Wno-address-of-packed-member" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler "\tamoadd.b" } } */
+/* { dg-final { scan-assembler "\tamoadd.b.aq" } } */
+/* { dg-final { scan-assembler "\tamoadd.b.rl" } } */
+/* { dg-final { scan-assembler "\tamoadd.b.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoand.b" } } */
+/* { dg-final { scan-assembler "\tamoand.b.aq" } } */
+/* { dg-final { scan-assembler "\tamoand.b.rl" } } */
+/* { dg-final { scan-assembler "\tamoand.b.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoxor.b" } } */
+/* { dg-final { scan-assembler "\tamoxor.b.aq" } } */
+/* { dg-final { scan-assembler "\tamoxor.b.rl" } } */
+/* { dg-final { scan-assembler "\tamoxor.b.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoor.b" } } */
+/* { dg-final { scan-assembler "\tamoor.b.aq" } } */
+/* { dg-final { scan-assembler "\tamoor.b.rl" } } */
+/* { dg-final { scan-assembler "\tamoor.b.aqrl" } } */
+
+#include "inline-atomics-3.c"
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c
new file mode 100644
index 00000000000..edc0a2c8f8e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-all-amo-ops-short.c
@@ -0,0 +1,23 @@ 
+/* Test __atomic routines for existence on 2 byte values with each valid memory model.  */
+/* { dg-compile } */
+/* { dg-options "-Wno-address-of-packed-member" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-final { scan-assembler "\tamoadd.h" } } */
+/* { dg-final { scan-assembler "\tamoadd.h.aq" } } */
+/* { dg-final { scan-assembler "\tamoadd.h.rl" } } */
+/* { dg-final { scan-assembler "\tamoadd.h.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoand.h" } } */
+/* { dg-final { scan-assembler "\tamoand.h.aq" } } */
+/* { dg-final { scan-assembler "\tamoand.h.rl" } } */
+/* { dg-final { scan-assembler "\tamoand.h.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoxor.h" } } */
+/* { dg-final { scan-assembler "\tamoxor.h.aq" } } */
+/* { dg-final { scan-assembler "\tamoxor.h.rl" } } */
+/* { dg-final { scan-assembler "\tamoxor.h.aqrl" } } */
+/* { dg-final { scan-assembler "\tamoor.h" } } */
+/* { dg-final { scan-assembler "\tamoor.h.aq" } } */
+/* { dg-final { scan-assembler "\tamoor.h.rl" } } */
+/* { dg-final { scan-assembler "\tamoor.h.aqrl" } } */
+
+#include "inline-atomics-4.c"
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c
new file mode 100644
index 00000000000..a75c102196d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-char.c
@@ -0,0 +1,57 @@ 
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_add_fetch_char_relaxed:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_relaxed (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
+
+/*
+** atomic_add_fetch_char_acquire:
+**	amoadd\.b\.aq\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_acquire (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
+
+/*
+** atomic_add_fetch_char_release:
+**	amoadd\.b\.rl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_release (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
+
+/*
+** atomic_add_fetch_char_acq_rel:
+**	amoadd\.b\.aqrl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_acq_rel (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
+
+/*
+** atomic_add_fetch_char_seq_cst:
+**	amoadd\.b\.aqrl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_seq_cst (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c
new file mode 100644
index 00000000000..7755bb84784
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-rvwmo-amo-add-short.c
@@ -0,0 +1,57 @@ 
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-remove-options riscv_ztso } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_add_fetch_short_relaxed:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_relaxed (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
+
+/*
+** atomic_add_fetch_short_acquire:
+**	amoadd\.h\.aq\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_acquire (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
+
+/*
+** atomic_add_fetch_short_release:
+**	amoadd\.h\.rl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_release (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
+
+/*
+** atomic_add_fetch_short_acq_rel:
+**	amoadd\.h\.aqrl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_acq_rel (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
+
+/*
+** atomic_add_fetch_short_seq_cst:
+**	amoadd\.h\.aqrl\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_seq_cst (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-char.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-char.c
new file mode 100644
index 00000000000..bcd7477c673
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-char.c
@@ -0,0 +1,57 @@ 
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_add_fetch_char_relaxed:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_relaxed (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
+
+/*
+** atomic_add_fetch_char_acquire:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_acquire (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
+
+/*
+** atomic_add_fetch_char_release:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_release (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
+
+/*
+** atomic_add_fetch_char_acq_rel:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_acq_rel (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
+
+/*
+** atomic_add_fetch_char_seq_cst:
+**	amoadd\.b\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_char_seq_cst (char* bar, char baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-short.c b/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-short.c
new file mode 100644
index 00000000000..c4e8c9cf3ef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/amo/zabha-ztso-amo-add-short.c
@@ -0,0 +1,57 @@ 
+/* Verify that atomic op mappings match the PSABI doc's recommended mapping.  */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-add-options riscv_ztso } */
+/* { dg-add-options riscv_zabha } */
+/* { dg-skip-if "" { *-*-* } { "-g" "-flto"} } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+** atomic_add_fetch_short_relaxed:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_relaxed (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELAXED);
+}
+
+/*
+** atomic_add_fetch_short_acquire:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_acquire (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQUIRE);
+}
+
+/*
+** atomic_add_fetch_short_release:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_release (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_RELEASE);
+}
+
+/*
+** atomic_add_fetch_short_acq_rel:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_acq_rel (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_ACQ_REL);
+}
+
+/*
+** atomic_add_fetch_short_seq_cst:
+**	amoadd\.h\tzero,a1,0\(a0\)
+**	ret
+*/
+void atomic_add_fetch_short_seq_cst (short* bar, short baz)
+{
+  __atomic_add_fetch(bar, baz, __ATOMIC_SEQ_CST);
+}
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 47ef8f41fb7..e9d1bbd5867 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -1911,6 +1911,17 @@  proc check_effective_target_riscv_zaamo { } {
     }]
 }

+# Return 1 if the target arch supports the atomic BHA extension, 0 otherwise.
+# Cache the result.
+
+proc check_effective_target_riscv_zabha { } {
+    return [check_no_compiler_messages riscv_ext_zabha assembly {
+       #ifndef __riscv_zabha
+       #error "Not __riscv_zabha"
+       #endif
+    }]
+}
+
 # Return 1 if the target arch supports the double precision floating point
 # extension, 0 otherwise.  Cache the result.

@@ -2129,7 +2140,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 v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh ztso zaamo zalrsc } {
+    foreach ext { i m a f d q c v zicsr zifencei zfh zba zbb zbc zbs zvbb zvfh ztso zaamo zalrsc zabha } {
 	if { [check_no_compiler_messages  riscv_ext_$ext assembly [string map [list DEF __riscv_$ext] {
 		#ifndef DEF
 		#error "Not DEF"
@@ -2294,12 +2305,15 @@  proc add_options_for_riscv_zaamo { flags } {

 proc remove_options_for_riscv_zaamo { flags } {
     set modified_flags [remove_options_for_riscv_z_ext 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 '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 [split $modified_flags]]
+    set no_a_flags [remove_options_for_riscv_a_only $modified_flags]
     if {![string equal $modified_flags $no_a_flags]} {
 	# 'a' was removed, add 'zalrsc' since it was previously implied
-	set modified_flags [add_options_for_riscv_zalrsc [split $no_a_flags]]
+	set modified_flags [add_options_for_riscv_zalrsc $no_a_flags]
     }
     return $modified_flags
 }
@@ -2312,14 +2326,23 @@  proc remove_options_for_riscv_zalrsc { flags } {
     set modified_flags [remove_options_for_riscv_z_ext zalrsc $flags]
     # If 'a' is set then zalrsc will be implied. We need to downgrade instances
     # of 'a' to 'zaamo'
-    set no_a_flags [remove_options_for_riscv_a_only [split $modified_flags]]
+    set no_a_flags [remove_options_for_riscv_a_only $modified_flags]
     if {![string equal $modified_flags $no_a_flags]} {
 	# 'a' was removed, add 'zalrsc' since it was previously implied
-	set modified_flags [add_options_for_riscv_zalrsc [split $no_a_flags]]
+	set modified_flags [add_options_for_riscv_zalrsc $no_a_flags]
     }
     return $modified_flags
 }

+proc add_options_for_riscv_zabha { flags } {
+    return [add_options_for_riscv_z_ext zabha $flags]
+}
+
+proc remove_options_for_riscv_zabha { flags } {
+    set modified_flags [remove_options_for_riscv_zaamo $flags]
+    return [remove_options_for_riscv_z_ext zabha $modified_flags]
+}
+
 proc add_options_for_riscv_zfh { flags } {
     return [add_options_for_riscv_z_ext zfh $flags]
 }