]> 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 54bfea44ce630fd76ca86286d69936d6af9f3b6a..9591b3d4b40055faa0c8afe79ccfaf771e607e77 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of Tensilica's Xtensa target machine for GNU compiler.
-   Copyright (C) 2001-2014 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,29 +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.  */
-
-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
-#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
@@ -52,6 +35,7 @@ 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
@@ -65,27 +49,40 @@ extern unsigned xtensa_current_frame_size;
 #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 \
-  ((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__");                                     \
     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) "
@@ -147,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
@@ -168,16 +165,6 @@ extern unsigned xtensa_current_frame_size;
    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)                                 \
-  ((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
@@ -185,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
@@ -219,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.  */
@@ -232,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 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.  */
 
@@ -293,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 */
@@ -311,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
@@ -350,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.  */
@@ -364,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
@@ -383,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 */
@@ -404,6 +367,7 @@ enum reg_class
   "FP_REGS",                                                           \
   "ACC_REG",                                                           \
   "SP_REG",                                                            \
+  "ISC_REGS",                                                          \
   "RL_REGS",                                                           \
   "GR_REGS",                                                           \
   "AR_REGS",                                                           \
@@ -420,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 */ \
@@ -430,9 +395,7 @@ 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.  */
@@ -446,36 +409,27 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 
 /* 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                                          \
-  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 {                                                                 \
-    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
@@ -495,11 +449,12 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 #define STACK_BOUNDARY 128
 
 /* 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.  */
@@ -520,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
@@ -559,11 +514,11 @@ 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.  */
@@ -571,7 +526,11 @@ typedef struct xtensa_args
 
 /* 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 (TARGET_CONST16 || TARGET_ABSOLUTE_LITERALS ? 60 : 52)
+#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
@@ -613,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
@@ -632,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
 
@@ -683,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)
 
@@ -766,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));                 \
@@ -795,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                                                            \
@@ -803,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 {                                                                 \
@@ -816,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