OSDN Git Service

* config/xtensa/xtensa.c (xtensa_secondary_reload_class): Revert
[pf3gnuchains/gcc-fork.git] / gcc / config / xtensa / xtensa.h
index 4300e11..1c23b8d 100644 (file)
@@ -1,12 +1,13 @@
 /* Definitions of Tensilica's Xtensa target machine for GNU compiler.
-   Copyright 2001, 2002, 2003, 2004, 2005, 2006 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
@@ -15,15 +16,13 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 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.  */
@@ -43,6 +42,15 @@ extern unsigned xtensa_current_frame_size;
 
 /* 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
@@ -61,9 +69,13 @@ extern unsigned xtensa_current_frame_size;
 #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_DEFAULT (                                               \
-  (XCHAL_HAVE_L32R     ? 0 : MASK_CONST16))
+#define TARGET_DEFAULT \
+  ((XCHAL_HAVE_L32R    ? 0 : MASK_CONST16) |                           \
+   MASK_SERIALIZE_VOLATILE)
 
 #define OVERRIDE_OPTIONS override_options ()
 
@@ -467,6 +479,11 @@ enum reg_class
   { 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
@@ -512,7 +529,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 
 /* 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.  */
@@ -543,7 +560,7 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 
 /* 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
@@ -596,22 +613,6 @@ extern const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER];
 #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
@@ -693,87 +694,19 @@ typedef struct xtensa_args
 /* 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)
+#define TRAMPOLINE_TEMPLATE(STREAM) xtensa_trampoline_template (STREAM)
 
 /* 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)
+#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)
+  xtensa_initialize_trampoline (ADDR, FUNC, CHAIN)
 
-/* Implement `va_start' for varargs and stdarg.  */
-#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
-  xtensa_va_start (valist, nextarg)
 
 /* If defined, a C expression that produces the machine-specific code
    to setup the stack so that arbitrary frames can be accessed.
@@ -822,39 +755,27 @@ typedef struct xtensa_args
 /* 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
@@ -862,52 +783,8 @@ typedef struct xtensa_args
 /* 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))           \
+    if (xtensa_legitimate_address_p (MODE, ADDR, REG_OK_STRICT_FLAG))  \
       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))          \
-      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
@@ -931,36 +808,13 @@ typedef struct xtensa_args
    && 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)
 
@@ -1063,20 +917,7 @@ typedef struct xtensa_args
    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)
 
@@ -1143,8 +984,28 @@ typedef struct xtensa_args
 /* 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