/* Definitions of Tensilica's Xtensa target machine for GNU compiler.
- Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* Get Xtensa configuration settings */
#include "xtensa-config.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;
/* Macros used in the machine description to select various Xtensa
#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
#define TARGET_BIG_ENDIAN XCHAL_HAVE_BE
#define TARGET_DENSITY XCHAL_HAVE_DENSITY
#define TARGET_MAC16 XCHAL_HAVE_MAC16
#define TARGET_HARD_FLOAT_RSQRT XCHAL_HAVE_FP_RSQRT
#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_DEFAULT ( \
- (XCHAL_HAVE_L32R ? 0 : MASK_CONST16))
-
-#define OVERRIDE_OPTIONS override_options ()
+#define TARGET_DEFAULT \
+ ((XCHAL_HAVE_L32R ? 0 : MASK_CONST16) | \
+ MASK_SERIALIZE_VOLATILE)
-/* 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)
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
\f
/* Target CPU builtins. */
#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
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
+ 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
35, \
}
-#define ORDER_REGS_FOR_LOCAL_ALLOC order_regs_for_local_alloc ()
+#define ADJUST_REG_ALLOC_ORDER 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
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))
-
/* 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. */
{ 0xffffffff, 0x0000000f } /* all registers */ \
}
+#define IRA_COVER_CLASSES \
+{ \
+ BR_REGS, FP_REGS, ACC_REG, AR_REGS, LIM_REG_CLASSES \
+}
+
/* A C expression whose value is a register class containing hard
register REGNO. In general there is more that one such class;
choose a class which is "minimal", meaning that no smaller class
#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
+/* 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
#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) \
/* Offset within stack frame to start allocating local variables at. */
#define STARTING_FRAME_OFFSET \
- current_function_outgoing_args_size
+ crtl->outgoing_args_size
/* The ARG_POINTER and FRAME_POINTER are not real Xtensa registers, so
they are eliminated to either the stack pointer or hard frame pointer. */
{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
-#define CAN_ELIMINATE(FROM, TO) 1
-
/* Specify the initial difference between the specified pair of registers. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
do { \
/* 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
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 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
+ TARGET_PROMOTE_FUNCTION_MODE to promote everything, 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 \
#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
#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
/* 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_CONST16 || TARGET_ABSOLUTE_LITERALS ? 60 : 52)
/* 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)
-
-/* Implement `va_start' for varargs and stdarg. */
-#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
- xtensa_va_start (valist, nextarg)
+#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.
/* 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. */
/* 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
+#define LEGITIMATE_CONSTANT_P(X) (! xtensa_tls_referenced_p (X))
/* A C expression that is nonzero if X is a legitimate immediate
operand on the target machine when generating position independent
&& 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
#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). */
/* How to start an assembler comment. */
#define ASM_COMMENT_START "#"
-/* Exception handling TODO!! */
-#define DWARF_UNWIND_INFO 0
+/* Exception handling. Xtensa uses much of the standard DWARF2 unwinding
+ machinery, but the variable size register window save areas are too
+ complicated to efficiently describe with CFI entries. The CFA must
+ still be specified in DWARF so that DW_AT_frame_base is set correctly
+ 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 EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + 2 : INVALID_REGNUM)
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
+ (flag_pic \
+ ? (((GLOBAL) ? DW_EH_PE_indirect : 0) \
+ | DW_EH_PE_pcrel | DW_EH_PE_sdata4) \
+ : DW_EH_PE_absptr)
+
+/* Emit a PC-relative relocation. */
+#define ASM_OUTPUT_DWARF_PCREL(FILE, SIZE, LABEL) \
+ do { \
+ fputs (integer_asm_op (SIZE, FALSE), FILE); \
+ assemble_name (FILE, LABEL); \
+ fputs ("@pcrel", FILE); \
+ } while (0)
/* Xtensa constant pool breaks the devices in crtstuff.c to control
section in where code resides. We have to write it as asm code. Use