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

Reply via email to