]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/config/xtensa/xtensa.h
Update copyright years.
[thirdparty/gcc.git] / gcc / config / xtensa / xtensa.h
index 58eb1b2604a73a7db9530185f667fda6f8b0df13..9591b3d4b40055faa0c8afe79ccfaf771e607e77 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of Tensilica's Xtensa target machine for GNU compiler.
-   Copyright (C) 2001-2016 Free Software Foundation, Inc.
+   Copyright (C) 2001-2024 Free Software Foundation, Inc.
    Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
 
 This file is part of GCC.
@@ -19,27 +19,12 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 /* Get Xtensa configuration settings */
-#include "xtensa-config.h"
+#include "xtensa-dynconfig.h"
 
-/* External variables defined in xtensa.c.  */
+/* External variables defined in xtensa.cc.  */
 
 /* Macros used in the machine description to select various Xtensa
    configuration options.  */
-#ifndef XCHAL_HAVE_MUL32_HIGH
-#define XCHAL_HAVE_MUL32_HIGH 0
-#endif
-#ifndef XCHAL_HAVE_RELEASE_SYNC
-#define XCHAL_HAVE_RELEASE_SYNC 0
-#endif
-#ifndef XCHAL_HAVE_S32C1I
-#define XCHAL_HAVE_S32C1I 0
-#endif
-#ifndef XCHAL_HAVE_THREADPTR
-#define XCHAL_HAVE_THREADPTR 0
-#endif
-#ifndef XCHAL_HAVE_FP_POSTINC
-#define XCHAL_HAVE_FP_POSTINC 0
-#endif
 #define TARGET_BIG_ENDIAN      XCHAL_HAVE_BE
 #define TARGET_DENSITY         XCHAL_HAVE_DENSITY
 #define TARGET_MAC16           XCHAL_HAVE_MAC16
@@ -50,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #define TARGET_NSA             XCHAL_HAVE_NSA
 #define TARGET_MINMAX          XCHAL_HAVE_MINMAX
 #define TARGET_SEXT            XCHAL_HAVE_SEXT
+#define TARGET_CLAMPS          XCHAL_HAVE_CLAMPS
 #define TARGET_BOOLEANS                XCHAL_HAVE_BOOLEANS
 #define TARGET_HARD_FLOAT      XCHAL_HAVE_FP
 #define TARGET_HARD_FLOAT_DIV  XCHAL_HAVE_FP_DIV
@@ -63,22 +49,29 @@ along with GCC; see the file COPYING3.  If not see
 #define TARGET_S32C1I          XCHAL_HAVE_S32C1I
 #define TARGET_ABSOLUTE_LITERALS XSHAL_USE_ABSOLUTE_LITERALS
 #define TARGET_THREADPTR       XCHAL_HAVE_THREADPTR
-#define TARGET_LOOPS           XCHAL_HAVE_LOOPS
-#define TARGET_WINDOWED_ABI    (XSHAL_ABI == XTHAL_ABI_WINDOWED)
+#define TARGET_LOOPS           XCHAL_HAVE_LOOPS
+#define TARGET_WINDOWED_ABI_DEFAULT (XSHAL_ABI == XTHAL_ABI_WINDOWED)
+#define TARGET_WINDOWED_ABI    xtensa_windowed_abi
 #define TARGET_DEBUG           XCHAL_HAVE_DEBUG
+#define TARGET_L32R            XCHAL_HAVE_L32R
+#define TARGET_SALT            (XTENSA_MARCH_EARLIEST >= 270000)
 
-#define TARGET_DEFAULT \
-  ((XCHAL_HAVE_L32R    ? 0 : MASK_CONST16) |                           \
-   MASK_SERIALIZE_VOLATILE)
+#define TARGET_DEFAULT (MASK_SERIALIZE_VOLATILE)
 
 #ifndef HAVE_AS_TLS
 #define HAVE_AS_TLS 0
 #endif
 
+/* Define this if the target has no hardware divide instructions.  */
+#if !__XCHAL_HAVE_DIV32
+#define TARGET_HAS_NO_HW_DIVIDE
+#endif
+
 \f
 /* Target CPU builtins.  */
 #define TARGET_CPU_CPP_BUILTINS()                                      \
   do {                                                                 \
+    const char **builtin;                                              \
     builtin_assert ("cpu=xtensa");                                     \
     builtin_assert ("machine=xtensa");                                 \
     builtin_define ("__xtensa__");                                     \
@@ -88,6 +81,8 @@ along with GCC; see the file COPYING3.  If not see
     builtin_define (TARGET_BIG_ENDIAN ? "__XTENSA_EB__" : "__XTENSA_EL__"); \
     if (!TARGET_HARD_FLOAT)                                            \
       builtin_define ("__XTENSA_SOFT_FLOAT__");                                \
+    for (builtin = xtensa_get_config_strings (); *builtin; ++builtin)  \
+      builtin_define (*builtin);                                       \
   } while (0)
 
 #define CPP_SPEC " %(subtarget_cpp_spec) "
@@ -149,7 +144,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
-#define STRICT_ALIGNMENT 1
+#define STRICT_ALIGNMENT (xtensa_strict_alignment)
 
 /* Promote integer modes smaller than a word to SImode.  Set UNSIGNEDP
    for QImode, because there is no 8-bit load from memory with sign
@@ -170,17 +165,6 @@ along with GCC; see the file COPYING3.  If not see
    bitfields and the structures that contain them.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
 
-/* Align string constants and constructors to at least a word boundary.
-   The typical use of this macro is to increase alignment for string
-   constants to be word aligned so that 'strcpy' calls that copy
-   constants can be done inline.  */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN)                                 \
-  (!optimize_size &&                                                   \
-   (TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR)   \
-   && (ALIGN) < BITS_PER_WORD                                          \
-       ? BITS_PER_WORD                                                 \
-       : (ALIGN))
-
 /* Align arrays, unions and records to at least a word boundary.
    One use of this macro is to increase alignment of medium-size
    data to make it all fit in fewer cache lines.  Another is to
@@ -222,7 +206,7 @@ along with GCC; see the file COPYING3.  If not see
 #define FIRST_PSEUDO_REGISTER 36
 
 /* Return the stabs register number to use for REGNO.  */
-#define DBX_REGISTER_NUMBER(REGNO) xtensa_dbx_register_number (REGNO)
+#define DEBUGGER_REGNO(REGNO) xtensa_debugger_regno (REGNO)
 
 /* 1 for registers that have pervasive standard uses
    and are not available for the register allocator.  */
@@ -235,7 +219,7 @@ along with GCC; see the file COPYING3.  If not see
 }
 
 /* 1 for registers not available across function calls.
-   These must include the FIXED_REGISTERS and also any
+   These need not include the FIXED_REGISTERS but must any
    registers that can be used without being saved.
    The latter must include the registers where values are returned
    and the register where structure-value addresses are passed.
@@ -248,52 +232,29 @@ along with GCC; see the file COPYING3.  If not see
 
    Proper values are computed in TARGET_CONDITIONAL_REGISTER_USAGE.  */
 
-#define CALL_USED_REGISTERS                                            \
+#define CALL_REALLY_USED_REGISTERS                                     \
 {                                                                      \
-  1, 1, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 2, 2, 2, 2,                      \
-  1, 1, 1,                                                             \
+  1, 0, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 2, 2, 2, 2,                      \
+  0, 0, 1,                                                             \
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,                      \
   1,                                                                   \
 }
 
-/* For non-leaf procedures on Xtensa processors, the allocation order
-   is as specified below by REG_ALLOC_ORDER.  For leaf procedures, we
-   want to use the lowest numbered registers first to minimize
-   register window overflows.  However, local-alloc is not smart
-   enough to consider conflicts with incoming arguments.  If an
-   incoming argument in a2 is live throughout the function and
-   local-alloc decides to use a2, then the incoming argument must
-   either be spilled or copied to another register.  To get around
-   this, we define ADJUST_REG_ALLOC_ORDER to redefine
-   reg_alloc_order for leaf functions such that lowest numbered
-   registers are used first with the exception that the incoming
-   argument registers are not used until after other register choices
-   have been exhausted.  */
-
-#define REG_ALLOC_ORDER \
-{  8,  9, 10, 11, 12, 13, 14, 15,  7,  6,  5,  4,  3,  2, \
-  18, \
-  19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, \
-   0,  1, 16, 17, \
-  35, \
-}
-
-#define ADJUST_REG_ALLOC_ORDER order_regs_for_local_alloc ()
+/* For the windowed register ABI on Xtensa processors, the allocation
+   order is as specified below by REG_ALLOC_ORDER.
+   For the call0 ABI, on the other hand, ADJUST_REG_ALLOC_ORDER hook
+   will be called once at the start of IRA, replacing it with the
+   appropriate one.  */
 
-/* For Xtensa, the only point of this is to prevent GCC from otherwise
-   giving preference to call-used registers.  To minimize window
-   overflows for the AR registers, we want to give preference to the
-   lower-numbered AR registers.  For other register files, which are
-   not windowed, we still prefer call-used registers, if there are any.  */
-extern const char xtensa_leaf_regs[FIRST_PSEUDO_REGISTER];
-#define LEAF_REGISTERS xtensa_leaf_regs
-
-/* For Xtensa, no remapping is necessary, but this macro must be
-   defined if LEAF_REGISTERS is defined.  */
-#define LEAF_REG_REMAP(REGNO) (REGNO)
-
-/* This must be declared if LEAF_REGISTERS is set.  */
-extern int leaf_function;
+#define REG_ALLOC_ORDER                                                        \
+{                                                                      \
+   8,  9, 10, 11, 12, 13, 14, 15,  7,  6,  5,  4,  3,  2,              \
+  18,                                                                  \
+  19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,      \
+   0,  1, 16, 17,                                                      \
+  35,                                                                  \
+}
+#define ADJUST_REG_ALLOC_ORDER xtensa_adjust_reg_alloc_order ()
 
 /* Internal macros to classify a register number.  */
 
@@ -304,7 +265,7 @@ extern int leaf_function;
 
 /* Coprocessor registers */
 #define BR_REG_FIRST 18
-#define BR_REG_LAST  18 
+#define BR_REG_LAST  18
 #define BR_REG_NUM   (BR_REG_LAST - BR_REG_FIRST + 1)
 
 /* 16 floating-point registers */
@@ -322,36 +283,17 @@ extern int leaf_function;
 #define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
 #define ACC_REG_P(REGNO) ((unsigned) ((REGNO) - ACC_REG_FIRST) < ACC_REG_NUM)
 
-/* Return number of consecutive hard regs needed starting at reg REGNO
-   to hold something of mode MODE.  */
-#define HARD_REGNO_NREGS(REGNO, MODE)                                  \
-  (FP_REG_P (REGNO) ?                                                  \
-       ((GET_MODE_SIZE (MODE) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG) : \
-       ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode
-   MODE.  */
-extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
-
-#define HARD_REGNO_MODE_OK(REGNO, MODE)                                        \
-  xtensa_hard_regno_mode_ok[(int) (MODE)][(REGNO)]
-
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
-   for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)                                  \
-  ((GET_MODE_CLASS (MODE1) == MODE_FLOAT ||                            \
-    GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)                      \
-   == (GET_MODE_CLASS (MODE2) == MODE_FLOAT ||                         \
-       GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
-
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM (GP_REG_FIRST + 1)
 
 /* Base register for access to local variables of the function.  */
-#define HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + \
-                                  (TARGET_WINDOWED_ABI ? 7 : 15))
+#define HARD_FRAME_POINTER_REGNUM \
+  (TARGET_WINDOWED_ABI \
+   ? XTENSA_WINDOWED_HARD_FRAME_POINTER_REGNUM \
+   : XTENSA_CALL0_HARD_FRAME_POINTER_REGNUM)
+
+#define XTENSA_WINDOWED_HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 7)
+#define XTENSA_CALL0_HARD_FRAME_POINTER_REGNUM (GP_REG_FIRST + 15)
 
 /* The register number of the frame pointer register, which is used to
    access automatic variables in the stack frame.  For Xtensa, this
@@ -362,6 +304,12 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM (GP_REG_FIRST + 17)
 
+/* Hard frame pointer is neither frame nor arg pointer.
+   The definitions are here because actual hard frame pointer register
+   definition is not a preprocessor constant.  */
+#define HARD_FRAME_POINTER_IS_FRAME_POINTER 0
+#define HARD_FRAME_POINTER_IS_ARG_POINTER 0
+
 /* For now we don't try to use the full set of boolean registers.  Without
    software pipelining of FP operations, there's not much to gain and it's
    a real pain to get them reloaded.  */
@@ -397,6 +345,7 @@ enum reg_class
   FP_REGS,                     /* floating point registers */
   ACC_REG,                     /* MAC16 accumulator */
   SP_REG,                      /* sp register (aka a1) */
+  ISC_REGS,                    /* registers for indirect sibling calls */
   RL_REGS,                     /* preferred reload regs (not sp or fp) */
   GR_REGS,                     /* integer registers except sp */
   AR_REGS,                     /* all integer registers */
@@ -418,6 +367,7 @@ enum reg_class
   "FP_REGS",                                                           \
   "ACC_REG",                                                           \
   "SP_REG",                                                            \
+  "ISC_REGS",                                                          \
   "RL_REGS",                                                           \
   "GR_REGS",                                                           \
   "AR_REGS",                                                           \
@@ -434,6 +384,7 @@ enum reg_class
   { 0xfff80000, 0x00000007 }, /* floating-point registers */ \
   { 0x00000000, 0x00000008 }, /* MAC16 accumulator */ \
   { 0x00000002, 0x00000000 }, /* stack pointer register */ \
+  { 0x000001fc, 0x00000000 }, /* registers for indirect sibling calls */ \
   { 0x0000fffd, 0x00000000 }, /* preferred reload registers */ \
   { 0x0000fffd, 0x00000000 }, /* general-purpose registers */ \
   { 0x0003ffff, 0x00000000 }, /* integer registers */ \
@@ -460,34 +411,25 @@ enum reg_class
 
 #define STACK_GROWS_DOWNWARD 1
 
-/* Offset within stack frame to start allocating local variables at.  */
-#define STARTING_FRAME_OFFSET                                          \
-  crtl->outgoing_args_size
+#define FRAME_GROWS_DOWNWARD (flag_stack_protect \
+                             || (flag_sanitize & SANITIZE_ADDRESS) != 0)
 
 /* The ARG_POINTER and FRAME_POINTER are not real Xtensa registers, so
-   they are eliminated to either the stack pointer or hard frame pointer.  */
-#define ELIMINABLE_REGS                                                        \
-{{ ARG_POINTER_REGNUM,         STACK_POINTER_REGNUM},                  \
- { ARG_POINTER_REGNUM,         HARD_FRAME_POINTER_REGNUM},             \
- { FRAME_POINTER_REGNUM,       STACK_POINTER_REGNUM},                  \
- { FRAME_POINTER_REGNUM,       HARD_FRAME_POINTER_REGNUM}}
+   they are eliminated to either the stack pointer or hard frame pointer.
+   Since hard frame pointer is different register in windowed and call0
+   ABIs list them both and only allow real HARD_FRAME_POINTER_REGNUM in
+   TARGET_CAN_ELIMINATE.  */
+#define ELIMINABLE_REGS                                                            \
+{{ ARG_POINTER_REGNUM,         STACK_POINTER_REGNUM},                      \
+ { ARG_POINTER_REGNUM,         XTENSA_WINDOWED_HARD_FRAME_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM,         XTENSA_CALL0_HARD_FRAME_POINTER_REGNUM},    \
+ { FRAME_POINTER_REGNUM,       STACK_POINTER_REGNUM},                      \
+ { FRAME_POINTER_REGNUM,       XTENSA_WINDOWED_HARD_FRAME_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM,       XTENSA_CALL0_HARD_FRAME_POINTER_REGNUM}}
 
 /* Specify the initial difference between the specified pair of registers.  */
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET)                   \
-  do {                                                                 \
-    long frame_size = compute_frame_size (get_frame_size ());          \
-    switch (FROM)                                                      \
-      {                                                                        \
-      case FRAME_POINTER_REGNUM:                                       \
-        (OFFSET) = 0;                                                  \
-       break;                                                          \
-      case ARG_POINTER_REGNUM:                                         \
-        (OFFSET) = frame_size;                                         \
-       break;                                                          \
-      default:                                                         \
-       gcc_unreachable ();                                             \
-      }                                                                        \
-  } while (0)
+  (OFFSET) = xtensa_initial_elimination_offset ((FROM), (TO))
 
 /* If defined, the maximum amount of space required for outgoing
    arguments will be computed and placed into the variable
@@ -511,7 +453,8 @@ enum reg_class
 
 /* Symbolic macros for the registers used to return integer, floating
    point, and values of coprocessor and user-defined modes.  */
-#define GP_RETURN (GP_REG_FIRST + 2 + WINDOW_SIZE)
+#define GP_RETURN_FIRST (GP_REG_FIRST + 2 + WINDOW_SIZE)
+#define GP_RETURN_LAST  (GP_RETURN_FIRST + 3)
 #define GP_OUTGOING_RETURN (GP_REG_FIRST + 2)
 
 /* Symbolic macros for the first/last argument registers.  */
@@ -532,7 +475,7 @@ enum reg_class
    used for this purpose since all function arguments are pushed on
    the stack.  */
 #define FUNCTION_ARG_REGNO_P(N)                                                \
-  ((N) >= GP_OUTGOING_ARG_FIRST && (N) <= GP_OUTGOING_ARG_LAST)
+  IN_RANGE ((N), GP_OUTGOING_ARG_FIRST, GP_OUTGOING_ARG_LAST)
 
 /* Record the number of argument words seen so far, along with a flag to
    indicate whether these are incoming arguments.  (FUNCTION_INCOMING_ARG
@@ -648,19 +591,10 @@ typedef struct xtensa_args
 /* C expressions that are nonzero if X (assumed to be a `reg' RTX) is
    valid for use as a base or index register.  */
 
-#ifdef REG_OK_STRICT
-#define REG_OK_STRICT_FLAG 1
-#else
-#define REG_OK_STRICT_FLAG 0
-#endif
-
 #define BASE_REG_P(X, STRICT)                                          \
-  ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER)                   \
+  ((!(STRICT) && ! HARD_REGISTER_P (X))                                        \
    || REGNO_OK_FOR_BASE_P (REGNO (X)))
 
-#define REG_OK_FOR_INDEX_P(X) 0
-#define REG_OK_FOR_BASE_P(X) BASE_REG_P (X, REG_OK_STRICT_FLAG)
-
 /* Maximum number of registers that can appear in a valid memory address.  */
 #define MAX_REGS_PER_ADDRESS 1
 
@@ -699,10 +633,6 @@ typedef struct xtensa_args
 /* Shift instructions ignore all but the low-order few bits.  */
 #define SHIFT_COUNT_TRUNCATED 1
 
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
-   is done just by pretending it is already truncated.  */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
 #define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = -1, 1)
 
@@ -782,7 +712,7 @@ typedef struct xtensa_args
 
 
 /* Define output to appear before the constant pool.  */
-#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE)          \
+#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE)         \
   do {                                                                 \
     if ((SIZE) > 0 || !TARGET_WINDOWED_ABI)                            \
       {                                                                        \
@@ -812,8 +742,9 @@ typedef struct xtensa_args
 #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 0)
 #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (0)
 #define DWARF_ALT_FRAME_RETURN_COLUMN 16
-#define DWARF_FRAME_REGISTERS (DWARF_ALT_FRAME_RETURN_COLUMN           \
-                              + (TARGET_WINDOWED_ABI ? 0 : 1))
+#define DWARF_FRAME_REGISTERS (TARGET_WINDOWED_ABI \
+                              ? DWARF_ALT_FRAME_RETURN_COLUMN          \
+                              : DWARF_ALT_FRAME_RETURN_COLUMN + 1)
 #define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + 2 : INVALID_REGNUM)
 #define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL)                     \
   (flag_pic                                                            \