From 05d286edcaa6880da1a2a303393f24356f73a740 Mon Sep 17 00:00:00 2001
From: Kuan-Lin Chen <rufus@andestech.com>
Date: Wed, 9 Apr 2025 10:53:16 +0800
Subject: [PATCH 2/7] RISC-V: Add support for the XAndesperf ISA extension.

This patch adds support for the XAndesperf ISA extension.
The 32-bit AndeStar V5 extension includes branch instructions,
load effective address instructions, and string processing
instructions for performance improvement.
New INSN patterns are added into the new file andes.md
as a seprated vender extension.

gcc/ChangeLog:

	* config/riscv/constraints.md (Ou07): New constraint.
	(ads_Bext): New constraint.
	* config/riscv/iterators.md (ANYLE32): New iterator.
	(sizen): New iterator.
	(sh_limit): New iterator.
	(sh_bit): New iterator.
	* config/riscv/predicates.md (ads_branch_bbcs_operand): New predicate.
	(ads_branch_bimm_operand): New predicate.
	(ads_imm_extract_operand): New predicate.
	(ads_extract_size_imm_si): New predicate.
	(ads_extract_size_imm_di): New predicate.
	(const_int5_operand): New predicate.
	* config/riscv/riscv-builtins.cc:
	Add new AVAIL andesperf32 and andesperf64.
	Add new define RISCV_ATYPE_ULONG and RISCV_ATYPE_LONG.
	* config/riscv/riscv-ftypes.def: New DEF_RISCV_FTYPE.
	* config/riscv/riscv.cc
	(riscv_extend_cost): Cost for pattern 'bfo'.
	(riscv_rtx_costs): Cost for XAndesperf extension.
	* config/riscv/riscv.md: Add support for XAndesperf to patterns
	zero_extendsidi2_internal, zero_extendhi2, extendsidi2_internal,
	extend<SHORT:mode><SUPERQI:mode>2, <any_extract:optab><GPR:mode>3
	and branch_on_bit.
	* config/riscv/vector-iterators.md
	 (sz): Add sign_extract and zero_extract.
	* config/riscv/andes.def: New file for vender Andes.
	* config/riscv/andes.md: New file for vender Andes.

gcc/testsuite/ChangeLog:

	* gcc.target/riscv/xandesperf-1.c: New test.
	* gcc.target/riscv/xandesperf-10.c: New test.
	* gcc.target/riscv/xandesperf-2.c: New test.
	* gcc.target/riscv/xandesperf-3.c: New test.
	* gcc.target/riscv/xandesperf-4.c: New test.
	* gcc.target/riscv/xandesperf-5.c: New test.
	* gcc.target/riscv/xandesperf-6.c: New test.
	* gcc.target/riscv/xandesperf-7.c: New test.
	* gcc.target/riscv/xandesperf-8.c: New test.
	* gcc.target/riscv/xandesperf-9.c: New test.
---
 gcc/config/riscv/andes.def                    |  10 +
 gcc/config/riscv/andes.md                     | 443 ++++++++++++++++++
 gcc/config/riscv/constraints.md               |  10 +
 gcc/config/riscv/iterators.md                 |  12 +
 gcc/config/riscv/predicates.md                |  42 ++
 gcc/config/riscv/riscv-builtins.cc            |   7 +
 gcc/config/riscv/riscv-ftypes.def             |   1 +
 gcc/config/riscv/riscv.cc                     |  32 ++
 gcc/config/riscv/riscv.md                     |  17 +-
 gcc/config/riscv/vector-iterators.md          |   2 +-
 gcc/testsuite/gcc.target/riscv/xandesperf-1.c |  13 +
 .../gcc.target/riscv/xandesperf-10.c          |  32 ++
 gcc/testsuite/gcc.target/riscv/xandesperf-2.c |  13 +
 gcc/testsuite/gcc.target/riscv/xandesperf-3.c |  11 +
 gcc/testsuite/gcc.target/riscv/xandesperf-4.c |  11 +
 gcc/testsuite/gcc.target/riscv/xandesperf-5.c |  11 +
 gcc/testsuite/gcc.target/riscv/xandesperf-6.c |  18 +
 gcc/testsuite/gcc.target/riscv/xandesperf-7.c |  22 +
 gcc/testsuite/gcc.target/riscv/xandesperf-8.c |  26 +
 gcc/testsuite/gcc.target/riscv/xandesperf-9.c |  31 ++
 20 files changed, 757 insertions(+), 7 deletions(-)
 create mode 100644 gcc/config/riscv/andes.def
 create mode 100644 gcc/config/riscv/andes.md
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-1.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-10.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-2.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-3.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-4.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-5.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-6.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-7.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-8.c
 create mode 100644 gcc/testsuite/gcc.target/riscv/xandesperf-9.c

diff --git a/gcc/config/riscv/andes.def b/gcc/config/riscv/andes.def
new file mode 100644
index 000000000000..b864ae712c1d
--- /dev/null
+++ b/gcc/config/riscv/andes.def
@@ -0,0 +1,10 @@
+// XANDESPERF
+/* Andes Performance Extension */
+RISCV_BUILTIN (nds_ffbsi, "nds_ffb", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32),
+RISCV_BUILTIN (nds_ffbdi, "nds_ffb", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64),
+RISCV_BUILTIN (nds_ffzmismsi, "nds_ffzmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32),
+RISCV_BUILTIN (nds_ffzmismdi, "nds_ffzmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64),
+RISCV_BUILTIN (nds_ffmismsi, "nds_ffmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32),
+RISCV_BUILTIN (nds_ffmismdi, "nds_ffmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64),
+RISCV_BUILTIN (nds_flmismsi, "nds_flmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf32),
+RISCV_BUILTIN (nds_flmismdi, "nds_flmism", RISCV_BUILTIN_DIRECT, RISCV_LONG_FTYPE_ULONG_ULONG, andesperf64),
diff --git a/gcc/config/riscv/andes.md b/gcc/config/riscv/andes.md
new file mode 100644
index 000000000000..51f61e58e244
--- /dev/null
+++ b/gcc/config/riscv/andes.md
@@ -0,0 +1,443 @@
+;; Machine description for Andes vendor extensions
+;; Copyright (C) 2025 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; <http://www.gnu.org/licenses/>.
+
+(define_c_enum "unspec" [
+  ;; XANDESPERF string
+  UNSPEC_NDS_FFB
+  UNSPEC_NDS_FFZMISM
+  UNSPEC_NDS_FFMISM
+  UNSPEC_NDS_FLMISM
+])
+
+;; AndesPerf
+;;  ....................
+;;
+;;      BRANCH OPERATION
+;;
+;;  ....................
+;;
+
+(define_insn "*nds_branch_imms7<mode>"
+  [(set (pc)
+	(if_then_else
+	  (match_operator 1 "equality_operator"
+	    [(match_operand:X 2 "register_operand" "r")
+	     (match_operand:X 3 "ads_branch_bimm_operand" "Ou07")])
+	  (label_ref (match_operand 0 "" ""))
+	  (pc)))]
+  "TARGET_XANDESPERF"
+{
+  if (get_attr_length (insn) == 12)
+    return "nds.b%C1c\t%2,%3,1f; jump\t%l0,ra; 1:";
+
+  return "nds.b%C1c\t%2,%3,%l0";
+}
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
+
+(define_insn "*nds_branch_on_bit<X:mode>"
+  [(set (pc)
+	(if_then_else
+	    (match_operator 1 "equality_operator"
+		[(zero_extract:X (match_operand:X 2 "register_operand" "r")
+				 (const_int 1)
+				 (match_operand 3 "ads_branch_bbcs_operand"))
+				 (const_int 0)])
+	    (label_ref (match_operand 0))
+	    (pc)))
+   (clobber (match_scratch:X 4 "=&r"))]
+   "TARGET_XANDESPERF"
+{
+  if (GET_CODE (operands[1]) == EQ)
+    {
+      if (get_attr_length (insn) == 12)
+	return "nds.bbc\t%2,%3,%1f; jump\t%l0,ra; 1:";
+
+      return "nds.bbc\t%2,%3,%l0";
+    }
+  else
+    {
+      if (get_attr_length (insn) == 12)
+	return "nds.bbs\t%2,%3,%1f; jump\t%l0,ra; 1:";
+
+      return "nds.bbs\t%2,%3,%l0";
+    }
+}
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
+
+;;
+;;  ....................
+;;
+;;      EXTENSION OPERATION
+;;
+;;  ....................
+;;
+
+(define_insn "*nds_zero_extendsidi2_internal"
+  [(set (match_operand:DI     0 "register_operand"     "=r,r")
+	(zero_extend:DI
+	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  "@
+   nds.bfoz\t%0,%1,31,0
+   lwu\t%0,%1"
+  [(set_attr "move_type" "arith,load")
+   (set_attr "type" "arith,load")
+   (set_attr "mode" "DI")])
+
+(define_insn "*nds_zero_extendhi<GPR:mode>2"
+  [(set (match_operand:GPR    0 "register_operand"     "=r,r")
+	(zero_extend:GPR
+	  (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
+  "TARGET_XANDESPERF"
+  "@
+   nds.bfoz\t%0,%1,15,0
+   lhu\t%0,%1"
+  [(set_attr "move_type" "arith,load")
+   (set_attr "type" "arith,load")
+   (set_attr "mode" "<GPR:MODE>, HI")])
+
+(define_insn "*nds_extendsidi2_internal"
+  [(set (match_operand:DI     0 "register_operand"     "=r,r")
+	(sign_extend:DI
+	  (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  "@
+   nds.bfos\t%0,%1,31,0
+   lw\t%0,%1"
+  [(set_attr "move_type" "arith,load")
+   (set_attr "type" "arith,load")
+   (set_attr "mode" "DI")])
+
+(define_insn "*nds_extend<SHORT:mode><SUPERQI:mode>2"
+  [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
+	(sign_extend:SUPERQI
+	  (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
+  "TARGET_XANDESPERF"
+  "@
+   nds.bfos\t%0,%1,<SHORT:sh_limit>,0
+   l<SHORT:size>\t%0,%1"
+  [(set_attr "move_type" "arith,load")
+   (set_attr "type" "arith,load")
+   (set_attr "mode" "<SHORT:MODE>")])
+
+;;
+;;  ....................
+;;
+;;      BIT FIELD OPERATION
+;;
+;;  ....................
+;;
+
+;; BFO[SZ]: msb >= lsb: Extract sequence tail bits.
+(define_insn "*nds_bfo_<sz>extra<mode>4"
+  [(set (match_operand:GPR 0 "register_operand"                          "=r")
+	(any_extract:GPR (match_operand:GPR 1 "register_operand"         " r")
+			  (match_operand 2 "ads_extract_size_imm_<mode>" " n")
+			  (match_operand 3 "const_int<sh_bit>_operand"   " n")))]
+  "TARGET_XANDESPERF
+   && IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+		1, GET_MODE_BITSIZE (<MODE>mode))"
+  {
+    operands[2] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[3]) - 1);
+    return "nds.bfo<sz>\t%0,%1,%2,%3";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb >= lsb: Mask sequence bits.
+(define_insn "*nds_bfoz_and<mode>3"
+  [(set (match_operand:GPR 0 "register_operand"          "=r")
+	(and:GPR (match_operand:GPR 1 "register_operand" " r")
+		 (match_operand:GPR 2 "ads_imm_extract_operand"  " ads_Bext")))]
+  "TARGET_XANDESPERF"
+  {
+    operands[2] = GEN_INT (__builtin_popcountll (INTVAL (operands[2])) - 1);
+    return "nds.bfoz\t%0,%1,%2,0";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb >= lsb: Extract sequence bits.
+(define_insn "*nds_zero_extend<GPR:mode>_lshr<SHORT:mode>"
+  [(set (match_operand:GPR 0 "register_operand"                                    "=r")
+	(zero_extend:GPR (lshiftrt:SHORT (match_operand:SHORT 1 "register_operand" " r")
+			 (match_operand 2 "const_int_operand"                      " n"))))]
+  "TARGET_XANDESPERF
+   && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
+  "nds.bfoz\t%0, %1, <SHORT:sh_limit>, %2"
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOS: msb >= lsb
+(define_insn "*nds_extend<GPR:mode>_ashr<SHORT:mode>"
+  [(set (match_operand:GPR 0 "register_operand"                                    "=r")
+	(sign_extend:GPR (ashiftrt:SHORT (match_operand:SHORT 1 "register_operand" " r")
+					 (match_operand 2 "const_int_operand"      " n"))))]
+  "TARGET_XANDESPERF
+   && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<SHORT:MODE>mode)"
+  "nds.bfos\t%0, %1, <SHORT:sh_limit>, %2"
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO[SZ]: msb < lsb: Combine pass doesn't convert (and (ashift) Y) to
+;; zero_extract when exact_log2 (Y + 1) < 0.
+(define_insn "*nds_bfoz<mode>4"
+  [(set (match_operand:GPR 0 "register_operand"                           "=r")
+	(and:GPR (ashift:GPR (match_operand:GPR 1 "register_operand"      " r")
+			     (match_operand 2 "const_int<sh_bit>_operand" " n"))
+		 (match_operand 3 "const_int_operand"                     " i")))]
+  "TARGET_XANDESPERF
+   && (UINTVAL (operands[2]) != 0)
+   && (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1) > 1)
+   && ((UINTVAL (operands[3]) & ((1 << UINTVAL (operands[2])) - 1)) == 0)"
+  {
+    operands[3] =
+      GEN_INT (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1)
+	       + UINTVAL (operands[2]) - 1) ;
+    return "nds.bfoz\t%0,%1,%2,%3";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFOZ: msb = 0.
+(define_insn "*nds_bfoz0<mode>4"
+  [(set (match_operand:GPR 0 "register_operand"                           "=r")
+	(and:GPR (ashift:GPR (match_operand:GPR 1 "register_operand"      " r")
+			     (match_operand 2 "const_int<sh_bit>_operand" " n"))
+		 (match_operand 3 "const_int_operand"                     " i")))]
+  "TARGET_XANDESPERF
+   && (UINTVAL (operands[2]) != 0)
+   && (exact_log2 ((UINTVAL (operands[3]) >> UINTVAL (operands[2])) + 1) == 1)
+   && ((UINTVAL (operands[3]) & ((1 << UINTVAL (operands[2])) - 1)) == 0)"
+  {
+    return "nds.bfoz\t%0,%1,0,%2";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb = 0.
+(define_insn "*nds_bfos0<mode>4"
+  [(set (match_operand:GPR 0 "register_operand"                                 "=r")
+	(ashift:GPR (any_extract:GPR (match_operand:GPR 1 "register_operand"    " r")
+				     (const_int 1)
+				     (const_int 0))
+		    (match_operand 2 "const_int<sh_bit>_operand"                " n")))]
+  "TARGET_XANDESPERF"
+  {
+    return "nds.bfo<sz>\t%0,%1,0,%2";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb < lsb.
+(define_insn "*nds_bfos_<sz>extra_<mode>4"
+  [(set (match_operand:GPR 0 "register_operand"                                     "=r")
+	(ashift:GPR (any_extract:GPR (match_operand:GPR 1 "register_operand"        " r")
+				     (match_operand 2 "ads_extract_size_imm_<mode>" " n")
+				     (const_int 0))
+		    (match_operand 3 "const_int<sh_bit>_operand"                    " n")))]
+  "TARGET_XANDESPERF
+   && UINTVAL (operands[2]) != 1"
+  {
+    operands[2] =  GEN_INT (UINTVAL (operands[2]) + UINTVAL (operands[3]) - 1);
+    return "nds.bfo<sz>\t%0,%1,%3,%2";
+  }
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;; BFO: msb < lsb
+(define_insn "*nds_<optab><ANYLE32:mode>_shft_<GPR:mode>"
+  [(set (match_operand:GPR 0 "register_operand"               "=r")
+	(ashift:GPR (any_extend:GPR
+		    (match_operand:ANYLE32 1 "register_operand" " r"))
+		    (match_operand 2 "const_int_operand"      " n")))]
+  "TARGET_XANDESPERF
+   && (UINTVAL (operands[2]) < <ANYLE32:sizen>)
+   && ((INTVAL (operands[2]) + <ANYLE32:sizen>) <= <GPR:sizen>)"
+{
+  operands[3] = GEN_INT (<ANYLE32:sizen> + INTVAL (operands[2]) - 1);
+  return "nds.bfo<sz>\t%0, %1, %2, %3";
+}
+  [(set_attr "type" "shift")])
+
+;; BFO: msb < lsb
+(define_insn "*nds_<optab><GPR:mode>_ashl<ANYLE32:mode>"
+  [(set (match_operand:GPR 0 "register_operand"                 "=r")
+	(any_extend:GPR
+	(ashift:ANYLE32 (match_operand:ANYLE32 1 "register_operand" " r")
+		      (match_operand 2 "const_int_operand"      " n"))))]
+  "TARGET_XANDESPERF
+   && UINTVAL (operands[2]) < ((<ANYLE32:sizen>) - 1)"
+{
+  operands[3] = GEN_INT (<ANYLE32:sizen> - 1);
+  return "nds.bfo<sz>\t%0, %1, %2, %3";
+}
+  [(set_attr "type" "shift")
+   (set_attr "mode" "<GPR:MODE>")])
+
+;;
+;;  ....................
+;;
+;;	LOAD ADDRESS
+;;
+;;  ....................
+;;
+
+(define_insn "lea_h<mode>"
+  [(set (match_operand:P                   0 "register_operand" "=r")
+	(plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+			  (const_int 1))
+		(match_operand:P           2 "register_operand" " r")))]
+  "TARGET_XANDESPERF"
+  { return "nds.lea.h\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_w<mode>"
+  [(set (match_operand:P                   0 "register_operand" "=r")
+	(plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+			  (const_int 2))
+		(match_operand:P           2 "register_operand" " r")))]
+  "TARGET_XANDESPERF"
+  { return "nds.lea.w\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_d<mode>"
+  [(set (match_operand:P                   0 "register_operand" "=r")
+	(plus:P (ashift:P (match_operand:P 1 "register_operand" " r")
+			  (const_int 3))
+		(match_operand:P           2 "register_operand" " r")))]
+  "TARGET_XANDESPERF"
+  { return "nds.lea.d\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "<MODE>")])
+
+(define_insn "lea_b_ze"
+  [(set (match_operand:DI 0 "register_operand"                          "=r")
+	(plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+		 (match_operand:DI 2 "register_operand"                 " r")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  { return "nds.lea.b.ze\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
+
+(define_insn "lea_h_ze"
+  [(set (match_operand:DI 0 "register_operand"                                     "=r")
+	(plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+			    (const_int 1))
+		 (match_operand:DI 2 "register_operand"                            " r")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  { return "nds.lea.h.ze\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
+
+(define_insn "lea_w_ze"
+  [(set (match_operand:DI 0 "register_operand"                                     "=r")
+	(plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+			    (const_int 2))
+		 (match_operand:DI 2 "register_operand"                            " r")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  { return "nds.lea.w.ze\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
+
+(define_insn "lea_d_ze"
+  [(set (match_operand:DI 0 "register_operand"                                     "=r")
+	(plus:DI (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r"))
+			    (const_int 3))
+		 (match_operand:DI 2 "register_operand"                            " r")))]
+  "TARGET_64BIT && TARGET_XANDESPERF"
+  { return "nds.lea.d.ze\t%0,%2,%1"; }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
+
+(define_insn "lea_andim_ashift"
+  [(set (match_operand:DI 0 "register_operand"				   "=r")
+	(plus:DI (and:DI (ashift:DI (match_operand:DI 1 "register_operand" " r")
+				    (match_operand 2 "const_int_operand"   " i"))
+			 (match_operand 3 "const_int_operand"		   " i"))
+	(match_operand:DI 4 "register_operand"				   " r")))]
+  "TARGET_64BIT && TARGET_XANDESPERF
+   && IN_RANGE (UINTVAL (operands[2]), 0, 3)
+   && exact_log2 ((INTVAL (operands[3]) >> INTVAL (operands[2])) + 1) == 32
+   && (INTVAL (operands[3]) & ((1 << INTVAL (operands[2])) - 1)) == 0"
+  {
+  switch (UINTVAL (operands[2]))
+    {
+    case 0:
+      return "nds.lea.b.ze %0, %4, %1";
+    case 1:
+      return "nds.lea.h.ze %0, %4, %1";
+    case 2:
+      return "nds.lea.w.ze %0, %4, %1";
+    case 3:
+      return "nds.lea.d.ze %0, %4, %1";
+    default:
+      gcc_unreachable ();
+    }
+  }
+  [(set_attr "type" "arith")
+   (set_attr "mode" "DI")])
+
+;;
+;;  ....................
+;;
+;;    String Extension
+;;
+;;  ....................
+;;
+
+(define_insn "riscv_nds_ffb<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+		     (match_operand:GPR 2 "nonmemory_operand" "rJ")] UNSPEC_NDS_FFB))]
+  ""
+  "nds.ffb\t%0, %z1, %z2"
+  [(set_attr "mode" "<MODE>")
+   (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_ffzmism<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+		     (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FFZMISM))]
+  ""
+  "nds.ffzmism\t%0, %z1, %z2"
+  [(set_attr "mode" "<MODE>")
+   (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_ffmism<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+		     (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FFMISM))]
+  ""
+  "nds.ffmism\t%0, %z1, %z2"
+  [(set_attr "mode" "<MODE>")
+   (set_attr "type" "arith")])
+
+(define_insn "riscv_nds_flmism<mode>"
+  [(set (match_operand:GPR 0 "register_operand" "=r")
+	(unspec:GPR [(match_operand:GPR 1 "reg_or_0_operand" "rJ")
+		     (match_operand:GPR 2 "reg_or_0_operand" "rJ")] UNSPEC_NDS_FLMISM))]
+  ""
+  "nds.flmism\t%0, %z1, %z2"
+  [(set_attr "mode" "<MODE>")
+   (set_attr "type" "arith")])
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index ccab1a2e29df..006a86ba1e31 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -329,3 +329,13 @@
 (define_constraint "Q"
   "An address operand that is valid for a prefetch instruction"
   (match_operand 0 "prefetch_operand"))
+
+(define_constraint "Ou07"
+  "A 7-bit unsigned immediate."
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (ival, 0, 127)")))
+
+(define_constraint "ads_Bext"
+  "Sequence bit extract."
+  (and (match_code "const_int")
+       (match_test "(ival & (ival + 1)) == 0")))
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 584b345f02c4..fdfa3fee01a9 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -71,6 +71,9 @@
 ;; Iterator for hardware integer modes narrower than XLEN, same as ANYI.
 (define_mode_iterator ANYI1 [QI HI SI (DI "TARGET_64BIT")])
 
+;; Iterator for integer modes less than or equal to 32bit.
+(define_mode_iterator ANYLE32 [QI HI SI])
+
 (define_mode_iterator ANYI_DOUBLE_TRUNC [HI SI (DI "TARGET_64BIT")])
 
 (define_mode_iterator ANYI_QUAD_TRUNC [SI (DI "TARGET_64BIT")])
@@ -169,10 +172,19 @@
 ;; the controlling mode.
 (define_mode_attr HALFMODE [(DF "SI") (DI "SI") (TF "DI")])
 
+;; Give the number of bits in the mode
+(define_mode_attr sizen [(QI "8") (HI "16") (SI "32") (DI "64")])
+
 ; bitmanip mode attribute
 (define_mode_attr shiftm1 [(SI "const_si_mask_operand") (DI "const_di_mask_operand")])
 (define_mode_attr shiftm1p [(SI "DsS") (DI "DsD")])
 
+; mode shift limit attribute
+(define_mode_attr sh_limit [(QI "7") (HI "15")])
+
+; mode shift bit limit attribute
+(define_mode_attr sh_bit [(SI "5") (DI "6")])
+
 ; zcmp mode attribute
 (define_mode_attr slot0_offset  [(SI "-4")  (DI "-8")])
 (define_mode_attr slot1_offset  [(SI "-8")  (DI "-16")])
diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md
index 061904b6e000..cf8dca939f48 100644
--- a/gcc/config/riscv/predicates.md
+++ b/gcc/config/riscv/predicates.md
@@ -465,6 +465,10 @@
   (ior (match_operand 0 "const_int6_operand")
        (match_operand 0 "register_operand")))
 
+(define_predicate "const_int5_operand"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
+
 (define_predicate "const_int5s_operand"
   (and (match_code "const_int")
        (match_test "IN_RANGE (INTVAL (op), -16, 15)")))
@@ -697,3 +701,41 @@
 (define_predicate "reg_or_const_int_operand"
   (ior (match_operand 0 "const_int_operand")
        (match_operand 0 "register_operand")))
+
+;; Branch-on-bit for AndesPerf.
+(define_predicate "ads_branch_bbcs_operand"
+  (match_code "const_int")
+{
+  if (TARGET_XANDESPERF && (INTVAL (op) >= 0))
+    {
+      if (TARGET_64BIT && INTVAL (op) <= 63)
+	return true;
+      else if (INTVAL (op) <=31)
+	return true;
+      else
+	return false;
+    }
+
+  return false;
+})
+
+;; Branch on small immediate range.
+(define_predicate "ads_branch_bimm_operand"
+  (match_code "const_int")
+{
+  if (TARGET_XANDESPERF)
+    return satisfies_constraint_Ou07 (op);
+  else
+    return false;
+})
+
+(define_predicate "ads_imm_extract_operand"
+  (match_test "satisfies_constraint_ads__Bext (op)"))
+
+(define_predicate "ads_extract_size_imm_si"
+  (and (match_code "const_int")
+	   (match_test "IN_RANGE (INTVAL (op), 1, 32)")))
+
+(define_predicate "ads_extract_size_imm_di"
+  (and (match_code "const_int")
+	   (match_test "IN_RANGE (INTVAL (op), 1, 64)")))
diff --git a/gcc/config/riscv/riscv-builtins.cc b/gcc/config/riscv/riscv-builtins.cc
index 9f8a9806bd94..8b081e240be4 100644
--- a/gcc/config/riscv/riscv-builtins.cc
+++ b/gcc/config/riscv/riscv-builtins.cc
@@ -137,6 +137,10 @@ AVAIL (cvalu, TARGET_XCVALU && !TARGET_64BIT)
 AVAIL (cvelw, TARGET_XCVELW && !TARGET_64BIT)
 AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT)
 
+/* ANDES AVAIL.  */
+AVAIL (andesperf32, !TARGET_64BIT && TARGET_XANDESPERF)
+AVAIL (andesperf64, TARGET_64BIT && TARGET_XANDESPERF)
+
 /* Construct a riscv_builtin_description from the given arguments.
 
    INSN is the name of the associated instruction pattern, without the
@@ -193,6 +197,8 @@ AVAIL (cvsimd, TARGET_XCVSIMD && !TARGET_64BIT)
 #define RISCV_ATYPE_SI intSI_type_node
 #define RISCV_ATYPE_VOID_PTR ptr_type_node
 #define RISCV_ATYPE_INT_PTR integer_ptr_type_node
+#define RISCV_ATYPE_ULONG long_unsigned_type_node
+#define RISCV_ATYPE_LONG long_integer_type_node
 
 /* RISCV_FTYPE_ATYPESN takes N RISCV_FTYPES-like type codes and lists
    their associated RISCV_ATYPEs.  */
@@ -212,6 +218,7 @@ static const struct riscv_builtin_description riscv_builtins[] = {
   #include "riscv-cmo.def"
   #include "riscv-scalar-crypto.def"
   #include "corev.def"
+  #include "andes.def"
 
   DIRECT_BUILTIN (frflags, RISCV_USI_FTYPE, hard_float),
   DIRECT_NO_TARGET_BUILTIN (fsflags, RISCV_VOID_FTYPE_USI, hard_float),
diff --git a/gcc/config/riscv/riscv-ftypes.def b/gcc/config/riscv/riscv-ftypes.def
index f7854dd996bc..fd1314d9d975 100644
--- a/gcc/config/riscv/riscv-ftypes.def
+++ b/gcc/config/riscv/riscv-ftypes.def
@@ -52,6 +52,7 @@ DEF_RISCV_FTYPE (2, (UDI, UDI, USI))
 DEF_RISCV_FTYPE (2, (UDI, UDI, UDI))
 DEF_RISCV_FTYPE (2, (SI, USI, USI))
 DEF_RISCV_FTYPE (2, (SI, SI, SI))
+DEF_RISCV_FTYPE (2, (LONG, ULONG, ULONG))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, UQI))
 DEF_RISCV_FTYPE (3, (USI, USI, USI, QI))
 DEF_RISCV_FTYPE (3, (USI, USI, UQI, USI))
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index bbc7547d385f..1bf507d18c3b 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -3912,6 +3912,10 @@ riscv_extend_cost (rtx op, bool unsigned_p)
   if (MEM_P (op))
     return 0;
 
+  /* Andes bfo patterns.  */
+  if (TARGET_XANDESPERF)
+    return COSTS_N_INSNS (1);
+
   if (unsigned_p && GET_MODE (op) == QImode)
     /* We can use ANDI.  */
     return COSTS_N_INSNS (1);
@@ -4197,6 +4201,12 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
       return false;
 
     case AND:
+      /* Andes bfo patterns.  */
+      if (TARGET_XANDESPERF && GET_CODE (XEXP (x, 0)) == ASHIFT)
+	{
+	  *total = COSTS_N_INSNS (1);
+	  return true;
+	}
       /* slli.uw pattern for zba.  */
       if (TARGET_ZBA && TARGET_64BIT && mode == DImode
 	  && GET_CODE (XEXP (x, 0)) == ASHIFT)
@@ -4256,6 +4266,13 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
       return false;
 
     case ZERO_EXTRACT:
+      /* Andes bbcs patterns.  */
+      if (TARGET_XANDESPERF
+	  && (outer_code == NE || outer_code == EQ))
+	{
+	  *total = 0;
+	  return true;
+	}
       /* This is an SImode shift.  */
       if (outer_code == SET
 	  && CONST_INT_P (XEXP (x, 1))
@@ -4283,6 +4300,12 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	  *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
 	  return true;
 	}
+      /* Andes bfo patterns.  */
+      if (TARGET_XANDESPERF)
+	{
+	  *total = COSTS_N_INSNS (1);
+	  return true;
+	}
       return false;
 
     case ASHIFT:
@@ -4451,6 +4474,15 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
 	  } while (false);
 	}
 
+      /* Andes lea patterns.  */
+      if (TARGET_XANDESPERF &&
+	  ((TARGET_64BIT && GET_CODE (XEXP (x, 0)) == AND)
+	   || GET_CODE (XEXP (x, 0)) == ASHIFT))
+	{
+	  *total = COSTS_N_INSNS (1);
+	  return true;
+	}
+
       if (float_mode_p)
 	*total = tune_param->fp_add[mode == DFmode];
       else
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 893c925b6b94..15a2c1177616 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1891,6 +1891,7 @@
 	(zero_extend:DI
 	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
   "TARGET_64BIT && !TARGET_ZBA && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+   && !TARGET_XANDESPERF
    && !(REG_P (operands[1]) && VL_REG_P (REGNO (operands[1])))"
   "@
    #
@@ -1917,7 +1918,8 @@
   [(set (match_operand:GPR    0 "register_operand"     "=r,r")
 	(zero_extend:GPR
 	    (match_operand:HI 1 "nonimmediate_operand" " r,m")))]
-  "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
+  "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+   && !TARGET_XANDESPERF"
   "@
    #
    lhu\t%0,%1"
@@ -1979,7 +1981,7 @@
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
 	(sign_extend:DI
 	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
-  "TARGET_64BIT && !TARGET_XTHEADMEMIDX"
+  "TARGET_64BIT && !TARGET_XTHEADMEMIDX && !TARGET_XANDESPERF"
   "@
    sext.w\t%0,%1
    lw\t%0,%1"
@@ -1996,7 +1998,8 @@
   [(set (match_operand:SUPERQI   0 "register_operand"     "=r,r")
 	(sign_extend:SUPERQI
 	    (match_operand:SHORT 1 "nonimmediate_operand" " r,m")))]
-  "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX"
+  "!TARGET_ZBB && !TARGET_XTHEADBB && !TARGET_XTHEADMEMIDX
+   && !TARGET_XANDESPERF"
   "@
    #
    l<SHORT:size>\t%0,%1"
@@ -3076,6 +3079,7 @@
       || TARGET_XVENTANACONDOPS || TARGET_SFB_ALU)
      && (INTVAL (operands[2]) == 1))
    && !TARGET_XTHEADBB
+   && !TARGET_XANDESPERF
    && !(TARGET_64BIT
         && (INTVAL (operands[3]) > 0)
         && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
@@ -3461,9 +3465,9 @@
 	    (label_ref (match_operand 1))
 	    (pc)))
    (clobber (match_scratch:X 4 "=&r"))]
-  ""
-  "#"
-  "reload_completed"
+   "!TARGET_XANDESPERF"
+   "#"
+   "&& reload_completed"
   [(set (match_dup 4)
 	(ashift:X (match_dup 2) (match_dup 3)))
    (set (pc)
@@ -4886,3 +4890,4 @@
 (include "sifive-p600.md")
 (include "generic-vector-ooo.md")
 (include "generic-ooo.md")
+(include "andes.md")
diff --git a/gcc/config/riscv/vector-iterators.md b/gcc/config/riscv/vector-iterators.md
index 0e1318d1447c..0e81a2440f39 100644
--- a/gcc/config/riscv/vector-iterators.md
+++ b/gcc/config/riscv/vector-iterators.md
@@ -4306,7 +4306,7 @@
 			      (umax "%3,%4")
 			      (mult "%3,%4")])
 
-(define_code_attr sz [(sign_extend "s") (zero_extend "z")])
+(define_code_attr sz [(sign_extend "s") (zero_extend "z") (sign_extract "s") (zero_extract "z")])
 
 ;; VLS modes that has NUNITS < 32.
 (define_mode_iterator VLS_AVL_IMM [
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-1.c b/gcc/testsuite/gcc.target/riscv/xandesperf-1.c
new file mode 100644
index 000000000000..503991416b55
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-1.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long cond)
+{
+  if (cond != 63)
+    cond += 10;
+  return cond;
+}
+
+/* { dg-final { scan-assembler {\mnds.beqc} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-10.c b/gcc/testsuite/gcc.target/riscv/xandesperf-10.c
new file mode 100644
index 000000000000..6f6598f88274
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-10.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+
+long
+test_nds_ffb (unsigned long a, unsigned long b)
+{
+  return __builtin_riscv_nds_ffb (a, b);
+}
+
+long
+test_nds_ffzmism (unsigned long a, unsigned long b)
+{
+  return __builtin_riscv_nds_ffzmism (a, b);
+}
+
+long
+test_nds_ffmism (unsigned long a, unsigned long b)
+{
+  return __builtin_riscv_nds_ffmism (a, b);
+}
+
+long
+test_nds_flmism (unsigned long a, unsigned long b)
+{
+  return __builtin_riscv_nds_flmism (a, b);
+}
+
+/* { dg-final { scan-assembler-times {nds\.ffb} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffzmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.ffmism} 1 } } */
+/* { dg-final { scan-assembler-times {nds\.flmism} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-2.c b/gcc/testsuite/gcc.target/riscv/xandesperf-2.c
new file mode 100644
index 000000000000..786cb7a64d2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long cond)
+{
+  if (cond & (1 << 30))
+    cond -= 10;
+  return cond;
+}
+
+/* { dg-final { scan-assembler {\mnds.bbc} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-3.c b/gcc/testsuite/gcc.target/riscv/xandesperf-3.c
new file mode 100644
index 000000000000..f5dfe2803b58
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+unsigned long foo (long a)
+{
+  unsigned int lala = a;
+  return lala;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfoz} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-4.c b/gcc/testsuite/gcc.target/riscv/xandesperf-4.c
new file mode 100644
index 000000000000..f49c19c08f97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+unsigned short foo (long a)
+{
+  return (unsigned short) a;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfoz} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-5.c b/gcc/testsuite/gcc.target/riscv/xandesperf-5.c
new file mode 100644
index 000000000000..fed87461794c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-5.c
@@ -0,0 +1,11 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long a)
+{
+  int lala = a;
+  return lala;
+}
+
+/* { dg-final { scan-assembler {\mnds.bfos} } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-6.c b/gcc/testsuite/gcc.target/riscv/xandesperf-6.c
new file mode 100644
index 000000000000..56afdd979a52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-6.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+short foo (long a)
+{
+  short lala = a;
+  return lala;
+}
+
+signed char foo1 (long a)
+{
+  signed char lala = a;
+  return lala;
+}
+
+/* { dg-final { scan-assembler-times {\mnds.bfos} 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-7.c b/gcc/testsuite/gcc.target/riscv/xandesperf-7.c
new file mode 100644
index 000000000000..b5d0ab9dfd21
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-7.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+long foo (long a)
+{
+  return (a & 0xffe0) >> 5;
+}
+
+unsigned long foo1 (unsigned long a)
+{
+  return (a & 0xffe0) >> 5;
+}
+
+signed char foo2 (long a)
+{
+  return (signed char) ((a & 0xff00) >> 8);
+}
+
+/* { dg-final { scan-assembler-times {\mnds.bfoz} 2 } } */
+/* { dg-final { scan-assembler-times {\mnds.bfos} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-8.c b/gcc/testsuite/gcc.target/riscv/xandesperf-8.c
new file mode 100644
index 000000000000..e201821bfba4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-8.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_xandesperf" { target { rv64 } } } */
+/* { dg-options "-march=rv32gc_xandesperf" { target { rv32 } } } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+short *ptr_h;
+short foo_h (long a)
+{
+  return *(ptr_h + a);
+}
+
+int *ptr_i;
+int foo_i (long a)
+{
+  return *(ptr_i + a);
+}
+
+long long *ptr_d;
+long long foo_d (long a)
+{
+  return *(ptr_d + a);
+}
+
+/* { dg-final { scan-assembler-times {\mnds.lea.h} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.w} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.d} 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/xandesperf-9.c b/gcc/testsuite/gcc.target/riscv/xandesperf-9.c
new file mode 100644
index 000000000000..1eadb10f52c1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/xandesperf-9.c
@@ -0,0 +1,31 @@
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-march=rv64gc_xandesperf" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+char *ptr_ub;
+char foo_ub (unsigned int a)
+{
+  return *(ptr_ub + a);
+}
+
+short *ptr_uh;
+short foo_uh (unsigned int a)
+{
+  return *(ptr_uh + a);
+}
+
+int *ptr_ui;
+int foo_ui (unsigned int a)
+{
+  return *(ptr_ui + a);
+}
+
+long long *ptr_ud;
+long long foo_ud (unsigned int a)
+{
+  return *(ptr_ud + a);
+}
+/* { dg-final { scan-assembler-times {\mnds.lea.b.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.h.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.w.ze} 1 } } */
+/* { dg-final { scan-assembler-times {\mnds.lea.d.ze} 1 } } */
-- 
2.34.1

