diff mbox series

[v2] RISC-V: Add support for Zabha extension

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

Commit Message

Patrick O'Neill July 3, 2024, 1:05 a.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:

	* gcc.target/riscv/amo/inline-atomics-1.c: Remove zabha to continue to
	test the lr/sc subword patterns.
	* gcc.target/riscv/amo/inline-atomics-2.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c: Ditto.
	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.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>
Signed-Off-By: Gianluca Guida <gianluca@rivosinc.com>
Tested-by: Andrea Parri <andrea@rivosinc.com>
---
v2 ChangeLog:
Rebase to resolve conflict with testsuite cleanup. Regenerate gcc/testsuite ChangeLog.
Add Signed-Off-By that Gianluca gave.
Ok'd by Jeff Law here: https://inbox.sourceware.org/gcc-patches/fae68675-519f-4d80-b0fb-dfd5d8a2241e@gmail.com/
I'll let it sit on the lists overnight and commit in the morning tomorrow (PST timezone).
---
 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 ++-
 .../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 +++++++++++++
 ...alrsc-rvwmo-subword-amo-add-char-acq-rel.c |  1 +
 ...alrsc-rvwmo-subword-amo-add-char-acquire.c |  1 +
 ...alrsc-rvwmo-subword-amo-add-char-relaxed.c |  1 +
 ...alrsc-rvwmo-subword-amo-add-char-release.c |  1 +
 ...alrsc-rvwmo-subword-amo-add-char-seq-cst.c |  1 +
 ...zalrsc-ztso-subword-amo-add-char-acq-rel.c |  1 +
 ...zalrsc-ztso-subword-amo-add-char-acquire.c |  1 +
 ...zalrsc-ztso-subword-amo-add-char-relaxed.c |  1 +
 ...zalrsc-ztso-subword-amo-add-char-release.c |  1 +
 ...zalrsc-ztso-subword-amo-add-char-seq-cst.c |  1 +
 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.43.2

Comments

Patrick O'Neill July 3, 2024, 4:26 p.m. UTC | #1
Committed w/ fixup to changelog to add missing:
* lib/target-supports.exp: Add zabha testsuite infra support.

Patrick

On 7/2/24 18:05, 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:
>
> 	* gcc.target/riscv/amo/inline-atomics-1.c: Remove zabha to continue to
> 	test the lr/sc subword patterns.
> 	* gcc.target/riscv/amo/inline-atomics-2.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c: Ditto.
> 	* gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.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>
> Signed-Off-By: Gianluca Guida <gianluca@rivosinc.com>
> Tested-by: Andrea Parri <andrea@rivosinc.com>
> ---
> v2 ChangeLog:
> Rebase to resolve conflict with testsuite cleanup. Regenerate gcc/testsuite ChangeLog.
> Add Signed-Off-By that Gianluca gave.
> Ok'd by Jeff Law here: https://inbox.sourceware.org/gcc-patches/fae68675-519f-4d80-b0fb-dfd5d8a2241e@gmail.com/
> I'll let it sit on the lists overnight and commit in the morning tomorrow (PST timezone).
> ---
>   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 ++-
>   .../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 +++++++++++++
>   ...alrsc-rvwmo-subword-amo-add-char-acq-rel.c |  1 +
>   ...alrsc-rvwmo-subword-amo-add-char-acquire.c |  1 +
>   ...alrsc-rvwmo-subword-amo-add-char-relaxed.c |  1 +
>   ...alrsc-rvwmo-subword-amo-add-char-release.c |  1 +
>   ...alrsc-rvwmo-subword-amo-add-char-seq-cst.c |  1 +
>   ...zalrsc-ztso-subword-amo-add-char-acq-rel.c |  1 +
>   ...zalrsc-ztso-subword-amo-add-char-acquire.c |  1 +
>   ...zalrsc-ztso-subword-amo-add-char-relaxed.c |  1 +
>   ...zalrsc-ztso-subword-amo-add-char-release.c |  1 +
>   ...zalrsc-ztso-subword-amo-add-char-seq-cst.c |  1 +
>   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
>
> 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/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/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
> index 2c2df133a28..33b70acb15c 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
> index abfbf63902c..e173296bcfc 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
> index 1f61c89da88..f544d677219 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
> index 343503ce79c..bb34873feeb 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
> index 045434b2579..d8991ee1a84 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-ztso-subword-amo-add-char-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
> index f64b10a076a..7c9187e52b5 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
> index 5d743f0ab83..675043f9c61 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
> index 3e7dda9c8c4..7bf9eb0a7f7 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
> index ffd832eef78..6b78ce74b00 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
> index e9ea3f5ff3b..14fadf1e3fe 100644
> --- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
> +++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
> @@ -2,6 +2,7 @@
>   /* Verify that subword atomic op mappings match the PSABI doc's 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/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
> index b7df6150bcb..e7a1984704a 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]
>   }
> --
> 2.43.2
>
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/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/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
index 2c2df133a28..33b70acb15c 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acq-rel.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
index abfbf63902c..e173296bcfc 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-acquire.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
index 1f61c89da88..f544d677219 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-relaxed.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
index 343503ce79c..bb34873feeb 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-release.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
index 045434b2579..d8991ee1a84 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-rvwmo-subword-amo-add-char-seq-cst.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc'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/zalrsc-ztso-subword-amo-add-char-acq-rel.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
index f64b10a076a..7c9187e52b5 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acq-rel.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-acquire.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
index 5d743f0ab83..675043f9c61 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-acquire.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-relaxed.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
index 3e7dda9c8c4..7bf9eb0a7f7 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-relaxed.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-release.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
index ffd832eef78..6b78ce74b00 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-release.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc's 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/zalrsc-ztso-subword-amo-add-char-seq-cst.c b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
index e9ea3f5ff3b..14fadf1e3fe 100644
--- a/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
+++ b/gcc/testsuite/gcc.target/riscv/amo/zalrsc-ztso-subword-amo-add-char-seq-cst.c
@@ -2,6 +2,7 @@ 
 /* Verify that subword atomic op mappings match the PSABI doc's 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/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index b7df6150bcb..e7a1984704a 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]
 }