]> 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 79cd05f7fb251038760a976873397c1ecd3e9ca4..9591b3d4b40055faa0c8afe79ccfaf771e607e77 100644 (file)
@@ -1,6 +1,5 @@
 /* Definitions of Tensilica's Xtensa target machine for GNU compiler.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
-   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.
@@ -20,38 +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"
 
-/* Standard GCC variables that we reference.  */
-extern int current_function_calls_alloca;
-extern int optimize;
-
-/* External variables defined in xtensa.c.  */
-
-/* comparison type */
-enum cmp_type {
-  CMP_SI,                              /* four byte integers */
-  CMP_DI,                              /* eight byte integers */
-  CMP_SF,                              /* single precision floats */
-  CMP_DF,                              /* double precision floats */
-  CMP_MAX                              /* max comparison type */
-};
-
-extern struct rtx_def * branch_cmp[2]; /* operands for compare */
-extern enum cmp_type branch_type;      /* what type of branch to use */
-extern unsigned xtensa_current_frame_size;
+/* 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
 #define TARGET_BIG_ENDIAN      XCHAL_HAVE_BE
 #define TARGET_DENSITY         XCHAL_HAVE_DENSITY
 #define TARGET_MAC16           XCHAL_HAVE_MAC16
@@ -62,46 +35,54 @@ extern unsigned xtensa_current_frame_size;
 #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
 #define TARGET_HARD_FLOAT_RECIP        XCHAL_HAVE_FP_RECIP
 #define TARGET_HARD_FLOAT_SQRT XCHAL_HAVE_FP_SQRT
 #define TARGET_HARD_FLOAT_RSQRT        XCHAL_HAVE_FP_RSQRT
+#define TARGET_HARD_FLOAT_POSTINC XCHAL_HAVE_FP_POSTINC
 #define TARGET_ABS             XCHAL_HAVE_ABS
 #define TARGET_ADDX            XCHAL_HAVE_ADDX
 #define TARGET_RELEASE_SYNC    XCHAL_HAVE_RELEASE_SYNC
 #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_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 (MASK_SERIALIZE_VOLATILE)
+
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
 
-#define TARGET_DEFAULT (                                               \
-  (XCHAL_HAVE_L32R     ? 0 : MASK_CONST16))
-
-#define OVERRIDE_OPTIONS override_options ()
-
-/* Reordering blocks for Xtensa is not a good idea unless the compiler
-   understands the range of conditional branches.  Currently all branch
-   relaxation for Xtensa is handled in the assembler, so GCC cannot do a
-   good job of reordering blocks.  Do not enable reordering unless it is
-   explicitly requested.  */
-#define OPTIMIZATION_OPTIONS(LEVEL, SIZE)                              \
-  do                                                                   \
-    {                                                                  \
-      flag_reorder_blocks = 0;                                         \
-    }                                                                  \
-  while (0)
+/* 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__");                                     \
     builtin_define ("__XTENSA__");                                     \
-    builtin_define ("__XTENSA_WINDOWED_ABI__");                                \
+    builtin_define (TARGET_WINDOWED_ABI ?                              \
+                   "__XTENSA_WINDOWED_ABI__" : "__XTENSA_CALL0_ABI__");\
     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) "
@@ -113,16 +94,6 @@ extern unsigned xtensa_current_frame_size;
 #define EXTRA_SPECS                                                    \
   { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },
 
-#ifdef __XTENSA_EB__
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
-/* Show we can debug even without a frame pointer.  */
-#define CAN_DEBUG_WITHOUT_FP
-
-
 /* Target machine storage layout */
 
 /* Define this if most significant bit is lowest numbered
@@ -173,7 +144,7 @@ extern unsigned xtensa_current_frame_size;
 
 /* 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
@@ -194,25 +165,6 @@ extern unsigned xtensa_current_frame_size;
    bitfields and the structures that contain them.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
 
-/* Disable the use of word-sized or smaller complex modes for structures,
-   and for function arguments in particular, where they cause problems with
-   register a7.  The xtensa_copy_incoming_a7 function assumes that there is
-   a single reference to an argument in a7, but with small complex modes the
-   real and imaginary components may be extracted separately, leading to two
-   uses of the register, only one of which would be replaced.  */
-#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
-  ((MODE) == CQImode || (MODE) == CHImode)
-
-/* 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)                                 \
-  ((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
@@ -220,14 +172,14 @@ extern unsigned xtensa_current_frame_size;
    that copy constants to character arrays can be done inline.  */
 #undef DATA_ALIGNMENT
 #define DATA_ALIGNMENT(TYPE, ALIGN)                                    \
-  ((((ALIGN) < BITS_PER_WORD)                                          \
+  (!optimize_size && (((ALIGN) < BITS_PER_WORD)                                \
     && (TREE_CODE (TYPE) == ARRAY_TYPE                                 \
        || TREE_CODE (TYPE) == UNION_TYPE                               \
        || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
 
 /* Operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
-#define WORD_REGISTER_OPERATIONS
+#define WORD_REGISTER_OPERATIONS 1
 
 /* Xtensa loads are zero-extended by default.  */
 #define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
@@ -254,7 +206,7 @@ extern unsigned xtensa_current_frame_size;
 #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.  */
@@ -267,57 +219,42 @@ extern unsigned xtensa_current_frame_size;
 }
 
 /* 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.
-   Aside from that, you can include as many other registers as you like.  */
-#define CALL_USED_REGISTERS                                            \
+   Aside from that, you can include as many other registers as you like.
+
+   The value encoding is the following:
+   1: register is used by all ABIs;
+   bit 1 is set: register is used by windowed ABI;
+   bit 2 is set: register is used by call0 ABI.
+
+   Proper values are computed in TARGET_CONDITIONAL_REGISTER_USAGE.  */
+
+#define CALL_REALLY_USED_REGISTERS                                     \
 {                                                                      \
-  1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,                      \
-  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 ORDER_REGS_FOR_LOCAL_ALLOC 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 ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
-
-/* 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 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, 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.  */
 
@@ -328,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 */
@@ -346,35 +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 + 7)
+#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
@@ -382,25 +301,14 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
    either the stack pointer or the hard frame pointer.  */
 #define FRAME_POINTER_REGNUM (GP_REG_FIRST + 16)
 
-/* Value should be nonzero if functions must have frame pointers.
-   Zero means the frame pointer need not be set up (and parms
-   may be accessed via the stack pointer) in functions that seem suitable.
-   This is computed in 'reload', in reload1.c.  */
-#define FRAME_POINTER_REQUIRED xtensa_frame_pointer_required ()
-
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM (GP_REG_FIRST + 17)
 
-/* If the static chain is passed in memory, these macros provide rtx
-   giving 'mem' expressions that denote where they are stored.
-   'STATIC_CHAIN' and 'STATIC_CHAIN_INCOMING' give the locations as
-   seen by the calling and called functions, respectively.  */
-
-#define STATIC_CHAIN                                                   \
-  gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, -5 * UNITS_PER_WORD))
-
-#define STATIC_CHAIN_INCOMING                                          \
-  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -5 * UNITS_PER_WORD))
+/* 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
@@ -416,14 +324,16 @@ extern char xtensa_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
    we use a fixed window size of 8.  */
 
 #define INCOMING_REGNO(OUT)                                            \
-  ((GP_REG_P (OUT) &&                                                  \
-    ((unsigned) ((OUT) - GP_REG_FIRST) >= WINDOW_SIZE)) ?              \
-   (OUT) - WINDOW_SIZE : (OUT))
+  (TARGET_WINDOWED_ABI ?                                               \
+   ((GP_REG_P (OUT) &&                                                 \
+     ((unsigned) ((OUT) - GP_REG_FIRST) >= WINDOW_SIZE)) ?             \
+    (OUT) - WINDOW_SIZE : (OUT)) : (OUT))
 
 #define OUTGOING_REGNO(IN)                                             \
-  ((GP_REG_P (IN) &&                                                   \
-    ((unsigned) ((IN) - GP_REG_FIRST) < WINDOW_SIZE)) ?                        \
-   (IN) + WINDOW_SIZE : (IN))
+  (TARGET_WINDOWED_ABI ?                                               \
+   ((GP_REG_P (IN) &&                                                  \
+     ((unsigned) ((IN) - GP_REG_FIRST) < WINDOW_SIZE)) ?               \
+    (IN) + WINDOW_SIZE : (IN)) : (IN))
 
 
 /* Define the classes of registers for register constraints in the
@@ -435,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 */
@@ -456,6 +367,7 @@ enum reg_class
   "FP_REGS",                                                           \
   "ACC_REG",                                                           \
   "SP_REG",                                                            \
+  "ISC_REGS",                                                          \
   "RL_REGS",                                                           \
   "GR_REGS",                                                           \
   "AR_REGS",                                                           \
@@ -472,7 +384,8 @@ enum reg_class
   { 0xfff80000, 0x00000007 }, /* floating-point registers */ \
   { 0x00000000, 0x00000008 }, /* MAC16 accumulator */ \
   { 0x00000002, 0x00000000 }, /* stack pointer register */ \
-  { 0x0000ff7d, 0x00000000 }, /* preferred reload registers */ \
+  { 0x000001fc, 0x00000000 }, /* registers for indirect sibling calls */ \
+  { 0x0000fffd, 0x00000000 }, /* preferred reload registers */ \
   { 0x0000fffd, 0x00000000 }, /* general-purpose registers */ \
   { 0x0003ffff, 0x00000000 }, /* integer registers */ \
   { 0xffffffff, 0x0000000f }  /* all registers */ \
@@ -482,79 +395,45 @@ enum reg_class
    register REGNO.  In general there is more that one such class;
    choose a class which is "minimal", meaning that no smaller class
    also contains the register.  */
-extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
-
-#define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class[ (REGNO) ]
+#define REGNO_REG_CLASS(REGNO) xtensa_regno_to_class (REGNO)
 
 /* Use the Xtensa AR register file for base registers.
    No index registers.  */
 #define BASE_REG_CLASS AR_REGS
 #define INDEX_REG_CLASS NO_REGS
 
-/* SMALL_REGISTER_CLASSES is required for Xtensa, because all of the
-   16 AR registers may be explicitly used in the RTL, as either
-   incoming or outgoing arguments.  */
-#define SMALL_REGISTER_CLASSES 1
-
-#define PREFERRED_RELOAD_CLASS(X, CLASS)                               \
-  xtensa_preferred_reload_class (X, CLASS, 0)
-
-#define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS)                                \
-  xtensa_preferred_reload_class (X, CLASS, 1)
-  
-#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)                   \
-  xtensa_secondary_reload_class (CLASS, MODE, X, 0)
-
-#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)                  \
-  xtensa_secondary_reload_class (CLASS, MODE, X, 1)
-
-/* Return the maximum number of consecutive registers
-   needed to represent mode MODE in a register of class CLASS.  */
-#define CLASS_UNITS(mode, size)                                                \
-  ((GET_MODE_SIZE (mode) + (size) - 1) / (size))
-
-#define CLASS_MAX_NREGS(CLASS, MODE)                                   \
-  (CLASS_UNITS (MODE, UNITS_PER_WORD))
-
+/* The small_register_classes_for_mode_p hook must always return true for
+   Xtrnase, because all of the 16 AR registers may be explicitly used in
+   the RTL, as either incoming or outgoing arguments.  */
+#define TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P hook_bool_mode_true
 
 /* Stack layout; function entry, exit and calling.  */
 
-#define STACK_GROWS_DOWNWARD
+#define STACK_GROWS_DOWNWARD 1
 
-/* Offset within stack frame to start allocating local variables at.  */
-#define STARTING_FRAME_OFFSET                                          \
-  current_function_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}}
-
-#define CAN_ELIMINATE(FROM, TO) 1
+   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 {                                                                 \
-    compute_frame_size (get_frame_size ());                            \
-    switch (FROM)                                                      \
-      {                                                                        \
-      case FRAME_POINTER_REGNUM:                                       \
-        (OFFSET) = 0;                                                  \
-       break;                                                          \
-      case ARG_POINTER_REGNUM:                                         \
-        (OFFSET) = xtensa_current_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
-   'current_function_outgoing_args_size'.  No space will be pushed
+   'crtl->outgoing_args_size'.  No space will be pushed
    onto the stack for each call; instead, the function prologue
    should increase the stack frame size by this amount.  */
 #define ACCUMULATE_OUTGOING_ARGS 1
@@ -569,15 +448,13 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
    128-bit datatypes defined in TIE (e.g., for Vectra).  */
 #define STACK_BOUNDARY 128
 
-/* Functions do not pop arguments off the stack.  */
-#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, SIZE) 0
-
 /* Use a fixed register window size of 8.  */
-#define WINDOW_SIZE 8
+#define WINDOW_SIZE (TARGET_WINDOWED_ABI ? 8 : 0)
 
 /* 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.  */
@@ -591,49 +468,6 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 /* Don't worry about compatibility with PCC.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
-/* Define how to find the value returned by a library function
-   assuming the value has mode MODE.  Because we have defined
-   TARGET_PROMOTE_FUNCTION_RETURN that returns true, we have to
-   perform the same promotions as PROMOTE_MODE.  */
-#define XTENSA_LIBCALL_VALUE(MODE, OUTGOINGP)                          \
-  gen_rtx_REG ((GET_MODE_CLASS (MODE) == MODE_INT                      \
-               && GET_MODE_SIZE (MODE) < UNITS_PER_WORD)               \
-              ? SImode : (MODE),                                       \
-              OUTGOINGP ? GP_OUTGOING_RETURN : GP_RETURN)
-
-#define LIBCALL_VALUE(MODE)                                            \
-  XTENSA_LIBCALL_VALUE ((MODE), 0)
-
-#define LIBCALL_OUTGOING_VALUE(MODE)                                   \
-  XTENSA_LIBCALL_VALUE ((MODE), 1)
-
-/* Define how to find the value returned by a function.
-   VALTYPE is the data type of the value (as a tree).
-   If the precise function being called is known, FUNC is its FUNCTION_DECL;
-   otherwise, FUNC is 0.  */
-#define XTENSA_FUNCTION_VALUE(VALTYPE, FUNC, OUTGOINGP)                        \
-  gen_rtx_REG ((INTEGRAL_TYPE_P (VALTYPE)                              \
-               && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD)            \
-              ? SImode: TYPE_MODE (VALTYPE),                           \
-              OUTGOINGP ? GP_OUTGOING_RETURN : GP_RETURN)
-
-#define FUNCTION_VALUE(VALTYPE, FUNC)                                  \
-  XTENSA_FUNCTION_VALUE (VALTYPE, FUNC, 0)
-
-#define FUNCTION_OUTGOING_VALUE(VALTYPE, FUNC)                         \
-  XTENSA_FUNCTION_VALUE (VALTYPE, FUNC, 1)
-
-/* A C expression that is nonzero if REGNO is the number of a hard
-   register in which the values of called function may come back.  A
-   register whose use for returning values is limited to serving as
-   the second of a pair (for a value of type 'double', say) need not
-   be recognized by this macro.  If the machine has register windows,
-   so that the caller and the called function use different registers
-   for the return value, this macro should recognize only the caller's
-   register numbers.  */
-#define FUNCTION_VALUE_REGNO_P(N)                                      \
-  ((N) == GP_RETURN)
-
 /* A C expression that is nonzero if REGNO is the number of a hard
    register in which function arguments are sometimes passed.  This
    does *not* include implicit arguments such as the static chain and
@@ -641,7 +475,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
    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
@@ -659,20 +493,6 @@ typedef struct xtensa_args
 #define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME)            \
   init_cumulative_args (&CUM, 1)
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)                   \
-  function_arg_advance (&CUM, MODE, TYPE)
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-  function_arg (&CUM, MODE, TYPE, FALSE)
-
-#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
-  function_arg (&CUM, MODE, TYPE, TRUE)
-
-#define FUNCTION_ARG_BOUNDARY function_arg_boundary
-
 /* Profiling Xtensa code is typically done with the built-in profiling
    feature of Tensilica's instruction set simulator, which does not
    require any compiler support.  Profiling code on a real (i.e.,
@@ -694,93 +514,26 @@ typedef struct xtensa_args
     fprintf (FILE, "\t%s\ta10, a0\n", TARGET_DENSITY ? "mov.n" : "mov"); \
     if (flag_pic)                                                      \
       {                                                                        \
-       fprintf (FILE, "\tmovi\ta8, _mcount@PLT\n");                    \
-       fprintf (FILE, "\tcallx8\ta8\n");                               \
+       fprintf (FILE, "\tmovi\ta%d, _mcount@PLT\n", WINDOW_SIZE);      \
+       fprintf (FILE, "\tcallx%d\ta%d\n", WINDOW_SIZE, WINDOW_SIZE);   \
       }                                                                        \
     else                                                               \
-      fprintf (FILE, "\tcall8\t_mcount\n");                            \
+      fprintf (FILE, "\tcall%d\t_mcount\n", WINDOW_SIZE);              \
   } while (0)
 
 /* Stack pointer value doesn't matter at exit.  */
 #define EXIT_IGNORE_STACK 1
 
-/* A C statement to output, on the stream FILE, assembler code for a
-   block of data that contains the constant parts of a trampoline. 
-   This code should not include a label--the label is taken care of
-   automatically.
-
-   For Xtensa, the trampoline must perform an entry instruction with a
-   minimal stack frame in order to get some free registers.  Once the
-   actual call target is known, the proper stack frame size is extracted
-   from the entry instruction at the target and the current frame is
-   adjusted to match.  The trampoline then transfers control to the
-   instruction following the entry at the target.  Note: this assumes
-   that the target begins with an entry instruction.  */
-
-/* minimum frame = reg save area (4 words) plus static chain (1 word)
-   and the total number of words must be a multiple of 128 bits */
-#define MIN_FRAME_SIZE (8 * UNITS_PER_WORD)
-
-#define TRAMPOLINE_TEMPLATE(STREAM)                                    \
-  do {                                                                 \
-    fprintf (STREAM, "\t.begin no-transform\n");                       \
-    fprintf (STREAM, "\tentry\tsp, %d\n", MIN_FRAME_SIZE);             \
-                                                                       \
-    /* save the return address */                                      \
-    fprintf (STREAM, "\tmov\ta10, a0\n");                              \
-                                                                       \
-    /* Use a CALL0 instruction to skip past the constants and in the   \
-       process get the PC into A0.  This allows PC-relative access to  \
-       the constants without relying on L32R, which may not always be  \
-       available.  */                                                  \
-                                                                       \
-    fprintf (STREAM, "\tcall0\t.Lskipconsts\n");                       \
-    fprintf (STREAM, "\t.align\t4\n");                                 \
-    fprintf (STREAM, ".Lchainval:%s0\n", integer_asm_op (4, TRUE));    \
-    fprintf (STREAM, ".Lfnaddr:%s0\n", integer_asm_op (4, TRUE));      \
-    fprintf (STREAM, ".Lskipconsts:\n");                               \
-                                                                       \
-    /* store the static chain */                                       \
-    fprintf (STREAM, "\taddi\ta0, a0, 3\n");                           \
-    fprintf (STREAM, "\tl32i\ta8, a0, 0\n");                           \
-    fprintf (STREAM, "\ts32i\ta8, sp, %d\n", MIN_FRAME_SIZE - 20);     \
-                                                                       \
-    /* set the proper stack pointer value */                           \
-    fprintf (STREAM, "\tl32i\ta8, a0, 4\n");                           \
-    fprintf (STREAM, "\tl32i\ta9, a8, 0\n");                           \
-    fprintf (STREAM, "\textui\ta9, a9, %d, 12\n",                      \
-            TARGET_BIG_ENDIAN ? 8 : 12);                               \
-    fprintf (STREAM, "\tslli\ta9, a9, 3\n");                           \
-    fprintf (STREAM, "\taddi\ta9, a9, %d\n", -MIN_FRAME_SIZE);         \
-    fprintf (STREAM, "\tsub\ta9, sp, a9\n");                           \
-    fprintf (STREAM, "\tmovsp\tsp, a9\n");                             \
-                                                                       \
-    /* restore the return address */                                   \
-    fprintf (STREAM, "\tmov\ta0, a10\n");                              \
-                                                                       \
-    /* jump to the instruction following the entry */                  \
-    fprintf (STREAM, "\taddi\ta8, a8, 3\n");                           \
-    fprintf (STREAM, "\tjx\ta8\n");                                    \
-    fprintf (STREAM, "\t.byte\t0\n");                                  \
-    fprintf (STREAM, "\t.end no-transform\n");                         \
-  } while (0)
-
 /* Size in bytes of the trampoline, as an integer.  Make sure this is
    a multiple of TRAMPOLINE_ALIGNMENT to avoid -Wpadded warnings.  */
-#define TRAMPOLINE_SIZE 60
+#define TRAMPOLINE_SIZE (TARGET_WINDOWED_ABI ? \
+                        (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \
+                         60 : 52) : \
+                        (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? \
+                         32 : 24))
 
 /* Alignment required for trampolines, in bits.  */
-#define TRAMPOLINE_ALIGNMENT (32)
-
-/* A C statement to initialize the variable parts of a trampoline.  */
-#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN)                       \
-  do {                                                                 \
-    rtx addr = ADDR;                                                   \
-    emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 12)), CHAIN); \
-    emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 16)), FUNC); \
-    emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_sync_caches"), \
-                      0, VOIDmode, 1, addr, Pmode);                    \
-  } while (0)
+#define TRAMPOLINE_ALIGNMENT 32
 
 /* If defined, a C expression that produces the machine-specific code
    to setup the stack so that arbitrary frames can be accessed.
@@ -819,7 +572,7 @@ typedef struct xtensa_args
 
 /* Define this if the return address of a particular stack frame is
    accessed from the frame pointer of the previous stack frame.  */
-#define RETURN_ADDR_IN_PREVIOUS_FRAME
+#define RETURN_ADDR_IN_PREVIOUS_FRAME TARGET_WINDOWED_ABI
 
 /* A C expression whose value is RTL representing the value of the
    return address for the frame COUNT steps up from the current
@@ -838,29 +591,13 @@ 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
 
-/* Identify valid Xtensa addresses.  */
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, ADDR, LABEL)                    \
-  do {                                                                 \
-    if (xtensa_legitimate_address_p (MODE, ADDR, REG_OK_STRICT_FLAG))  \
-      goto LABEL;                                                      \
-  } while (0)
-
 /* A C expression that is 1 if the RTX X is a constant which is a
    valid address.  This is defined to be the same as 'CONSTANT_P (X)',
    but rejecting CONST_DOUBLE.  */
@@ -869,10 +606,6 @@ typedef struct xtensa_args
     || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH               \
     || (GET_CODE (X) == CONST)))
 
-/* Nonzero if the constant value X is a legitimate general operand.
-   It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
-#define LEGITIMATE_CONSTANT_P(X) 1
-
 /* A C expression that is nonzero if X is a legitimate immediate
    operand on the target machine when generating position independent
    code.  */
@@ -882,31 +615,6 @@ typedef struct xtensa_args
    && GET_CODE (X) != LABEL_REF                                                \
    && GET_CODE (X) != CONST)
 
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)                         \
-  do {                                                                 \
-    rtx new_x = xtensa_legitimize_address (X, OLDX, MODE);             \
-    if (new_x)                                                         \
-      {                                                                        \
-       X = new_x;                                                      \
-       goto WIN;                                                       \
-      }                                                                        \
-  } while (0)
-
-
-/* Treat constant-pool references as "mode dependent" since they can
-   only be accessed with SImode loads.  This works around a bug in the
-   combiner where a constant pool reference is temporarily converted
-   to an HImode load, which is then assumed to zero-extend based on
-   our definition of LOAD_EXTEND_OP.  This is wrong because the high
-   bits of a 16-bit value in the constant pool are now sign-extended
-   by default.  */
-
-#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)                      \
-  do {                                                                 \
-    if (constantpool_address_p (ADDR))                                 \
-      goto LABEL;                                                      \
-  } while (0)
-
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
 #define CASE_VECTOR_MODE (SImode)
@@ -925,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)
 
@@ -941,27 +645,7 @@ typedef struct xtensa_args
    indexing purposes) so give the MEM rtx a words's mode.  */
 #define FUNCTION_MODE SImode
 
-/* A C expression for the cost of moving data from a register in
-   class FROM to one in class TO.  The classes are expressed using
-   the enumeration values such as 'GENERAL_REGS'.  A value of 2 is
-   the default; other values are interpreted relative to that.  */
-#define REGISTER_MOVE_COST(MODE, FROM, TO)                             \
-  (((FROM) == (TO) && (FROM) != BR_REGS && (TO) != BR_REGS)            \
-   ? 2                                                                 \
-   : (reg_class_subset_p ((FROM), AR_REGS)                             \
-      && reg_class_subset_p ((TO), AR_REGS)                            \
-      ? 2                                                              \
-      : (reg_class_subset_p ((FROM), AR_REGS)                          \
-        && (TO) == ACC_REG                                             \
-        ? 3                                                            \
-        : ((FROM) == ACC_REG                                           \
-           && reg_class_subset_p ((TO), AR_REGS)                       \
-           ? 3                                                         \
-           : 10))))
-
-#define MEMORY_MOVE_COST(MODE, CLASS, IN) 4
-
-#define BRANCH_COST 3
+#define BRANCH_COST(speed_p, predictable_p) 3
 
 /* How to refer to registers in assembler output.
    This sequence is indexed by compiler's hard-register-number (see above).  */
@@ -987,14 +671,6 @@ typedef struct xtensa_args
 #define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
 #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
 
-/* Recognize machine-specific patterns that may appear within
-   constants.  Used for PIC-specific UNSPECs.  */
-#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL)                       \
-  do {                                                                 \
-    if (xtensa_output_addr_const_extra (STREAM, X) == FALSE)           \
-      goto FAIL;                                                       \
-  } while (0)
-
 /* Globalizing directive for a label.  */
 #define GLOBAL_ASM_OP "\t.global\t"
 
@@ -1036,9 +712,9 @@ 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)                                                    \
+    if ((SIZE) > 0 || !TARGET_WINDOWED_ABI)                            \
       {                                                                        \
        resolve_unique_section ((FUNDECL), 0, flag_function_sections);  \
        switch_to_section (function_section (FUNDECL));                 \
@@ -1065,7 +741,10 @@ typedef struct xtensa_args
    for debugging.  */
 #define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 0)
 #define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (0)
-#define DWARF_FRAME_REGISTERS 16
+#define DWARF_ALT_FRAME_RETURN_COLUMN 16
+#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                                                            \
@@ -1073,6 +752,8 @@ typedef struct xtensa_args
       | DW_EH_PE_pcrel | DW_EH_PE_sdata4)                              \
    : DW_EH_PE_absptr)
 
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 10)
+
 /* Emit a PC-relative relocation.  */
 #define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL)                      \
   do {                                                                 \
@@ -1086,8 +767,16 @@ typedef struct xtensa_args
    a MOVI and let the assembler relax it -- for the .init and .fini
    sections, the assembler knows to put the literal in the right
    place.  */
+#if defined(__XTENSA_WINDOWED_ABI__)
 #define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
     asm (SECTION_OP "\n\
        movi\ta8, " USER_LABEL_PREFIX #FUNC "\n\
        callx8\ta8\n" \
        TEXT_SECTION_ASM_OP);
+#elif defined(__XTENSA_CALL0_ABI__)
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+    asm (SECTION_OP "\n\
+       movi\ta0, " USER_LABEL_PREFIX #FUNC "\n\
+       callx0\ta0\n" \
+       TEXT_SECTION_ASM_OP);
+#endif