/* Definitions of Tensilica's Xtensa target machine for GNU compiler.
- Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 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, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, 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 target_flags;
extern int optimize;
/* External variables defined in xtensa.c. */
extern enum cmp_type branch_type; /* what type of branch to use */
extern unsigned xtensa_current_frame_size;
-/* Masks for the -m switches */
-#define MASK_NO_FUSED_MADD 0x00000001 /* avoid f-p mul/add */
-#define MASK_CONST16 0x00000002 /* use CONST16 instruction */
-
/* 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
#define TARGET_BIG_ENDIAN XCHAL_HAVE_BE
#define TARGET_DENSITY XCHAL_HAVE_DENSITY
#define TARGET_MAC16 XCHAL_HAVE_MAC16
#define TARGET_MUL16 XCHAL_HAVE_MUL16
#define TARGET_MUL32 XCHAL_HAVE_MUL32
+#define TARGET_MUL32_HIGH XCHAL_HAVE_MUL32_HIGH
#define TARGET_DIV32 XCHAL_HAVE_DIV32
#define TARGET_NSA XCHAL_HAVE_NSA
#define TARGET_MINMAX XCHAL_HAVE_MINMAX
#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
-/* Macros controlled by command-line options. */
-#define TARGET_NO_FUSED_MADD (target_flags & MASK_NO_FUSED_MADD)
-#define TARGET_CONST16 (target_flags & MASK_CONST16)
+#define TARGET_DEFAULT \
+ ((XCHAL_HAVE_L32R ? 0 : MASK_CONST16) | \
+ MASK_SERIALIZE_VOLATILE)
-#define TARGET_DEFAULT ( \
- (XCHAL_HAVE_L32R ? 0 : MASK_CONST16))
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
-#define TARGET_SWITCHES \
-{ \
- {"const16", MASK_CONST16, \
- N_("Use CONST16 instruction to load constants")}, \
- {"no-const16", -MASK_CONST16, \
- N_("Use PC-relative L32R instruction to load constants")}, \
- {"no-fused-madd", MASK_NO_FUSED_MADD, \
- N_("Disable fused multiply/add and multiply/subtract FP instructions")}, \
- {"fused-madd", -MASK_NO_FUSED_MADD, \
- N_("Enable fused multiply/add and multiply/subtract FP instructions")}, \
- {"text-section-literals", 0, \
- N_("Intersperse literal pools with code in the text section")}, \
- {"no-text-section-literals", 0, \
- N_("Put literal pools in a separate literal section")}, \
- {"target-align", 0, \
- N_("Automatically align branch targets to reduce branch penalties")}, \
- {"no-target-align", 0, \
- N_("Do not automatically align branch targets")}, \
- {"longcalls", 0, \
- N_("Use indirect CALLXn instructions for large programs")}, \
- {"no-longcalls", 0, \
- N_("Use direct CALLn instructions for fast calls")}, \
- {"", TARGET_DEFAULT, 0} \
-}
+#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 OVERRIDE_OPTIONS override_options ()
\f
/* Target CPU builtins. */
#define TARGET_CPU_CPP_BUILTINS() \
do { \
builtin_assert ("cpu=xtensa"); \
builtin_assert ("machine=xtensa"); \
+ builtin_define ("__xtensa__"); \
builtin_define ("__XTENSA__"); \
+ builtin_define ("__XTENSA_WINDOWED_ABI__"); \
builtin_define (TARGET_BIG_ENDIAN ? "__XTENSA_EB__" : "__XTENSA_EL__"); \
if (!TARGET_HARD_FLOAT) \
builtin_define ("__XTENSA_SOFT_FLOAT__"); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} while (0)
#define CPP_SPEC " %(subtarget_cpp_spec) "
#define INT_TYPE_SIZE 32
#define SHORT_TYPE_SIZE 16
#define LONG_TYPE_SIZE 32
-#define MAX_LONG_TYPE_SIZE 32
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
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
call an address kept in a register. */
#define NO_FUNCTION_CSE 1
-/* It is as good or better for a function to call itself with an
- explicit address than to call an address kept in a register. */
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
/* Xtensa processors have "register windows". GCC does not currently
take advantage of the possibility for variable-sized windows; instead,
we use a fixed window size of 8. */
{ 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
incoming or outgoing arguments. */
#define SMALL_REGISTER_CLASSES 1
-
-/* REGISTER AND CONSTANT CLASSES */
-
-/* Get reg_class from a letter such as appears in the machine
- description.
-
- Available letters: a-f,h,j-l,q,t-z,A-D,W,Y-Z
-
- DEFINED REGISTER CLASSES:
-
- 'a' general-purpose registers except sp
- 'q' sp (aka a1)
- 'D' general-purpose registers (only if density option enabled)
- 'd' general-purpose registers, including sp (only if density enabled)
- 'A' MAC16 accumulator (only if MAC16 option enabled)
- 'B' general-purpose registers (only if sext instruction enabled)
- 'C' general-purpose registers (only if mul16 option enabled)
- 'W' general-purpose registers (only if const16 option enabled)
- 'b' coprocessor boolean registers
- 'f' floating-point registers
-*/
-
-extern enum reg_class xtensa_char_to_class[256];
-
-#define REG_CLASS_FROM_LETTER(C) xtensa_char_to_class[ (int) (C) ]
-
-/* The letters I, J, K, L, M, N, O, and P in a register constraint
- string can be used to stand for particular ranges of immediate
- operands. This macro defines what the ranges are. C is the
- letter, and VALUE is a constant value. Return 1 if VALUE is
- in the range specified by C.
-
- For Xtensa:
-
- I = 12-bit signed immediate for movi
- J = 8-bit signed immediate for addi
- K = 4-bit value in (b4const U {0})
- L = 4-bit value in b4constu
- M = 7-bit value in simm7
- N = 8-bit unsigned immediate shifted left by 8 bits for addmi
- O = 4-bit value in ai4const
- P = valid immediate mask value for extui */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'I' ? (xtensa_simm12b (VALUE)) \
- : (C) == 'J' ? (xtensa_simm8 (VALUE)) \
- : (C) == 'K' ? (((VALUE) == 0) || xtensa_b4const (VALUE)) \
- : (C) == 'L' ? (xtensa_b4constu (VALUE)) \
- : (C) == 'M' ? (xtensa_simm7 (VALUE)) \
- : (C) == 'N' ? (xtensa_simm8x256 (VALUE)) \
- : (C) == 'O' ? (xtensa_ai4const (VALUE)) \
- : (C) == 'P' ? (xtensa_mask_immediate (VALUE)) \
- : FALSE)
-
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself. */
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) (0)
-
-
-/* Other letters can be defined in a machine-dependent fashion to
- stand for particular classes of registers or other arbitrary
- operand types.
-
- R = memory that can be accessed with a 4-bit unsigned offset
- T = memory in a constant pool (addressable with a pc-relative load)
- U = memory *NOT* in a constant pool
-
- The offset range should not be checked here (except to distinguish
- denser versions of the instructions for which more general versions
- are available). Doing so leads to problems in reloading: an
- argptr-relative address may become invalid when the phony argptr is
- eliminated in favor of the stack pointer (the offset becomes too
- large to fit in the instruction's immediate field); a reload is
- generated to fix this but the RTL is not immediately updated; in
- the meantime, the constraints are checked and none match. The
- solution seems to be to simply skip the offset check here. The
- address will be checked anyway because of the code in
- GO_IF_LEGITIMATE_ADDRESS. */
-
-#define EXTRA_CONSTRAINT(OP, CODE) \
- ((GET_CODE (OP) != MEM) ? \
- ((CODE) >= 'R' && (CODE) <= 'U' \
- && reload_in_progress && GET_CODE (OP) == REG \
- && REGNO (OP) >= FIRST_PSEUDO_REGISTER) \
- : ((CODE) == 'R') ? smalloffset_mem_p (OP) \
- : ((CODE) == 'T') ? !TARGET_CONST16 && constantpool_mem_p (OP) \
- : ((CODE) == 'U') ? !constantpool_mem_p (OP) \
- : FALSE)
-
#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. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
do { \
compute_frame_size (get_frame_size ()); \
- if ((FROM) == FRAME_POINTER_REGNUM) \
- (OFFSET) = 0; \
- else if ((FROM) == ARG_POINTER_REGNUM) \
- (OFFSET) = xtensa_current_frame_size; \
- else \
- abort (); \
+ switch (FROM) \
+ { \
+ case FRAME_POINTER_REGNUM: \
+ (OFFSET) = 0; \
+ break; \
+ case ARG_POINTER_REGNUM: \
+ (OFFSET) = xtensa_current_frame_size; \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
} while (0)
/* 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
#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 FUNCTION_ARG_REGNO_P(N) \
((N) >= GP_OUTGOING_ARG_FIRST && (N) <= GP_OUTGOING_ARG_LAST)
-/* Define a data type for recording info about an argument list
- during the scan of that argument list. This data type should
- hold all necessary information about the function itself
- and about the args processed so far, enough to enable macros
- such as FUNCTION_ARG to determine where the next arg should go. */
-typedef struct xtensa_args {
- int arg_words; /* # total words the arguments take */
+/* Record the number of argument words seen so far, along with a flag to
+ indicate whether these are incoming arguments. (FUNCTION_INCOMING_ARG
+ is used for both incoming and outgoing args, so a separate flag is
+ needed. */
+typedef struct xtensa_args
+{
+ int arg_words;
+ int incoming;
} CUMULATIVE_ARGS;
-/* Initialize a variable CUM of type CUMULATIVE_ARGS
- for a call to a function whose data type is FNTYPE.
- For a library call, FNTYPE is 0. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
- init_cumulative_args (&CUM, FNTYPE, LIBNAME)
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
+ init_cumulative_args (&CUM, 0)
#define INIT_CUMULATIVE_INCOMING_ARGS(CUM, FNTYPE, LIBNAME) \
- init_cumulative_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.
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, TRUE)
-/* Arguments are never passed partly in memory and partly in registers. */
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) (0)
-
-/* Specify function argument alignment. */
-#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
- ((TYPE) != 0 \
- ? (TYPE_ALIGN (TYPE) <= PARM_BOUNDARY \
- ? PARM_BOUNDARY \
- : TYPE_ALIGN (TYPE)) \
- : (GET_MODE_ALIGNMENT (MODE) <= PARM_BOUNDARY \
- ? PARM_BOUNDARY \
- : GET_MODE_ALIGNMENT (MODE)))
-
-/* Nonzero if we do not know how to pass TYPE solely in registers.
- We cannot do so in the following cases:
-
- - if the type has variable size
- - if the type is marked as addressable (it is required to be constructed
- into the stack)
-
- This differs from the default in that it does not check if the padding
- and mode of the type are such that a copy into a register would put it
- into the wrong part of the register. */
-
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE)))
-
-/* Pass complex arguments independently. */
-#define SPLIT_COMPLEX_ARGS 1
+#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
/* 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.
+#define TRAMPOLINE_TEMPLATE(STREAM) xtensa_trampoline_template (STREAM)
- 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-generics\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.end no-generics\n"); \
- } while (0)
-
-/* Size in bytes of the trampoline, as an integer. */
-#define TRAMPOLINE_SIZE 59
+/* 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)
/* Alignment required for trampolines, in bits. */
-#define TRAMPOLINE_ALIGNMENT (32)
+#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)
+ xtensa_initialize_trampoline (ADDR, FUNC, CHAIN)
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- xtensa_va_arg (valist, type)
/* If defined, a C expression that produces the machine-specific code
to setup the stack so that arbitrary frames can be accessed.
when count == 0 and the stack pointer when count > 0. */
#define DYNAMIC_CHAIN_ADDRESS(frame) \
- gen_rtx (PLUS, Pmode, frame, \
- gen_rtx_CONST_INT (VOIDmode, -3 * UNITS_PER_WORD))
+ gen_rtx_PLUS (Pmode, frame, GEN_INT (-3 * UNITS_PER_WORD))
/* Define this if the return address of a particular stack frame is
accessed from the frame pointer of the previous stack frame. */
/* Addressing modes, and classification of registers for them. */
/* C expressions which are nonzero if register number NUM is suitable
- for use as a base or index register in operand addresses. It may
- be either a suitable hard register or a pseudo register that has
- been allocated such a hard register. The difference between an
- index register and a base register is that the index register may
- be scaled. */
+ for use as a base or index register in operand addresses. */
+#define REGNO_OK_FOR_INDEX_P(NUM) 0
#define REGNO_OK_FOR_BASE_P(NUM) \
(GP_REG_P (NUM) || GP_REG_P ((unsigned) reg_renumber[NUM]))
-#define REGNO_OK_FOR_INDEX_P(NUM) 0
-
/* C expressions that are nonzero if X (assumed to be a `reg' RTX) is
- valid for use as a base or index register. For hard registers, it
- should always accept those which the hardware permits and reject
- the others. Whether the macro accepts or rejects pseudo registers
- must be controlled by `REG_OK_STRICT'. This usually requires two
- variant definitions, of which `REG_OK_STRICT' controls the one
- actually used. The difference between an index register and a base
- register is that the index register may be scaled. */
+ 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 REG_OK_FOR_INDEX_P(X) 0
-#define REG_OK_FOR_BASE_P(X) \
- REGNO_OK_FOR_BASE_P (REGNO (X))
-
-#else /* !REG_OK_STRICT */
+#define BASE_REG_P(X, STRICT) \
+ ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER) \
+ || REGNO_OK_FOR_BASE_P (REGNO (X)))
#define REG_OK_FOR_INDEX_P(X) 0
-#define REG_OK_FOR_BASE_P(X) \
- ((REGNO (X) >= FIRST_PSEUDO_REGISTER) || (GP_REG_P (REGNO (X))))
-
-#endif /* !REG_OK_STRICT */
+#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 { \
- rtx xinsn = (ADDR); \
- \
- /* allow constant pool addresses */ \
- if ((MODE) != BLKmode && GET_MODE_SIZE (MODE) >= UNITS_PER_WORD \
- && !TARGET_CONST16 && constantpool_address_p (xinsn)) \
- goto LABEL; \
- \
- while (GET_CODE (xinsn) == SUBREG) \
- xinsn = SUBREG_REG (xinsn); \
- \
- /* allow base registers */ \
- if (GET_CODE (xinsn) == REG && REG_OK_FOR_BASE_P (xinsn)) \
+ if (xtensa_legitimate_address_p (MODE, ADDR, REG_OK_STRICT_FLAG)) \
goto LABEL; \
- \
- /* check for "register + offset" addressing */ \
- if (GET_CODE (xinsn) == PLUS) \
- { \
- rtx xplus0 = XEXP (xinsn, 0); \
- rtx xplus1 = XEXP (xinsn, 1); \
- enum rtx_code code0; \
- enum rtx_code code1; \
- \
- while (GET_CODE (xplus0) == SUBREG) \
- xplus0 = SUBREG_REG (xplus0); \
- code0 = GET_CODE (xplus0); \
- \
- while (GET_CODE (xplus1) == SUBREG) \
- xplus1 = SUBREG_REG (xplus1); \
- code1 = GET_CODE (xplus1); \
- \
- /* swap operands if necessary so the register is first */ \
- if (code0 != REG && code1 == REG) \
- { \
- xplus0 = XEXP (xinsn, 1); \
- xplus1 = XEXP (xinsn, 0); \
- code0 = GET_CODE (xplus0); \
- code1 = GET_CODE (xplus1); \
- } \
- \
- if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) \
- && code1 == CONST_INT \
- && xtensa_mem_offset (INTVAL (xplus1), (MODE))) \
- { \
- goto LABEL; \
- } \
- } \
} while (0)
/* A C expression that is 1 if the RTX X is a constant which is a
/* 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
code. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- ((GET_CODE (X) != SYMBOL_REF || SYMBOL_REF_LOCAL_P (X)) \
+ ((GET_CODE (X) != SYMBOL_REF \
+ || (SYMBOL_REF_LOCAL_P (X) && !SYMBOL_REF_EXTERNAL_P (X))) \
&& GET_CODE (X) != LABEL_REF \
&& GET_CODE (X) != CONST)
-/* Tell GCC how to use ADDMI to generate addresses. */
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
do { \
- rtx xinsn = (X); \
- if (GET_CODE (xinsn) == PLUS) \
- { \
- rtx plus0 = XEXP (xinsn, 0); \
- rtx plus1 = XEXP (xinsn, 1); \
- \
- if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG) \
- { \
- plus0 = XEXP (xinsn, 1); \
- plus1 = XEXP (xinsn, 0); \
- } \
- \
- if (GET_CODE (plus0) == REG \
- && GET_CODE (plus1) == CONST_INT \
- && !xtensa_mem_offset (INTVAL (plus1), MODE) \
- && !xtensa_simm8 (INTVAL (plus1)) \
- && xtensa_mem_offset (INTVAL (plus1) & 0xff, MODE) \
- && xtensa_simm8x256 (INTVAL (plus1) & ~0xff)) \
- { \
- rtx temp = gen_reg_rtx (Pmode); \
- emit_insn (gen_rtx (SET, Pmode, temp, \
- gen_rtx (PLUS, Pmode, plus0, \
- GEN_INT (INTVAL (plus1) & ~0xff)))); \
- (X) = gen_rtx (PLUS, Pmode, temp, \
- GEN_INT (INTVAL (plus1) & 0xff)); \
- goto WIN; \
- } \
+ rtx new_x = xtensa_legitimize_address (X, OLDX, MODE); \
+ if (new_x) \
+ { \
+ X = new_x; \
+ goto WIN; \
} \
} while (0)
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE (SImode)
-/* Define this if the tablejump instruction expects the table
- to contain offsets from the address of the table.
- Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE */
-
/* Define this as 1 if 'char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 0
/* Prefer word-sized loads. */
#define SLOW_BYTE_ACCESS 1
-/* ??? Xtensa doesn't have any instructions that set integer values
- based on the results of comparisons, but the simplification code in
- the combiner also uses STORE_FLAG_VALUE. The default value (1) is
- fine for us, but (-1) might be better. */
-
/* Shift instructions ignore all but the low-order few bits. */
#define SHIFT_COUNT_TRUNCATED 1
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)
+
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
between pointers and any other objects of this machine mode. */
#define MEMORY_MOVE_COST(MODE, CLASS, IN) 4
-#define BRANCH_COST 3
-
-/* Optionally define this if you have added predicates to
- 'MACHINE.c'. This macro is called within an initializer of an
- array of structures. The first field in the structure is the
- name of a predicate and the second field is an array of rtl
- codes. For each predicate, list all rtl codes that can be in
- expressions matched by the predicate. The list should have a
- trailing comma. */
-
-#define PREDICATE_CODES \
- {"add_operand", { REG, CONST_INT, SUBREG }}, \
- {"arith_operand", { REG, CONST_INT, SUBREG }}, \
- {"nonimmed_operand", { REG, SUBREG, MEM }}, \
- {"mem_operand", { MEM }}, \
- {"mask_operand", { REG, CONST_INT, SUBREG }}, \
- {"extui_fldsz_operand", { CONST_INT }}, \
- {"sext_fldsz_operand", { CONST_INT }}, \
- {"lsbitnum_operand", { CONST_INT }}, \
- {"fpmem_offset_operand", { CONST_INT }}, \
- {"sext_operand", { REG, SUBREG, MEM }}, \
- {"branch_operand", { REG, CONST_INT, SUBREG }}, \
- {"ubranch_operand", { REG, CONST_INT, SUBREG }}, \
- {"call_insn_operand", { CONST_INT, CONST, SYMBOL_REF, REG }}, \
- {"move_operand", { REG, SUBREG, MEM, CONST_INT, CONST_DOUBLE, \
- CONST, SYMBOL_REF, LABEL_REF }}, \
- {"const_float_1_operand", { CONST_DOUBLE }}, \
- {"branch_operator", { EQ, NE, LT, GE }}, \
- {"ubranch_operator", { LTU, GEU }}, \
- {"boolean_operator", { EQ, NE }},
-
-/* Control the assembler format that we output. */
+#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). */
constants. Used for PIC-specific UNSPECs. */
#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
do { \
- if (flag_pic && GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
- { \
- switch (XINT ((X), 1)) \
- { \
- case UNSPEC_PLT: \
- output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
- fputs ("@PLT", (STREAM)); \
- break; \
- default: \
- goto FAIL; \
- } \
- break; \
- } \
- else \
+ if (xtensa_output_addr_const_extra (STREAM, X) == FALSE) \
goto FAIL; \
} while (0)
#define BSS_SECTION_ASM_OP "\t.section\t.bss"
-/* Define output to appear before the constant pool. If the function
- has been assigned to a specific ELF section, or if it goes into a
- unique section, set the name of that section to be the literal
- prefix. */
+/* Define output to appear before the constant pool. */
#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, FUNDECL, SIZE) \
do { \
- tree fnsection; \
- resolve_unique_section ((FUNDECL), 0, flag_function_sections); \
- fnsection = DECL_SECTION_NAME (FUNDECL); \
- if (fnsection != NULL_TREE) \
- { \
- const char *fnsectname = TREE_STRING_POINTER (fnsection); \
- fprintf (FILE, "\t.begin\tliteral_prefix %s\n", \
- strcmp (fnsectname, ".text") ? fnsectname : ""); \
- } \
if ((SIZE) > 0) \
{ \
- function_section (FUNDECL); \
+ resolve_unique_section ((FUNDECL), 0, flag_function_sections); \
+ switch_to_section (function_section (FUNDECL)); \
fprintf (FILE, "\t.literal_position\n"); \
} \
} while (0)
-/* Define code to write out the ".end literal_prefix" directive for a
- function in a special section. This is appended to the standard ELF
- code for ASM_DECLARE_FUNCTION_SIZE. */
-#define XTENSA_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
- if (DECL_SECTION_NAME (DECL) != NULL_TREE) \
- fprintf (FILE, "\t.end\tliteral_prefix\n")
-
/* A C statement (with or without semicolon) to output a constant in
the constant pool, if it needs special treatment. */
#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, X, MODE, ALIGN, LABELNO, JUMPTO) \
/* 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