This patch implements the backend machine description patterns and
constraints required for APEX custom instruction code generation.
The implementation provides RTL patterns covering all APEX instruction
signatures through define_insn and define_expand patterns in arcv-apex.md.
Each pattern uses UNSPEC/UNSPEC_VOLATILE to prevent unwanted optimization
of side-effecting instructions while allowing pure operations to be
optimized normally.
Mode iterators (APEX_DEST, APEX_SRC0, APEX_SRC1) generate variants for
SI/DI/SF/DF modes from a single pattern template, reducing code duplication.
Constraint predicates (xAVpXD, xAVpXS, xAVpXI, xAVpXC) validate that the
opcode index matches the instruction format at instruction selection time,
ensuring arcv_apex_asm_mnemonic can generate correct mnemonics with
format-specific suffixes when needed.
gcc/ChangeLog:
* config.gcc: Add arcv-builtins.o to extra_objs for RISC-V.
* config/riscv/constraints.md (Os08): New constraint for 8-bit signed
immediates.
(xAVpXD, xAVpXS, xAVpXI, xAVpXC): New constraints for APEX opcode
validation per instruction format.
* config/riscv/iterators.md (APEX_DEST, APEX_SRC0, APEX_SRC1): New
mode iterators for APEX instruction operands.
* config/riscv/riscv-protos.h (arcv_apex_asm_mnemonic): Declare.
(arcv_apex_format_enabled_p): Declare.
* config/riscv/riscv.h (RISCV_APEX_H): New header guard.
(enum apex_insn_format): New enum for APEX instruction formats.
* config/riscv/riscv.md: Include arcv-apex.md.
* config/riscv/t-riscv: Add build rules for arcv-builtins.o.
* config/riscv/arcv-apex.md: New file.
* config/riscv/arcv-builtins.cc: New file.
Signed-off-by: Luis Silva <[email protected]>
---
gcc/config.gcc | 1 +
gcc/config/riscv/arcv-apex.md | 367 ++++++++++++++++++++++++++++++
gcc/config/riscv/arcv-builtins.cc | 112 +++++++++
gcc/config/riscv/constraints.md | 34 +++
gcc/config/riscv/iterators.md | 6 +
gcc/config/riscv/riscv-protos.h | 5 +
gcc/config/riscv/riscv.h | 18 ++
gcc/config/riscv/riscv.md | 1 +
gcc/config/riscv/t-riscv | 7 +
9 files changed, 551 insertions(+)
create mode 100644 gcc/config/riscv/arcv-apex.md
create mode 100644 gcc/config/riscv/arcv-builtins.cc
diff --git a/gcc/config.gcc b/gcc/config.gcc
index fabd5f75f96..d5283c080cc 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -568,6 +568,7 @@ riscv*)
extra_objs="${extra_objs} riscv-v.o riscv-vsetvl.o riscv-vector-costs.o
riscv-avlprop.o riscv-vect-permconst.o"
extra_objs="${extra_objs} riscv-vector-builtins.o
riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o
sifive-vector-builtins-bases.o andes-vector-builtins-bases.o"
extra_objs="${extra_objs} thead.o riscv-target-attr.o riscv-zicfilp.o
riscv-bclr-lowest-set-bit.o riscv-opt-popretz.o riscv-fusion.o"
+ extra_objs="${extra_objs} arcv-builtins.o"
d_target_objs="riscv-d.o"
extra_headers="riscv_vector.h riscv_crypto.h riscv_bitmanip.h
riscv_th_vector.h sifive_vector.h andes_vector.h"
target_gtfiles="$target_gtfiles
\$(srcdir)/config/riscv/riscv-vector-builtins.cc"
diff --git a/gcc/config/riscv/arcv-apex.md b/gcc/config/riscv/arcv-apex.md
new file mode 100644
index 00000000000..d05d991356c
--- /dev/null
+++ b/gcc/config/riscv/arcv-apex.md
@@ -0,0 +1,367 @@
+;; Machine description for the APEX instructions
+;; Copyright (C) 2026 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" [
+
+;; ARC-V APEX
+ UNSPEC_ARCV_APEX_VOID_V
+ UNSPEC_ARCV_APEX_VOID_SRC0_V
+ UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V
+ UNSPEC_ARCV_APEX_DEST
+ UNSPEC_ARCV_APEX_DEST_V
+ UNSPEC_ARCV_APEX_DEST_SRC0
+ UNSPEC_ARCV_APEX_DEST_SRC0_V
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V
+])
+
+;; Used by XD (volatile): insn
+(define_insn "riscv_arcv_apex_void_ftype_v"
+ [(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXD")]
+ UNSPEC_ARCV_APEX_VOID_V)]
+ ""
+{
+ return xasprintf ("%s",
+ arcv_apex_asm_mnemonic (operands[0], false));
+}
+ [(set_attr "type" "arith")]
+)
+
+;; Used by XI and XD (volatile): insn src0
+(define_insn "riscv_arcv_apex_void_ftype_<APEX_SRC0:mode>_v"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXI,xAVpXD")
+ (match_operand:APEX_SRC0 1 "nonmemory_operand" "I,r")]
+ UNSPEC_ARCV_APEX_VOID_SRC0_V)]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%d",
+ arcv_apex_asm_mnemonic (operands[0], true),
+ (int) INTVAL (operands[1]));
+ case 1:
+ return xasprintf ("%s\t%s",
+ arcv_apex_asm_mnemonic (operands[0], false),
+ reg_names[REGNO (operands[1])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_void_ftype_src0_v"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand")
+ (match_operand 1 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_VOID_SRC0_V)]
+ ""
+{
+ emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
+ gen_rtvec (2, operands[0],
+ operands[1]),
+ UNSPEC_ARCV_APEX_VOID_SRC0_V));
+ DONE;
+})
+
+;; Used by XS and XD (volatile): insn src0, src1
+(define_insn "riscv_arcv_apex_void_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>_v"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXS,xAVpXD")
+ (match_operand:APEX_SRC0 1 "register_operand" "r,r")
+ (match_operand:APEX_SRC1 2 "nonmemory_operand"
"Os08,r")]
+ UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%s,%d",
+ arcv_apex_asm_mnemonic (operands[0], true),
+ reg_names[REGNO (operands[1])],
+ (int) INTVAL (operands[2]));
+ case 1:
+ return xasprintf ("%s\t%s,%s",
+ arcv_apex_asm_mnemonic (operands[0], false),
+ reg_names[REGNO (operands[1])],
+ reg_names[REGNO (operands[2])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_void_ftype_src0_src1_v"
+ [(unspec_volatile [(match_operand:SI 0 "const_int_operand")
+ (match_operand 1 "register_operand")
+ (match_operand 2 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
+ ""
+{
+ emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
+ gen_rtvec (3, operands[0],
+ operands[1],
+ operands[2]),
+ UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V));
+ DONE;
+})
+
+;; Used by XD (volatile): insn rd
+(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_v"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r")
+ (unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand"
"xAVpXD")]
+ UNSPEC_ARCV_APEX_DEST_V))]
+ ""
+{
+ return xasprintf ("%s\t%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])]);
+}
+ [(set_attr "type" "arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype_v"
+ [(set (match_operand 0 "register_operand")
+ (unspec_volatile [(match_operand:SI 1 "const_int_operand")]
+ UNSPEC_ARCV_APEX_DEST_V))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
+ gen_rtvec (1, operands[1]),
+ UNSPEC_ARCV_APEX_DEST_V)));
+ DONE;
+})
+
+;; Used by XD: insn rd
+(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r")
+ (unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
+ UNSPEC_ARCV_APEX_DEST))]
+ ""
+{
+ return xasprintf ("%s\t%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])]);
+}
+ [(set_attr "type" "arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype"
+ [(set (match_operand 0 "register_operand")
+ (unspec [(match_operand:SI 1 "const_int_operand")]
+ UNSPEC_ARCV_APEX_DEST))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC (GET_MODE (operands[0]),
+ gen_rtvec (1, operands[1]),
+ UNSPEC_ARCV_APEX_DEST)));
+ DONE;
+})
+
+;; Used by XI and XD (volatile): insn rd, src0
+(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_v"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r,r")
+ (unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand"
"xAVpXI,xAVpXD")
+ (match_operand:APEX_SRC0 2 "nonmemory_operand" "I,r")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_V))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ (int) INTVAL (operands[2]));
+ case 1:
+ return xasprintf ("%s\t%s,%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype_src0_v"
+ [(set (match_operand 0 "register_operand")
+ (unspec_volatile [(match_operand:SI 1 "const_int_operand")
+ (match_operand 2 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_V))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
+ gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_ARCV_APEX_DEST_SRC0_V)));
+ DONE;
+})
+
+;; Used by XI and XD: insn rd, src0
+(define_insn "riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r,r")
+ (unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand"
"xAVpXI,xAVpXD")
+ (match_operand:APEX_SRC0 2 "nonmemory_operand" "I,r")]
+ UNSPEC_ARCV_APEX_DEST_SRC0))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ (int) INTVAL (operands[2]));
+ case 1:
+ return xasprintf ("%s\t%s,%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype_src0"
+ [(set (match_operand 0 "register_operand")
+ (unspec [(match_operand:SI 1 "const_int_operand")
+ (match_operand 2 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_DEST_SRC0))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC (GET_MODE (operands[0]),
+ gen_rtvec (2, operands[1],
+ operands[2]),
+ UNSPEC_ARCV_APEX_DEST_SRC0)));
+ DONE;
+})
+
+;; Used by XS, XC and XD (volatile): insn rd, src0, imm/src1
+(define_insn
"riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>_v"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r,r,r")
+ (unspec_volatile:APEX_DEST [(match_operand:SI 1 "const_int_operand"
"xAVpXS,xAVpXC,xAVpXD")
+ (match_operand:APEX_SRC0 2 "register_operand" "r,0,r")
+ (match_operand:APEX_SRC1 3 "nonmemory_operand" "Os08,I,r")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%s,%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ (int) INTVAL (operands[3]));
+ case 1:
+ return xasprintf ("%s\t%s,%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ (int) INTVAL (operands[3]));
+ case 2:
+ return xasprintf ("%s\t%s,%s,%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ reg_names[REGNO (operands[3])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype_src0_src1_v"
+ [(set (match_operand 0 "register_operand")
+ (unspec_volatile [(match_operand:SI 1 "const_int_operand")
+ (match_operand 2 "register_operand")
+ (match_operand 3 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
+ gen_rtvec (3, operands[1],
+ operands[2],
+ operands[3]),
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V)));
+ DONE;
+})
+
+;; Used by XS, XC and XD: insn rd, src0, imm/src1
+(define_insn
"riscv_arcv_apex_<APEX_DEST:mode>_ftype_<APEX_SRC0:mode>_<APEX_SRC1:mode>"
+ [(set (match_operand:APEX_DEST 0 "register_operand" "=r,r,r")
+ (unspec:APEX_DEST [(match_operand:SI 1 "const_int_operand"
"xAVpXS,xAVpXC,xAVpXD")
+ (match_operand:APEX_SRC0 2 "register_operand" "r,0,r")
+ (match_operand:APEX_SRC1 3 "nonmemory_operand" "Os08,I,r")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
+ ""
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return xasprintf ("%s\t%s,%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ (int) INTVAL (operands[3]));
+ case 1:
+ return xasprintf ("%s\t%s,%s,%d",
+ arcv_apex_asm_mnemonic (operands[1], true),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ (int) INTVAL (operands[3]));
+ case 2:
+ return xasprintf ("%s\t%s,%s,%s",
+ arcv_apex_asm_mnemonic (operands[1], false),
+ reg_names[REGNO (operands[0])],
+ reg_names[REGNO (operands[2])],
+ reg_names[REGNO (operands[3])]);
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "arith,arith,arith")]
+)
+
+(define_expand "riscv_arcv_apex_dest_ftype_src0_src1"
+ [(set (match_operand 0 "register_operand")
+ (unspec [(match_operand:SI 1 "const_int_operand")
+ (match_operand 2 "register_operand")
+ (match_operand 3 "nonmemory_operand")]
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
+ ""
+{
+ emit_insn (gen_rtx_SET (operands[0],
+ gen_rtx_UNSPEC (GET_MODE (operands[0]),
+ gen_rtvec (3, operands[1],
+ operands[2],
+ operands[3]),
+ UNSPEC_ARCV_APEX_DEST_SRC0_SRC1)));
+ DONE;
+})
diff --git a/gcc/config/riscv/arcv-builtins.cc
b/gcc/config/riscv/arcv-builtins.cc
new file mode 100644
index 00000000000..8bbfacdb34c
--- /dev/null
+++ b/gcc/config/riscv/arcv-builtins.cc
@@ -0,0 +1,112 @@
+/* ARCV (ARC RISC-V) builtin functions.
+ Copyright (C) 2026 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 IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tree.h"
+#include "gimple-expr.h"
+#include "memmodel.h"
+#include "expmed.h"
+#include "profile-count.h"
+#include "optabs.h"
+#include "recog.h"
+#include "diagnostic-core.h"
+#include "stor-layout.h"
+#include "stringpool.h"
+#include "expr.h"
+#include "langhooks.h"
+#include "tm_p.h"
+#include "backend.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+
+/* Specifies how a built-in function should be converted into rtl. */
+enum riscv_builtin_type {
+ /* The function corresponds directly to an .md pattern. */
+ RISCV_BUILTIN_DIRECT,
+
+ /* Likewise, but with return type VOID. */
+ RISCV_BUILTIN_DIRECT_NO_TARGET
+};
+
+/* This structure describes an APEX built-in function. */
+struct arcv_apex_builtin_description {
+ /* The code of the main .md file instruction. See riscv_builtin_type
+ for more information. */
+ enum insn_code icode;
+
+ /* The name of the built-in function. */
+ const char *name;
+
+ /* The assembly mnemonic of the built-in instruction. */
+ const char *mnemonic;
+
+ /* The opcode of the built-in instruction. */
+ unsigned int opcode;
+
+ /* Specifies how the function should be expanded. */
+ enum riscv_builtin_type builtin_type;
+
+ /* Specifies the instruction format. See "apex_insn_format" enum
+ for more details. */
+ unsigned int format_flags;
+};
+
+/* The XD-type has 8 function bits encoding up to 256 instructions.
+ The XS-type has 6 function bits encoding up to 64 instructions.
+ Both the XI-type and the XC-type have 5 function bits each encoding up
+ to 32 instructions respectively. Thus giving a total of 384 possible
+ different instructions. */
+static const int arcv_apex_builtins_limit = 384;
+static struct arcv_apex_builtin_description
+arcv_apex_builtins[arcv_apex_builtins_limit];
+
+/* Return the assembly mnemonic for an APEX instruction.
+ Appends "i" suffix if immediate_p is true and multiple formats exist. */
+
+const char*
+arcv_apex_asm_mnemonic (rtx op, bool immediate_p)
+{
+ unsigned int subcode = UINTVAL (op);
+ const char *base_mnemonic = arcv_apex_builtins[subcode].mnemonic;
+ unsigned int format_flags = arcv_apex_builtins[subcode].format_flags;
+
+ /* Add suffix only for immediate alternatives when XD coexists. */
+ if (immediate_p
+ && (format_flags & APEX_XD)
+ && (format_flags & (APEX_XS | APEX_XI | APEX_XC)))
+ return xasprintf ("%si", base_mnemonic);
+
+ return base_mnemonic;
+}
+
+/* Checks if the APEX builtin instruction identified by the subcode
+ supports the given instruction format. */
+
+bool
+arcv_apex_format_enabled_p (unsigned int subcode, unsigned int insn_format)
+{
+ const struct arcv_apex_builtin_description *d = &arcv_apex_builtins[subcode];
+ return (d->format_flags & insn_format);
+}
diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 673b05954e1..a84459f8e20 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -344,3 +344,37 @@
"Sequence bit extract."
(and (match_code "const_int")
(match_test "(ival & (ival + 1)) == 0")))
+
+(define_constraint "Os08"
+ "An 8-bit signed immediate."
+ (and (match_code "const_int")
+ (match_test "IN_RANGE (ival, -128, 127)")))
+
+;; These constraints check whether the APEX builtin instruction identified by
+;; the given subcode (an integer indexing into `arcv_apex_builtins`) has the
+;; specified instruction format enabled (APEX_XD, APEX_XS, APEX_XI, or
APEX_XC).
+;;
+;; The function `arcv_apex_format_enabled_p` returns true if the instruction's
+;; supported formats include the queried format.
+;;
+;; This validation is used in instruction selection to ensure the chosen
pattern
+;; matches only when the instruction supports the required format.
+(define_constraint "xAVpXD"
+ "Validate support of APEX_XD instruction format."
+ (and (match_code "const_int")
+ (match_test "arcv_apex_format_enabled_p (INTVAL (op), APEX_XD)")))
+
+(define_constraint "xAVpXS"
+ "Validate support of APEX_XS instruction format."
+ (and (match_code "const_int")
+ (match_test "arcv_apex_format_enabled_p (INTVAL (op), APEX_XS)")))
+
+(define_constraint "xAVpXI"
+ "Validate support of APEX_XI instruction format."
+ (and (match_code "const_int")
+ (match_test "arcv_apex_format_enabled_p (INTVAL (op), APEX_XI)")))
+
+(define_constraint "xAVpXC"
+ "Validate support of APEX_XC instruction format."
+ (and (match_code "const_int")
+ (match_test "arcv_apex_format_enabled_p (INTVAL (op), APEX_XC)")))
diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
index 076911e5e7f..e4bd6251b72 100644
--- a/gcc/config/riscv/iterators.md
+++ b/gcc/config/riscv/iterators.md
@@ -22,6 +22,12 @@
;; Mode Iterators
;; -------------------------------------------------------------------
+;; APEX mode iterators for instruction operands.
+;; All APEX instructions support 32/64-bit integer and float types.
+(define_mode_iterator APEX_DEST [SI DI SF DF]) ;; Destination operand
+(define_mode_iterator APEX_SRC0 [SI DI SF DF]) ;; Source operand 0
+(define_mode_iterator APEX_SRC1 [SI DI SF DF]) ;; Source operand 1
+
;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
;; from the same template.
(define_mode_iterator GPR [SI (DI "TARGET_64BIT")])
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 234d625441d..a601e7392b5 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -868,6 +868,11 @@ extern unsigned int th_int_get_mask (unsigned int);
extern unsigned int th_int_get_save_adjustment (void);
extern rtx th_int_adjust_cfi_prologue (unsigned int);
extern const char *th_asm_output_opcode (FILE *asm_out_file, const char *p);
+
+/* Routines implemented in arcv-builtins.cc. */
+extern const char* arcv_apex_asm_mnemonic (rtx, bool);
+extern bool arcv_apex_format_enabled_p (unsigned int, unsigned int);
+
#ifdef RTX_CODE
extern const char*
th_mempair_output_move (rtx[4], bool, machine_mode, RTX_CODE);
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 57c5777c34d..fc0e11009f8 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1346,4 +1346,22 @@ typedef enum {
TCACHE_HINT = 3 << 3
} CacheHint;
+#ifndef RISCV_APEX_H
+#define RISCV_APEX_H
+
+/* APEX instruction format flags. */
+enum apex_insn_format {
+ APEX_NONE = 0,
+ APEX_XD = 1 << 0,
+ APEX_XS = 1 << 1,
+ APEX_XI = 1 << 2,
+ APEX_XC = 1 << 3,
+ APEX_VOLATILE = 1 << 4,
+ APEX_VOID = 1 << 5,
+ APEX_NO_SRC0 = 1 << 6,
+ APEX_NO_SRC1 = 1 << 7,
+};
+
+#endif /* ! RISCV_APEX_H */
+
#endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 8615a2ebad4..1db4672aea7 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -5311,3 +5311,4 @@
(include "spacemit-x60.md")
(include "arcv-rmx100.md")
(include "arcv-rhx100.md")
+(include "arcv-apex.md")
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 1f06a3697b6..5968140a3c9 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -185,6 +185,13 @@ thead.o: $(srcdir)/config/riscv/thead.cc \
$(COMPILE) $<
$(POSTCOMPILE)
+arcv-builtins.o: $(srcdir)/config/riscv/arcv-builtins.cc \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
+ gimple-expr.h memmodel.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_CORE_H) \
+ stor-layout.h stringpool.h $(EXPR_H) $(TM_P_H) $(BACKEND_H)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/riscv/arcv-builtins.cc
+
riscv-zicfilp.o: $(srcdir)/config/riscv/riscv-zicfilp.cc \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
--
2.34.0