OSDN Git Service

2009-04-13 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.h
index 73d8333..a44b403 100644 (file)
@@ -1,6 +1,7 @@
 /* Definitions of target machine for GNU compiler, for ARM.
    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
    and Martin Simmons (@harleqn.co.uk).
    More major hacks by Richard Earnshaw (rearnsha@arm.com)
@@ -10,7 +11,7 @@
 
    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
+   by the Free 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
    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/>.  */
 
 #ifndef GCC_ARM_H
 #define GCC_ARM_H
 
+#include "config/vxworks-dummy.h"
+
 /* The architecture define.  */
 extern char arm_arch_name[];
 
@@ -39,6 +41,8 @@ extern char arm_arch_name[];
        builtin_define ("__APCS_32__");                 \
        if (TARGET_THUMB)                               \
          builtin_define ("__thumb__");                 \
+       if (TARGET_THUMB2)                              \
+         builtin_define ("__thumb2__");                \
                                                        \
        if (TARGET_BIG_END)                             \
          {                                             \
@@ -61,6 +65,9 @@ extern char arm_arch_name[];
        if (TARGET_VFP)                                 \
          builtin_define ("__VFP_FP__");                \
                                                        \
+       if (TARGET_NEON)                                \
+         builtin_define ("__ARM_NEON__");              \
+                                                       \
        /* Add a define for interworking.               \
           Needed when building libgcc.a.  */           \
        if (arm_cpp_interwork)                          \
@@ -126,8 +133,8 @@ extern rtx pool_vector_label;
 /* Set to 1 when a return insn is output, this means that the epilogue
    is not needed.  */
 extern int return_used_this_function;
-/* Used to produce AOF syntax assembler.  */
-extern GTY(()) rtx aof_pic_label;
+/* Callback to output language specific object attributes.  */
+extern void (*arm_lang_output_object_attributes_hook)(void);
 \f
 /* Just in case configure has failed to define anything.  */
 #ifndef TARGET_CPU_DEFAULT
@@ -181,8 +188,8 @@ extern GTY(()) rtx aof_pic_label;
 #define TARGET_MAVERICK                        (arm_fp_model == ARM_FP_MODEL_MAVERICK)
 #define TARGET_VFP                     (arm_fp_model == ARM_FP_MODEL_VFP)
 #define TARGET_IWMMXT                  (arm_arch_iwmmxt)
-#define TARGET_REALLY_IWMMXT           (TARGET_IWMMXT && TARGET_ARM)
-#define TARGET_IWMMXT_ABI (TARGET_ARM && arm_abi == ARM_ABI_IWMMXT)
+#define TARGET_REALLY_IWMMXT           (TARGET_IWMMXT && TARGET_32BIT)
+#define TARGET_IWMMXT_ABI (TARGET_32BIT && arm_abi == ARM_ABI_IWMMXT)
 #define TARGET_ARM                      (! TARGET_THUMB)
 #define TARGET_EITHER                  1 /* (TARGET_ARM | TARGET_THUMB) */
 #define TARGET_BACKTRACE               (leaf_function_p () \
@@ -195,6 +202,53 @@ extern GTY(()) rtx aof_pic_label;
 #define TARGET_HARD_TP                 (target_thread_pointer == TP_CP15)
 #define TARGET_SOFT_TP                 (target_thread_pointer == TP_SOFT)
 
+/* Only 16-bit thumb code.  */
+#define TARGET_THUMB1                  (TARGET_THUMB && !arm_arch_thumb2)
+/* Arm or Thumb-2 32-bit code.  */
+#define TARGET_32BIT                   (TARGET_ARM || arm_arch_thumb2)
+/* 32-bit Thumb-2 code.  */
+#define TARGET_THUMB2                  (TARGET_THUMB && arm_arch_thumb2)
+/* Thumb-1 only.  */
+#define TARGET_THUMB1_ONLY             (TARGET_THUMB1 && !arm_arch_notm)
+
+/* The following two macros concern the ability to execute coprocessor
+   instructions for VFPv3 or NEON.  TARGET_VFP3/TARGET_VFPD32 are currently
+   only ever tested when we know we are generating for VFP hardware; we need
+   to be more careful with TARGET_NEON as noted below.  */
+
+/* FPU is has the full VFPv3/NEON register file of 32 D registers.  */
+#define TARGET_VFPD32 (arm_fp_model == ARM_FP_MODEL_VFP \
+                      && (arm_fpu_arch == FPUTYPE_VFP3 \
+                          || arm_fpu_arch == FPUTYPE_NEON))
+
+/* FPU supports VFPv3 instructions.  */
+#define TARGET_VFP3 (arm_fp_model == ARM_FP_MODEL_VFP \
+                    && (arm_fpu_arch == FPUTYPE_VFP3D16 \
+                        || TARGET_VFPD32))
+
+/* FPU supports Neon instructions.  The setting of this macro gets
+   revealed via __ARM_NEON__ so we add extra guards upon TARGET_32BIT
+   and TARGET_HARD_FLOAT to ensure that NEON instructions are
+   available.  */
+#define TARGET_NEON (TARGET_32BIT && TARGET_HARD_FLOAT \
+                    && arm_fp_model == ARM_FP_MODEL_VFP \
+                    && arm_fpu_arch == FPUTYPE_NEON)
+
+/* "DSP" multiply instructions, eg. SMULxy.  */
+#define TARGET_DSP_MULTIPLY \
+  (TARGET_32BIT && arm_arch5e && arm_arch_notm)
+/* Integer SIMD instructions, and extend-accumulate instructions.  */
+#define TARGET_INT_SIMD \
+  (TARGET_32BIT && arm_arch6 && arm_arch_notm)
+
+/* Should MOVW/MOVT be used in preference to a constant pool.  */
+#define TARGET_USE_MOVT (arm_arch_thumb2 && !optimize_size)
+
+/* We could use unified syntax for arm mode, but for now we just use it
+   for Thumb-2.  */
+#define TARGET_UNIFIED_ASM TARGET_THUMB2
+
+
 /* True iff the full BPABI is being used.  If TARGET_BPABI is true,
    then TARGET_AAPCS_BASED must be true -- but the converse does not
    hold.  TARGET_BPABI implies the use of the BPABI runtime library,
@@ -252,7 +306,13 @@ enum fputype
   /* Cirrus Maverick floating point co-processor.  */
   FPUTYPE_MAVERICK,
   /* VFP.  */
-  FPUTYPE_VFP
+  FPUTYPE_VFP,
+  /* VFPv3-D16.  */
+  FPUTYPE_VFP3D16,
+  /* VFPv3.  */
+  FPUTYPE_VFP3,
+  /* Neon.  */
+  FPUTYPE_NEON
 };
 
 /* Recast the floating point class to be the floating point attribute.  */
@@ -320,6 +380,9 @@ extern int arm_arch5e;
 /* Nonzero if this chip supports the ARM Architecture 6 extensions.  */
 extern int arm_arch6;
 
+/* Nonzero if instructions not present in the 'M' profile can be used.  */
+extern int arm_arch_notm;
+
 /* Nonzero if this chip can benefit from load scheduling.  */
 extern int arm_ld_sched;
 
@@ -344,6 +407,9 @@ extern int arm_tune_xscale;
 /* Nonzero if tuning for stores via the write buffer.  */
 extern int arm_tune_wbuf;
 
+/* Nonzero if tuning for Cortex-A9.  */
+extern int arm_tune_cortex_a9;
+
 /* Nonzero if we should define __THUMB_INTERWORK__ in the
    preprocessor.
    XXX This is a bit of a hack, it's intended to help work around
@@ -351,6 +417,12 @@ extern int arm_tune_wbuf;
    interworking clean.  */
 extern int arm_cpp_interwork;
 
+/* Nonzero if chip supports Thumb 2.  */
+extern int arm_arch_thumb2;
+
+/* Nonzero if chip supports integer division instruction.  */
+extern int arm_arch_hwdiv;
+
 #ifndef TARGET_DEFAULT
 #define TARGET_DEFAULT  (MASK_APCS_FRAME)
 #endif
@@ -361,6 +433,9 @@ extern int arm_cpp_interwork;
 
 #define OVERRIDE_OPTIONS  arm_override_options ()
 
+#define OPTIMIZATION_OPTIONS(LEVEL,SIZE)               \
+       arm_optimization_options ((LEVEL), (SIZE))
+
 /* Nonzero if PIC code requires explicit qualifiers to generate
    PLT and GOT relocs rather than the assembler doing so implicitly.
    Subtargets can override these if required.  */
@@ -444,6 +519,12 @@ extern int arm_cpp_interwork;
 
 #define UNITS_PER_WORD 4
 
+/* Use the option -mvectorize-with-neon-quad to override the use of doubleword
+   registers when autovectorizing for Neon, at least until multiple vector
+   widths are supported properly by the middle-end.  */
+#define UNITS_PER_SIMD_WORD(MODE) \
+  (TARGET_NEON ? (TARGET_NEON_VECTORIZE_QUAD ? 16 : 8) : UNITS_PER_WORD)
+
 /* True if natural alignment is used for doubleword types.  */
 #define ARM_DOUBLEWORD_ALIGN   TARGET_AAPCS_BASED
 
@@ -479,9 +560,23 @@ extern int arm_cpp_interwork;
 
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)                         \
    ((TREE_CODE (EXP) == STRING_CST                             \
+     && !optimize_size                                         \
      && (ALIGN) < BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR)   \
     ? BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR : (ALIGN))
 
+/* Align definitions of arrays, unions and structures so that
+   initializations and copies can be made more efficient.  This is not
+   ABI-changing, so it only affects places where we can see the
+   definition.  */
+#define DATA_ALIGNMENT(EXP, ALIGN)                                     \
+  ((((ALIGN) < BITS_PER_WORD)                                           \
+    && (TREE_CODE (EXP) == ARRAY_TYPE                                  \
+       || TREE_CODE (EXP) == UNION_TYPE                                \
+       || TREE_CODE (EXP) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
+
+/* Similarly, make sure that objects on the stack are sensibly aligned.  */
+#define LOCAL_ALIGNMENT(EXP, ALIGN) DATA_ALIGNMENT(EXP, ALIGN)
+
 /* Setting STRUCTURE_SIZE_BOUNDARY to 32 produces more efficient code, but the
    value set in previous versions of this toolchain was 8, which produces more
    compact structures.  The command line option -mstructure_size_boundary=<n>
@@ -610,6 +705,10 @@ extern int arm_structure_size_boundary;
   1,1,1,1,1,1,1,1,     \
   1,1,1,1,1,1,1,1,     \
   1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
+  1,1,1,1,1,1,1,1,     \
   1                    \
 }
 
@@ -636,6 +735,10 @@ extern int arm_structure_size_boundary;
   1,1,1,1,1,1,1,1,          \
   1,1,1,1,1,1,1,1,          \
   1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
+  1,1,1,1,1,1,1,1,          \
   1                         \
 }
 
@@ -647,7 +750,7 @@ extern int arm_structure_size_boundary;
 {                                                              \
   int regno;                                                   \
                                                                \
-  if (TARGET_SOFT_FLOAT || TARGET_THUMB || !TARGET_FPA)                \
+  if (TARGET_SOFT_FLOAT || TARGET_THUMB1 || !TARGET_FPA)       \
     {                                                          \
       for (regno = FIRST_FPA_REGNUM;                           \
           regno <= LAST_FPA_REGNUM; ++regno)                   \
@@ -659,6 +762,7 @@ extern int arm_structure_size_boundary;
       /* When optimizing for size, it's better not to use      \
         the HI regs, because of the overhead of stacking       \
         them.  */                                              \
+      /* ??? Is this still true for thumb2?  */                        \
       for (regno = FIRST_HI_REGNUM;                            \
           regno <= LAST_HI_REGNUM; ++regno)                    \
        fixed_regs[regno] = call_used_regs[regno] = 1;          \
@@ -667,10 +771,10 @@ extern int arm_structure_size_boundary;
   /* The link register can be clobbered by any branch insn,    \
      but we have no way to track that at present, so mark      \
      it as unavailable.  */                                    \
-  if (TARGET_THUMB                                           \
+  if (TARGET_THUMB1)                                           \
     fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1;     \
                                                                \
-  if (TARGET_ARM && TARGET_HARD_FLOAT)                         \
+  if (TARGET_32BIT && TARGET_HARD_FLOAT)                       \
     {                                                          \
       if (TARGET_MAVERICK)                                     \
        {                                                       \
@@ -686,11 +790,15 @@ extern int arm_structure_size_boundary;
        }                                                       \
       if (TARGET_VFP)                                          \
        {                                                       \
+         /* VFPv3 registers are disabled when earlier VFP      \
+            versions are selected due to the definition of     \
+            LAST_VFP_REGNUM.  */                               \
          for (regno = FIRST_VFP_REGNUM;                        \
               regno <= LAST_VFP_REGNUM; ++ regno)              \
            {                                                   \
              fixed_regs[regno] = 0;                            \
-             call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16; \
+             call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16 \
+               || regno >= FIRST_VFP_REGNUM + 32;              \
            }                                                   \
        }                                                       \
     }                                                          \
@@ -806,7 +914,7 @@ extern int arm_structure_size_boundary;
 /* The native (Norcroft) Pascal compiler for the ARM passes the static chain
    as an invisible last argument (possible since varargs don't exist in
    Pascal), so the following is not true.  */
-#define STATIC_CHAIN_REGNUM    (TARGET_ARM ? 12 : 9)
+#define STATIC_CHAIN_REGNUM    12
 
 /* Define this to be where the real frame pointer is if it is not possible to
    work out the offset between the frame pointer and the automatic variables
@@ -864,15 +972,47 @@ extern int arm_structure_size_boundary;
   (((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
 
 #define FIRST_VFP_REGNUM       63
-#define LAST_VFP_REGNUM                94
+#define D7_VFP_REGNUM          78  /* Registers 77 and 78 == VFP reg D7.  */
+#define LAST_VFP_REGNUM        \
+  (TARGET_VFPD32 ? LAST_HI_VFP_REGNUM : LAST_LO_VFP_REGNUM)
+
 #define IS_VFP_REGNUM(REGNUM) \
   (((REGNUM) >= FIRST_VFP_REGNUM) && ((REGNUM) <= LAST_VFP_REGNUM))
 
+/* VFP registers are split into two types: those defined by VFP versions < 3
+   have D registers overlaid on consecutive pairs of S registers. VFP version 3
+   defines 16 new D registers (d16-d31) which, for simplicity and correctness
+   in various parts of the backend, we implement as "fake" single-precision
+   registers (which would be S32-S63, but cannot be used in that way).  The
+   following macros define these ranges of registers.  */
+#define LAST_LO_VFP_REGNUM     94
+#define FIRST_HI_VFP_REGNUM    95
+#define LAST_HI_VFP_REGNUM     126
+
+#define VFP_REGNO_OK_FOR_SINGLE(REGNUM) \
+  ((REGNUM) <= LAST_LO_VFP_REGNUM)
+
+/* DFmode values are only valid in even register pairs.  */
+#define VFP_REGNO_OK_FOR_DOUBLE(REGNUM) \
+  ((((REGNUM) - FIRST_VFP_REGNUM) & 1) == 0)
+
+/* Neon Quad values must start at a multiple of four registers.  */
+#define NEON_REGNO_OK_FOR_QUAD(REGNUM) \
+  ((((REGNUM) - FIRST_VFP_REGNUM) & 3) == 0)
+
+/* Neon structures of vectors must be in even register pairs and there
+   must be enough registers available.  Because of various patterns
+   requiring quad registers, we require them to start at a multiple of
+   four.  */
+#define NEON_REGNO_OK_FOR_NREGS(REGNUM, N) \
+  ((((REGNUM) - FIRST_VFP_REGNUM) & 3) == 0 \
+   && (LAST_VFP_REGNUM - (REGNUM) >= 2 * (N) - 1))
+
 /* The number of hard registers is 16 ARM + 8 FPA + 1 CC + 1 SFP + 1 AFP.  */
 /* + 16 Cirrus registers take us up to 43.  */
 /* Intel Wireless MMX Technology registers add 16 + 4 more.  */
-/* VFP adds 32 + 1 more.  */
-#define FIRST_PSEUDO_REGISTER   96
+/* VFP (VFP3) adds 32 (64) + 1 more.  */
+#define FIRST_PSEUDO_REGISTER   128
 
 #define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
 
@@ -888,7 +1028,7 @@ extern int arm_structure_size_boundary;
 #endif
 
 #define FRAME_POINTER_REQUIRED                                 \
-  (current_function_has_nonlocal_label                         \
+  (cfun->has_nonlocal_label                            \
    || SUBTARGET_FRAME_POINTER_REQUIRED                         \
    || (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
 
@@ -900,7 +1040,7 @@ extern int arm_structure_size_boundary;
    On the ARM regs are UNITS_PER_WORD bits wide; FPA regs can hold any FP
    mode.  */
 #define HARD_REGNO_NREGS(REGNO, MODE)          \
-  ((TARGET_ARM                                 \
+  ((TARGET_32BIT                       \
     && REGNO >= FIRST_FPA_REGNUM       \
     && REGNO != FRAME_POINTER_REGNUM   \
     && REGNO != ARG_POINTER_REGNUM)    \
@@ -921,37 +1061,63 @@ extern int arm_structure_size_boundary;
 #define VALID_IWMMXT_REG_MODE(MODE) \
  (arm_vector_mode_supported_p (MODE) || (MODE) == DImode)
 
+/* Modes valid for Neon D registers.  */
+#define VALID_NEON_DREG_MODE(MODE) \
+  ((MODE) == V2SImode || (MODE) == V4HImode || (MODE) == V8QImode \
+   || (MODE) == V2SFmode || (MODE) == DImode)
+
+/* Modes valid for Neon Q registers.  */
+#define VALID_NEON_QREG_MODE(MODE) \
+  ((MODE) == V4SImode || (MODE) == V8HImode || (MODE) == V16QImode \
+   || (MODE) == V4SFmode || (MODE) == V2DImode)
+
+/* Structure modes valid for Neon registers.  */
+#define VALID_NEON_STRUCT_MODE(MODE) \
+  ((MODE) == TImode || (MODE) == EImode || (MODE) == OImode \
+   || (MODE) == CImode || (MODE) == XImode)
+
 /* The order in which register should be allocated.  It is good to use ip
    since no saving is required (though calls clobber it) and it never contains
    function parameters.  It is quite good to use lr since other calls may
    clobber it anyway.  Allocate r0 through r3 in reverse order since r3 is
    least likely to contain a function parameter; in addition results are
-   returned in r0.  */
-
-#define REG_ALLOC_ORDER            \
-{                                   \
-     3,  2,  1,  0, 12, 14,  4,  5, \
-     6,  7,  8, 10,  9, 11, 13, 15, \
-    16, 17, 18, 19, 20, 21, 22, 23, \
-    27, 28, 29, 30, 31, 32, 33, 34, \
-    35, 36, 37, 38, 39, 40, 41, 42, \
-    43, 44, 45, 46, 47, 48, 49, 50, \
-    51, 52, 53, 54, 55, 56, 57, 58, \
-    59, 60, 61, 62,                \
-    24, 25, 26,                            \
-    78, 77, 76, 75, 74, 73, 72, 71, \
-    70, 69, 68, 67, 66, 65, 64, 63, \
-    79, 80, 81, 82, 83, 84, 85, 86, \
-    87, 88, 89, 90, 91, 92, 93, 94, \
-    95                             \
+   returned in r0.
+   For VFP/VFPv3, allocate D16-D31 first, then caller-saved registers (D0-D7),
+   then D8-D15.  The reason for doing this is to attempt to reduce register
+   pressure when both single- and double-precision registers are used in a
+   function.  */
+
+#define REG_ALLOC_ORDER                                \
+{                                              \
+     3,  2,  1,  0, 12, 14,  4,  5,            \
+     6,  7,  8, 10,  9, 11, 13, 15,            \
+    16, 17, 18, 19, 20, 21, 22, 23,            \
+    27, 28, 29, 30, 31, 32, 33, 34,            \
+    35, 36, 37, 38, 39, 40, 41, 42,            \
+    43, 44, 45, 46, 47, 48, 49, 50,            \
+    51, 52, 53, 54, 55, 56, 57, 58,            \
+    59, 60, 61, 62,                            \
+    24, 25, 26,                                        \
+    95,  96,  97,  98,  99, 100, 101, 102,     \
+   103, 104, 105, 106, 107, 108, 109, 110,     \
+   111, 112, 113, 114, 115, 116, 117, 118,     \
+   119, 120, 121, 122, 123, 124, 125, 126,     \
+    78,  77,  76,  75,  74,  73,  72,  71,     \
+    70,  69,  68,  67,  66,  65,  64,  63,     \
+    79,  80,  81,  82,  83,  84,  85,  86,     \
+    87,  88,  89,  90,  91,  92,  93,  94,     \
+   127                                         \
 }
 
+/* Use different register alloc ordering for Thumb.  */
+#define ORDER_REGS_FOR_LOCAL_ALLOC arm_order_regs_for_local_alloc ()
+
 /* Interrupt functions can only use registers that have already been
    saved by the prologue, even if they would normally be
    call-clobbered.  */
 #define HARD_REGNO_RENAME_OK(SRC, DST)                                 \
        (! IS_INTERRUPT (cfun->machine->func_type) ||                   \
-               regs_ever_live[DST])
+        df_regs_ever_live_p (DST))
 \f
 /* Register and constant classes.  */
 
@@ -962,6 +1128,9 @@ enum reg_class
   NO_REGS,
   FPA_REGS,
   CIRRUS_REGS,
+  VFP_D0_D7_REGS,
+  VFP_LO_REGS,
+  VFP_HI_REGS,
   VFP_REGS,
   IWMMXT_GR_REGS,
   IWMMXT_REGS,
@@ -972,6 +1141,7 @@ enum reg_class
   CC_REG,
   VFPCC_REG,
   GENERAL_REGS,
+  CORE_REGS,
   ALL_REGS,
   LIM_REG_CLASSES
 };
@@ -984,6 +1154,9 @@ enum reg_class
   "NO_REGS",           \
   "FPA_REGS",          \
   "CIRRUS_REGS",       \
+  "VFP_D0_D7_REGS",    \
+  "VFP_LO_REGS",       \
+  "VFP_HI_REGS",       \
   "VFP_REGS",          \
   "IWMMXT_GR_REGS",    \
   "IWMMXT_REGS",       \
@@ -994,36 +1167,60 @@ enum reg_class
   "CC_REG",            \
   "VFPCC_REG",         \
   "GENERAL_REGS",      \
+  "CORE_REGS",         \
   "ALL_REGS",          \
 }
 
 /* Define which registers fit in which classes.
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
-#define REG_CLASS_CONTENTS                                     \
-{                                                              \
-  { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS  */       \
-  { 0x00FF0000, 0x00000000, 0x00000000 }, /* FPA_REGS */       \
-  { 0xF8000000, 0x000007FF, 0x00000000 }, /* CIRRUS_REGS */    \
-  { 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS  */      \
-  { 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \
-  { 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */    \
-  { 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */                \
-  { 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */      \
-  { 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */      \
-  { 0x0000FF00, 0x00000000, 0x00000000 }, /* HI_REGS */                \
-  { 0x01000000, 0x00000000, 0x00000000 }, /* CC_REG */         \
-  { 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */      \
-  { 0x0200FFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */   \
-  { 0xFAFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }  /* ALL_REGS */       \
+#define REG_CLASS_CONTENTS                                             \
+{                                                                      \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS  */   \
+  { 0x00FF0000, 0x00000000, 0x00000000, 0x00000000 }, /* FPA_REGS */   \
+  { 0xF8000000, 0x000007FF, 0x00000000, 0x00000000 }, /* CIRRUS_REGS */        \
+  { 0x00000000, 0x80000000, 0x00007FFF, 0x00000000 }, /* VFP_D0_D7_REGS  */ \
+  { 0x00000000, 0x80000000, 0x7FFFFFFF, 0x00000000 }, /* VFP_LO_REGS  */ \
+  { 0x00000000, 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_HI_REGS  */ \
+  { 0x00000000, 0x80000000, 0xFFFFFFFF, 0x7FFFFFFF }, /* VFP_REGS  */  \
+  { 0x00000000, 0x00007800, 0x00000000, 0x00000000 }, /* IWMMXT_GR_REGS */ \
+  { 0x00000000, 0x7FFF8000, 0x00000000, 0x00000000 }, /* IWMMXT_REGS */        \
+  { 0x000000FF, 0x00000000, 0x00000000, 0x00000000 }, /* LO_REGS */    \
+  { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */  \
+  { 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */  \
+  { 0x0000DF00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */    \
+  { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* CC_REG */     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */  \
+  { 0x0200DFFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+  { 0x0200FFFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */  \
+  { 0xFAFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF }  /* ALL_REGS */   \
 }
 
+/* Any of the VFP register classes.  */
+#define IS_VFP_CLASS(X) \
+  ((X) == VFP_D0_D7_REGS || (X) == VFP_LO_REGS \
+   || (X) == VFP_HI_REGS || (X) == VFP_REGS)
+
 /* The same information, inverted:
    Return the class number of the smallest class containing
    reg number REGNO.  This could be a conditional expression
    or could index an array.  */
 #define REGNO_REG_CLASS(REGNO)  arm_regno_class (REGNO)
 
+/* The following macro defines cover classes for Integrated Register
+   Allocator.  Cover classes is a set of non-intersected register
+   classes covering all hard registers used for register allocation
+   purpose.  Any move between two registers of a cover class should be
+   cheaper than load or store of the registers.  The macro value is
+   array of register classes with LIM_REG_CLASSES used as the end
+   marker.  */
+
+#define IRA_COVER_CLASSES                                                   \
+{                                                                           \
+  GENERAL_REGS, FPA_REGS, CIRRUS_REGS, VFP_REGS, IWMMXT_GR_REGS, IWMMXT_REGS,\
+  LIM_REG_CLASSES                                                           \
+}
+
 /* FPA registers can't do subreg as all values are reformatted to internal
    precision.  VFP registers may only be accessed in the mode they
    were set.  */
@@ -1041,14 +1238,14 @@ enum reg_class
      || (CLASS) == CC_REG)
 
 /* The class value for index registers, and the one for base regs.  */
-#define INDEX_REG_CLASS  (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
-#define BASE_REG_CLASS   (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
+#define INDEX_REG_CLASS  (TARGET_THUMB1 ? LO_REGS : GENERAL_REGS)
+#define BASE_REG_CLASS   (TARGET_THUMB1 ? LO_REGS : CORE_REGS)
 
 /* For the Thumb the high registers cannot be used as base registers
    when addressing quantities in QI or HI mode; if we don't know the
    mode, then we must be conservative.  */
 #define MODE_BASE_REG_CLASS(MODE)                                      \
-    (TARGET_ARM ? GENERAL_REGS :                                       \
+    (TARGET_32BIT ? CORE_REGS :                                        \
      (((MODE) == SImode) ? BASE_REGS : LO_REGS))
 
 /* For Thumb we can not support SP+reg addressing, so we return LO_REGS
@@ -1059,15 +1256,17 @@ enum reg_class
    registers explicitly used in the rtl to be used as spill registers
    but prevents the compiler from extending the lifetime of these
    registers.  */
-#define SMALL_REGISTER_CLASSES   TARGET_THUMB
+#define SMALL_REGISTER_CLASSES   TARGET_THUMB1
 
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
-   In general this is just CLASS, but for the Thumb we prefer
-   a LO_REGS class or a subset.  */
-#define PREFERRED_RELOAD_CLASS(X, CLASS)       \
-  (TARGET_ARM ? (CLASS) :                      \
-   ((CLASS) == BASE_REGS ? (CLASS) : LO_REGS))
+   In general this is just CLASS, but for the Thumb core registers and
+   immediate constants we prefer a LO_REGS class or a subset.  */
+#define PREFERRED_RELOAD_CLASS(X, CLASS)               \
+  (TARGET_ARM ? (CLASS) :                              \
+   ((CLASS) == GENERAL_REGS || (CLASS) == HI_REGS      \
+    || (CLASS) == NO_REGS || (CLASS) == STACK_REG      \
+   ? LO_REGS : (CLASS)))
 
 /* Must leave BASE_REGS reloads alone */
 #define THUMB_SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)             \
@@ -1088,27 +1287,31 @@ enum reg_class
    or out of a register in CLASS in MODE.  If it can be done directly,
    NO_REGS is returned.  */
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)          \
-  /* Restrict which direct reloads are allowed for VFP regs.  */ \
+  /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
-    && (CLASS) == VFP_REGS)                                    \
-   ? vfp_secondary_reload_class (MODE, X)                      \
-   : TARGET_ARM                                                        \
+    && IS_VFP_CLASS (CLASS))                                   \
+   ? coproc_secondary_reload_class (MODE, X, FALSE)            \
+   : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS)                 \
+   ? coproc_secondary_reload_class (MODE, X, TRUE)             \
+   : TARGET_32BIT                                              \
    ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
     ? GENERAL_REGS : NO_REGS)                                  \
    : THUMB_SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X))
 
 /* If we need to load shorts byte-at-a-time, then we need a scratch.  */
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)           \
-  /* Restrict which direct reloads are allowed for VFP regs.  */ \
+  /* Restrict which direct reloads are allowed for VFP/iWMMXt regs.  */ \
   ((TARGET_VFP && TARGET_HARD_FLOAT                            \
-    && (CLASS) == VFP_REGS)                                    \
-    ? vfp_secondary_reload_class (MODE, X) :                   \
+    && IS_VFP_CLASS (CLASS))                                   \
+    ? coproc_secondary_reload_class (MODE, X, FALSE) :         \
+    (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ?                        \
+    coproc_secondary_reload_class (MODE, X, TRUE) :            \
   /* Cannot load constants into Cirrus registers.  */          \
    (TARGET_MAVERICK && TARGET_HARD_FLOAT                       \
      && (CLASS) == CIRRUS_REGS                                 \
      && (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF))                \
     ? GENERAL_REGS :                                           \
-  (TARGET_ARM ?                                                        \
+  (TARGET_32BIT ?                                              \
    (((CLASS) == IWMMXT_REGS || (CLASS) == IWMMXT_GR_REGS)      \
       && CONSTANT_P (X))                                       \
    ? GENERAL_REGS :                                            \
@@ -1187,6 +1390,7 @@ enum reg_class
 /* We could probably achieve better results by defining PROMOTE_MODE to help
    cope with the variances between the Thumb's signed and unsigned byte and
    halfword load instructions.  */
+/* ??? This should be safe for thumb2, but we may be able to do better.  */
 #define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_L, WIN)     \
 do {                                                                         \
   rtx new_x = thumb_legitimize_reload_address (&X, MODE, OPNUM, TYPE, IND_L); \
@@ -1214,11 +1418,11 @@ do {                                                                          \
 
 /* Moves between FPA_REGS and GENERAL_REGS are two memory insns.  */
 #define REGISTER_MOVE_COST(MODE, FROM, TO)             \
-  (TARGET_ARM ?                                                \
+  (TARGET_32BIT ?                                              \
    ((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 :      \
     (FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 :      \
-    (FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 :  \
-    (FROM) != VFP_REGS && (TO) == VFP_REGS ? 10 :  \
+    IS_VFP_CLASS (FROM) && !IS_VFP_CLASS (TO) ? 10 :   \
+    !IS_VFP_CLASS (FROM) && IS_VFP_CLASS (TO) ? 10 :   \
     (FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 :  \
     (FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 :  \
     (FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 :  \
@@ -1251,7 +1455,7 @@ do {                                                                            \
    couldn't convert a direct call into an indirect one.  */
 #define CALLER_INTERWORKING_SLOT_SIZE                  \
   (TARGET_CALLER_INTERWORKING                          \
-   && current_function_outgoing_args_size != 0         \
+   && crtl->outgoing_args_size != 0            \
    ? UNITS_PER_WORD : 0)
 
 /* Offset within stack frame to start allocating local variables at.
@@ -1268,7 +1472,7 @@ do {                                                                            \
 
 /* Define this if the maximum size of all the outgoing args is to be
    accumulated and pushed during the prologue.  The amount can be
-   found in the variable current_function_outgoing_args_size.  */
+   found in the variable crtl->outgoing_args_size.  */
 #define ACCUMULATE_OUTGOING_ARGS 1
 
 /* Offset of first parameter from the argument pointer register value.  */
@@ -1288,10 +1492,10 @@ do {                                                                          \
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  */
 #define LIBCALL_VALUE(MODE)  \
-  (TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_FPA                   \
+  (TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_FPA                 \
    && GET_MODE_CLASS (MODE) == MODE_FLOAT                              \
    ? gen_rtx_REG (MODE, FIRST_FPA_REGNUM)                              \
-   : TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK            \
+   : TARGET_32BIT && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK          \
      && GET_MODE_CLASS (MODE) == MODE_FLOAT                            \
    ? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM)                        \
    : TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (MODE)           \
@@ -1310,31 +1514,21 @@ do {                                                                          \
 /* On a Cirrus chip, mvf0 can return results.  */
 #define FUNCTION_VALUE_REGNO_P(REGNO)  \
   ((REGNO) == ARG_REGISTER (1) \
-   || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM)               \
+   || (TARGET_32BIT && ((REGNO) == FIRST_CIRRUS_FP_REGNUM)             \
        && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK)                    \
    || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \
-   || (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM)                     \
+   || (TARGET_32BIT && ((REGNO) == FIRST_FPA_REGNUM)                   \
        && TARGET_HARD_FLOAT_ABI && TARGET_FPA))
 
 /* Amount of memory needed for an untyped call to save all possible return
    registers.  */
 #define APPLY_RESULT_SIZE arm_apply_result_size()
 
-/* How large values are returned */
-/* A C expression which can inhibit the returning of certain function values
-   in registers, based on the type of value.  */
-#define RETURN_IN_MEMORY(TYPE) arm_return_in_memory (TYPE)
-
 /* Define DEFAULT_PCC_STRUCT_RETURN to 1 if all structure and union return
    values must be in memory.  On the ARM, they need only do so if larger
    than a word, or if they contain elements offset from zero in the struct.  */
 #define DEFAULT_PCC_STRUCT_RETURN 0
 
-/* Flags for the call/call_value rtl operations set up by function_arg.  */
-#define CALL_NORMAL            0x00000000      /* No special processing.  */
-#define CALL_LONG              0x00000001      /* Always call indirect.  */
-#define CALL_SHORT             0x00000002      /* Never call indirect.  */
-
 /* These bits describe the different types of function supported
    by the ARM backend.  They are exclusive.  i.e. a function cannot be both a
    normal function and an interworked function, for example.  Knowing the
@@ -1361,6 +1555,7 @@ do {                                                                            \
 #define ARM_FT_NAKED           (1 << 3) /* No prologue or epilogue.  */
 #define ARM_FT_VOLATILE                (1 << 4) /* Does not return.  */
 #define ARM_FT_NESTED          (1 << 5) /* Embedded inside another func.  */
+#define ARM_FT_STACKALIGN      (1 << 6) /* Called with misaligned stack.  */
 
 /* Some macros to test these flags.  */
 #define ARM_FUNC_TYPE(t)       (t & ARM_FT_TYPE_MASK)
@@ -1368,6 +1563,7 @@ do {                                                                            \
 #define IS_VOLATILE(t)         (t & ARM_FT_VOLATILE)
 #define IS_NAKED(t)            (t & ARM_FT_NAKED)
 #define IS_NESTED(t)           (t & ARM_FT_NESTED)
+#define IS_STACKALIGN(t)               (t & ARM_FT_STACKALIGN)
 
 
 /* Structure used to hold the function stack frame layout.  Offsets are
@@ -1383,6 +1579,7 @@ typedef struct arm_stack_offsets GTY(())
   int soft_frame;      /* FRAME_POINTER_REGNUM.  */
   int locals_base;     /* THUMB_HARD_FRAME_POINTER_REGNUM.  */
   int outgoing_args;   /* STACK_POINTER_REGNUM.  */
+  unsigned int saved_regs_mask;
 }
 arm_stack_offsets;
 
@@ -1413,6 +1610,9 @@ typedef struct machine_function GTY(())
      register.  We can never call via LR or PC.  We can call via SP if a
      trampoline happens to be on the top of the stack.  */
   rtx call_via[14];
+  /* Set to 1 when a return insn is output, this means that the epilogue
+     is not needed.  */
+  int return_used_this_function;
 }
 machine_function;
 
@@ -1431,8 +1631,6 @@ typedef struct
   int iwmmxt_nregs;
   int named_count;
   int nargs;
-  /* One of CALL_NORMAL, CALL_LONG or CALL_SHORT.  */
-  int call_cookie;
   int can_split;
 } CUMULATIVE_ARGS;
 
@@ -1504,8 +1702,7 @@ typedef struct
 
 \f
 /* If your target environment doesn't prefix user functions with an
-   underscore, you may wish to re-define this to prevent any conflicts.
-   e.g. AOF may prefix mcount with an underscore.  */
+   underscore, you may wish to re-define this to prevent any conflicts.  */
 #ifndef ARM_MCOUNT_NAME
 #define ARM_MCOUNT_NAME "*mcount"
 #endif
@@ -1565,10 +1762,12 @@ typedef struct
    frame.  */
 #define EXIT_IGNORE_STACK 1
 
-#define EPILOGUE_USES(REGNO) (reload_completed && (REGNO) == LR_REGNUM)
+#define EPILOGUE_USES(REGNO) ((REGNO) == LR_REGNUM)
 
 /* Determine if the epilogue should be output as RTL.
    You should override this if you define FUNCTION_EXTRA_EPILOGUE.  */
+/* This is disabled for Thumb-2 because it will confuse the
+   conditional insn counter.  */
 #define USE_RETURN_INSN(ISCOND)                                \
   (TARGET_ARM ? use_return_insn (ISCOND, NULL) : 0)
 
@@ -1645,37 +1844,57 @@ typedef struct
   assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);       \
 }
 
-/* On the Thumb we always switch into ARM mode to execute the trampoline.
-   Why - because it is easier.  This code will always be branched to via
-   a BX instruction and since the compiler magically generates the address
-   of the function the linker has no opportunity to ensure that the
-   bottom bit is set.  Thus the processor will be in ARM mode when it
-   reaches this code.  So we duplicate the ARM trampoline code and add
-   a switch into Thumb mode as well.  */
-#define THUMB_TRAMPOLINE_TEMPLATE(FILE)                \
+/* The Thumb-2 trampoline is similar to the arm implementation.
+   Unlike 16-bit Thumb, we enter the stub in thumb mode.  */
+#define THUMB2_TRAMPOLINE_TEMPLATE(FILE)                       \
+{                                                              \
+  asm_fprintf (FILE, "\tldr.w\t%r, [%r, #4]\n",                        \
+              STATIC_CHAIN_REGNUM, PC_REGNUM);                 \
+  asm_fprintf (FILE, "\tldr.w\t%r, [%r, #4]\n",                        \
+              PC_REGNUM, PC_REGNUM);                           \
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);       \
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);       \
+}
+
+#define THUMB1_TRAMPOLINE_TEMPLATE(FILE)       \
 {                                              \
-  fprintf (FILE, "\t.code 32\n");              \
+  ASM_OUTPUT_ALIGN(FILE, 2);                   \
+  fprintf (FILE, "\t.code\t16\n");             \
   fprintf (FILE, ".Ltrampoline_start:\n");     \
-  asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n",  \
-              STATIC_CHAIN_REGNUM, PC_REGNUM); \
-  asm_fprintf (FILE, "\tldr\t%r, [%r, #8]\n",  \
-              IP_REGNUM, PC_REGNUM);           \
-  asm_fprintf (FILE, "\torr\t%r, %r, #1\n",     \
-              IP_REGNUM, IP_REGNUM);           \
-  asm_fprintf (FILE, "\tbx\t%r\n", IP_REGNUM); \
-  fprintf (FILE, "\t.word\t0\n");              \
-  fprintf (FILE, "\t.word\t0\n");              \
-  fprintf (FILE, "\t.code 16\n");              \
+  asm_fprintf (FILE, "\tpush\t{r0, r1}\n");    \
+  asm_fprintf (FILE, "\tldr\tr0, [%r, #8]\n",  \
+              PC_REGNUM);                      \
+  asm_fprintf (FILE, "\tmov\t%r, r0\n",                \
+              STATIC_CHAIN_REGNUM);            \
+  asm_fprintf (FILE, "\tldr\tr0, [%r, #8]\n",  \
+              PC_REGNUM);                      \
+  asm_fprintf (FILE, "\tstr\tr0, [%r, #4]\n",  \
+              SP_REGNUM);                      \
+  asm_fprintf (FILE, "\tpop\t{r0, %r}\n",      \
+              PC_REGNUM);                      \
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);       \
+  assemble_aligned_integer (UNITS_PER_WORD, const0_rtx);       \
 }
 
 #define TRAMPOLINE_TEMPLATE(FILE)              \
   if (TARGET_ARM)                              \
     ARM_TRAMPOLINE_TEMPLATE (FILE)             \
+  else if (TARGET_THUMB2)                      \
+    THUMB2_TRAMPOLINE_TEMPLATE (FILE)          \
   else                                         \
-    THUMB_TRAMPOLINE_TEMPLATE (FILE)
+    THUMB1_TRAMPOLINE_TEMPLATE (FILE)
+
+/* Thumb trampolines should be entered in thumb mode, so set the bottom bit
+   of the address.  */
+#define TRAMPOLINE_ADJUST_ADDRESS(ADDR) do                                 \
+{                                                                          \
+  if (TARGET_THUMB)                                                        \
+    (ADDR) = expand_simple_binop (Pmode, IOR, (ADDR), GEN_INT(1),          \
+                                 gen_reg_rtx (Pmode), 0, OPTAB_LIB_WIDEN); \
+} while(0)
 
 /* Length in units of the trampoline for entering a nested function.  */
-#define TRAMPOLINE_SIZE  (TARGET_ARM ? 16 : 24)
+#define TRAMPOLINE_SIZE  (TARGET_32BIT ? 16 : 20)
 
 /* Alignment required for a trampoline in bits.  */
 #define TRAMPOLINE_ALIGNMENT  32
@@ -1689,11 +1908,11 @@ typedef struct
 {                                                                      \
   emit_move_insn (gen_rtx_MEM (SImode,                                 \
                               plus_constant (TRAMP,                    \
-                                             TARGET_ARM ? 8 : 16)),    \
+                                             TARGET_32BIT ? 8 : 12)),  \
                  CXT);                                                 \
   emit_move_insn (gen_rtx_MEM (SImode,                                 \
                               plus_constant (TRAMP,                    \
-                                             TARGET_ARM ? 12 : 20)),   \
+                                             TARGET_32BIT ? 12 : 16)), \
                  FNADDR);                                              \
   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"),      \
                     0, VOIDmode, 2, TRAMP, Pmode,                      \
@@ -1704,13 +1923,13 @@ typedef struct
 \f
 /* Addressing modes, and classification of registers for them.  */
 #define HAVE_POST_INCREMENT   1
-#define HAVE_PRE_INCREMENT    TARGET_ARM
-#define HAVE_POST_DECREMENT   TARGET_ARM
-#define HAVE_PRE_DECREMENT    TARGET_ARM
-#define HAVE_PRE_MODIFY_DISP  TARGET_ARM
-#define HAVE_POST_MODIFY_DISP TARGET_ARM
-#define HAVE_PRE_MODIFY_REG   TARGET_ARM
-#define HAVE_POST_MODIFY_REG  TARGET_ARM
+#define HAVE_PRE_INCREMENT    TARGET_32BIT
+#define HAVE_POST_DECREMENT   TARGET_32BIT
+#define HAVE_PRE_DECREMENT    TARGET_32BIT
+#define HAVE_PRE_MODIFY_DISP  TARGET_32BIT
+#define HAVE_POST_MODIFY_DISP TARGET_32BIT
+#define HAVE_PRE_MODIFY_REG   TARGET_32BIT
+#define HAVE_POST_MODIFY_REG  TARGET_32BIT
 
 /* Macros to check register numbers against specific register classes.  */
 
@@ -1722,31 +1941,32 @@ typedef struct
 #define TEST_REGNO(R, TEST, VALUE) \
   ((R TEST VALUE) || ((unsigned) reg_renumber[R] TEST VALUE))
 
-/*   On the ARM, don't allow the pc to be used.  */
+/* Don't allow the pc to be used.  */
 #define ARM_REGNO_OK_FOR_BASE_P(REGNO)                 \
   (TEST_REGNO (REGNO, <, PC_REGNUM)                    \
    || TEST_REGNO (REGNO, ==, FRAME_POINTER_REGNUM)     \
    || TEST_REGNO (REGNO, ==, ARG_POINTER_REGNUM))
 
-#define THUMB_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)            \
+#define THUMB1_REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)           \
   (TEST_REGNO (REGNO, <=, LAST_LO_REGNUM)                      \
    || (GET_MODE_SIZE (MODE) >= 4                               \
        && TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM)))
 
 #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE)          \
-  (TARGET_THUMB                                                \
-   ? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)      \
+  (TARGET_THUMB1                                       \
+   ? THUMB1_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE)     \
    : ARM_REGNO_OK_FOR_BASE_P (REGNO))
 
 /* Nonzero if X can be the base register in a reg+reg addressing mode.
    For Thumb, we can not use SP + reg, so reject SP.  */
 #define REGNO_MODE_OK_FOR_REG_BASE_P(X, MODE)  \
-  REGNO_OK_FOR_INDEX_P (X)
+  REGNO_MODE_OK_FOR_BASE_P (X, QImode)
 
 /* For ARM code, we don't care about the mode, but for Thumb, the index
    must be suitable for use in a QImode load.  */
 #define REGNO_OK_FOR_INDEX_P(REGNO)    \
-  REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode)
+  (REGNO_MODE_OK_FOR_BASE_P (REGNO, QImode) \
+   && !TEST_REGNO (REGNO, ==, STACK_POINTER_REGNUM))
 
 /* Maximum number of registers that can appear in a valid memory address.
    Shifts in addresses can't be by a register.  */
@@ -1754,20 +1974,20 @@ typedef struct
 
 /* Recognize any constant value that is a valid address.  */
 /* XXX We can address any constant, eventually...  */
-
-#ifdef AOF_ASSEMBLER
-
-#define CONSTANT_ADDRESS_P(X)          \
-  (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X))
-
-#else
-
+/* ??? Should the TARGET_ARM here also apply to thumb2?  */
 #define CONSTANT_ADDRESS_P(X)                          \
   (GET_CODE (X) == SYMBOL_REF                  \
    && (CONSTANT_POOL_ADDRESS_P (X)             \
        || (TARGET_ARM && optimize > 0 && SYMBOL_REF_FLAG (X))))
 
-#endif /* AOF_ASSEMBLER */
+/* True if SYMBOL + OFFSET constants must refer to something within
+   SYMBOL's section.  */
+#define ARM_OFFSETS_MUST_BE_WITHIN_SECTIONS_P 0
+
+/* Nonzero if all target requires all absolute relocations be R_ARM_ABS32.  */
+#ifndef TARGET_DEFAULT_WORD_RELOCATIONS
+#define TARGET_DEFAULT_WORD_RELOCATIONS 0
+#endif
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
@@ -1786,21 +2006,9 @@ typedef struct
   || flag_pic)
 
 #define LEGITIMATE_CONSTANT_P(X)                       \
-  (!arm_tls_referenced_p (X)                           \
-   && (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X)      \
-                 : THUMB_LEGITIMATE_CONSTANT_P (X)))
-
-/* Special characters prefixed to function names
-   in order to encode attribute like information.
-   Note, '@' and '*' have already been taken.  */
-#define SHORT_CALL_FLAG_CHAR   '^'
-#define LONG_CALL_FLAG_CHAR    '#'
-
-#define ENCODED_SHORT_CALL_ATTR_P(SYMBOL_NAME) \
-  (*(SYMBOL_NAME) == SHORT_CALL_FLAG_CHAR)
-
-#define ENCODED_LONG_CALL_ATTR_P(SYMBOL_NAME)  \
-  (*(SYMBOL_NAME) == LONG_CALL_FLAG_CHAR)
+  (!arm_cannot_force_const_mem (X)                     \
+   && (TARGET_32BIT ? ARM_LEGITIMATE_CONSTANT_P (X)    \
+                   : THUMB_LEGITIMATE_CONSTANT_P (X)))
 
 #ifndef SUBTARGET_NAME_ENCODING_LENGTHS
 #define SUBTARGET_NAME_ENCODING_LENGTHS
@@ -1811,8 +2019,6 @@ typedef struct
    be stripped from the start of a function's name, if that
    name starts with the indicated character.  */
 #define ARM_NAME_ENCODING_LENGTHS              \
-  case SHORT_CALL_FLAG_CHAR: return 1;         \
-  case LONG_CALL_FLAG_CHAR:  return 1;         \
   case '*':  return 1;                         \
   SUBTARGET_NAME_ENCODING_LENGTHS
 
@@ -1822,6 +2028,11 @@ typedef struct
 #define ASM_OUTPUT_LABELREF(FILE, NAME)                \
    arm_asm_output_labelref (FILE, NAME)
 
+/* Output IT instructions for conditionally executed Thumb-2 instructions.  */
+#define ASM_OUTPUT_OPCODE(STREAM, PTR) \
+  if (TARGET_THUMB2)                   \
+    thumb2_asm_output_opcode (STREAM);
+
 /* The EABI specifies that constructors should go in .init_array.
    Other targets use .ctors for compatibility.  */
 #ifndef ARM_EABI_CTORS_SECTION_OP
@@ -1874,15 +2085,6 @@ typedef struct
 #define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P true
 #endif
 
-/* Set the short-call flag for any function compiled in the current
-   compilation unit.  We skip this for functions with the section
-   attribute when long-calls are in effect as this tells the compiler
-   that the section might be placed a long way from the caller.
-   See arm_is_longcall_p() for more information.  */
-#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL)  \
-  if (!TARGET_LONG_CALLS || ! DECL_SECTION_NAME (DECL)) \
-    arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
-
 #define ARM_OUTPUT_FN_UNWIND(F, PROLOGUE) arm_output_fn_unwind (F, PROLOGUE)
 
 #ifdef TARGET_UNWIND_INFO
@@ -1897,7 +2099,8 @@ typedef struct
    We have two alternate definitions for each of them.
    The usual definition accepts all pseudo regs; the other rejects
    them unless they have been allocated suitable hard regs.
-   The symbol REG_OK_STRICT causes the latter definition to be used.  */
+   The symbol REG_OK_STRICT causes the latter definition to be used.
+   Thumb-2 has the same restrictions as arm.  */
 #ifndef REG_OK_STRICT
 
 #define ARM_REG_OK_FOR_BASE_P(X)               \
@@ -1906,7 +2109,14 @@ typedef struct
    || REGNO (X) == FRAME_POINTER_REGNUM                \
    || REGNO (X) == ARG_POINTER_REGNUM)
 
-#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE)  \
+#define ARM_REG_OK_FOR_INDEX_P(X)              \
+  ((REGNO (X) <= LAST_ARM_REGNUM               \
+    && REGNO (X) != STACK_POINTER_REGNUM)      \
+   || REGNO (X) >= FIRST_PSEUDO_REGISTER       \
+   || REGNO (X) == FRAME_POINTER_REGNUM                \
+   || REGNO (X) == ARG_POINTER_REGNUM)
+
+#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \
   (REGNO (X) <= LAST_LO_REGNUM                 \
    || REGNO (X) >= FIRST_PSEUDO_REGISTER       \
    || (GET_MODE_SIZE (MODE) >= 4               \
@@ -1921,8 +2131,11 @@ typedef struct
 #define ARM_REG_OK_FOR_BASE_P(X)               \
   ARM_REGNO_OK_FOR_BASE_P (REGNO (X))
 
-#define THUMB_REG_MODE_OK_FOR_BASE_P(X, MODE)  \
-  THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
+#define ARM_REG_OK_FOR_INDEX_P(X)              \
+  ARM_REGNO_OK_FOR_INDEX_P (REGNO (X))
+
+#define THUMB1_REG_MODE_OK_FOR_BASE_P(X, MODE) \
+  THUMB1_REGNO_MODE_OK_FOR_BASE_P (REGNO (X), MODE)
 
 #define REG_STRICT_P 1
 
@@ -1931,22 +2144,21 @@ typedef struct
 /* Now define some helpers in terms of the above.  */
 
 #define REG_MODE_OK_FOR_BASE_P(X, MODE)                \
-  (TARGET_THUMB                                        \
-   ? THUMB_REG_MODE_OK_FOR_BASE_P (X, MODE)    \
+  (TARGET_THUMB1                               \
+   ? THUMB1_REG_MODE_OK_FOR_BASE_P (X, MODE)   \
    : ARM_REG_OK_FOR_BASE_P (X))
 
-#define ARM_REG_OK_FOR_INDEX_P(X) ARM_REG_OK_FOR_BASE_P (X)
-
-/* For Thumb, a valid index register is anything that can be used in
+/* For 16-bit Thumb, a valid index register is anything that can be used in
    a byte load instruction.  */
-#define THUMB_REG_OK_FOR_INDEX_P(X) THUMB_REG_MODE_OK_FOR_BASE_P (X, QImode)
+#define THUMB1_REG_OK_FOR_INDEX_P(X) \
+  THUMB1_REG_MODE_OK_FOR_BASE_P (X, QImode)
 
 /* Nonzero if X is a hard reg that can be used as an index
    or if it is a pseudo reg.  On the Thumb, the stack pointer
    is not suitable.  */
 #define REG_OK_FOR_INDEX_P(X)                  \
-  (TARGET_THUMB                                        \
-   ? THUMB_REG_OK_FOR_INDEX_P (X)              \
+  (TARGET_THUMB1                               \
+   ? THUMB1_REG_OK_FOR_INDEX_P (X)             \
    : ARM_REG_OK_FOR_INDEX_P (X))
 
 /* Nonzero if X can be the base register in a reg+reg addressing mode.
@@ -1971,17 +2183,25 @@ typedef struct
       goto WIN;                                                        \
   }
 
-#define THUMB_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN)             \
+#define THUMB2_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN)            \
   {                                                            \
-    if (thumb_legitimate_address_p (MODE, X, REG_STRICT_P))    \
+    if (thumb2_legitimate_address_p (MODE, X, REG_STRICT_P))   \
+      goto WIN;                                                        \
+  }
+
+#define THUMB1_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN)            \
+  {                                                            \
+    if (thumb1_legitimate_address_p (MODE, X, REG_STRICT_P))   \
       goto WIN;                                                        \
   }
 
 #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, WIN)                         \
   if (TARGET_ARM)                                                      \
     ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)                        \
-  else /* if (TARGET_THUMB) */                                         \
-    THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
+  else if (TARGET_THUMB2)                                              \
+    THUMB2_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)                     \
+  else /* if (TARGET_THUMB1) */                                                \
+    THUMB1_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
 
 \f
 /* Try machine-dependent ways of modifying an illegitimate address
@@ -1991,7 +2211,12 @@ do {                                                     \
   X = arm_legitimize_address (X, OLDX, MODE);          \
 } while (0)
 
-#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)   \
+/* ??? Implement LEGITIMIZE_ADDRESS for thumb2.  */
+#define THUMB2_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)  \
+do {                                                   \
+} while (0)
+
+#define THUMB1_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)  \
 do {                                                   \
   X = thumb_legitimize_address (X, OLDX, MODE);                \
 } while (0)
@@ -2000,8 +2225,10 @@ do {                                                     \
 do {                                                   \
   if (TARGET_ARM)                                      \
     ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);       \
+  else if (TARGET_THUMB2)                              \
+    THUMB2_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);    \
   else                                                 \
-    THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);     \
+    THUMB1_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN);    \
                                                        \
   if (memory_address_p (MODE, X))                      \
     goto WIN;                                          \
@@ -2018,7 +2245,7 @@ do {                                                      \
 
 /* Nothing helpful to do for the Thumb */
 #define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)      \
-  if (TARGET_ARM)                                      \
+  if (TARGET_32BIT)                                    \
     ARM_GO_IF_MODE_DEPENDENT_ADDRESS (ADDR, LABEL)
 \f
 
@@ -2026,6 +2253,13 @@ do {                                                     \
    for the index in the tablejump instruction.  */
 #define CASE_VECTOR_MODE Pmode
 
+#define CASE_VECTOR_PC_RELATIVE TARGET_THUMB2
+
+#define CASE_VECTOR_SHORTEN_MODE(min, max, body)               \
+   ((min < 0 || max >= 0x2000 || !TARGET_THUMB2) ? SImode      \
+   : (max >= 0x200) ? HImode                                   \
+   : QImode)
+
 /* signed 'char' is most compatible, but RISC OS wants it unsigned.
    unsigned is probably best, but may break some code.  */
 #ifndef DEFAULT_SIGNED_CHAR
@@ -2037,7 +2271,7 @@ do {                                                      \
 #define MOVE_MAX 4
 
 #undef  MOVE_RATIO
-#define MOVE_RATIO (arm_tune_xscale ? 4 : 2)
+#define MOVE_RATIO(speed) (arm_tune_xscale ? 4 : 2)
 
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
@@ -2084,14 +2318,14 @@ do {                                                    \
 
 /* Moves to and from memory are quite expensive */
 #define MEMORY_MOVE_COST(M, CLASS, IN)                 \
-  (TARGET_ARM ? 10 :                                   \
+  (TARGET_32BIT ? 10 :                                 \
    ((GET_MODE_SIZE (M) < 4 ? 8 : 2 * GET_MODE_SIZE (M))        \
     * (CLASS == LO_REGS ? 1 : 2)))
 
 /* Try to generate sequences that don't involve branches, we can then use
    conditional instructions */
-#define BRANCH_COST \
-  (TARGET_ARM ? 4 : (optimize > 1 ? 1 : 0))
+#define BRANCH_COST(speed_p, predictable_p) \
+  (TARGET_32BIT ? 4 : (optimize > 0 ? 2 : 0))
 \f
 /* Position Independent Code.  */
 /* We decide which register to use based on the compilation options and
@@ -2121,10 +2355,12 @@ extern unsigned arm_pic_register;
 extern int making_const_table;
 \f
 /* Handle pragmas for compatibility with Intel's compilers.  */
+/* Also abuse this to register additional C specific EABI attributes.  */
 #define REGISTER_TARGET_PRAGMAS() do {                                 \
   c_register_pragma (0, "long_calls", arm_pr_long_calls);              \
   c_register_pragma (0, "no_long_calls", arm_pr_no_long_calls);                \
   c_register_pragma (0, "long_calls_off", arm_pr_long_calls_off);      \
+  arm_lang_object_attributes_init(); \
 } while (0)
 
 /* Condition code information.  */
@@ -2159,7 +2395,8 @@ extern int making_const_table;
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE)  ((VALUE) = 32, 1)
 \f
 #undef  ASM_APP_OFF
-#define ASM_APP_OFF (TARGET_THUMB ? "\t.code\t16\n" : "")
+#define ASM_APP_OFF (TARGET_THUMB1 ? "\t.code\t16\n" : \
+                    TARGET_THUMB2 ? "\t.thumb\n" : "")
 
 /* Output a push or a pop instruction (only used when profiling).  */
 #define ASM_OUTPUT_REG_PUSH(STREAM, REGNO)             \
@@ -2183,16 +2420,28 @@ extern int making_const_table;
        asm_fprintf (STREAM, "\tpop {%r}\n", REGNO);    \
     } while (0)
 
+/* Jump table alignment is explicit in ASM_OUTPUT_CASE_LABEL.  */
+#define ADDR_VEC_ALIGN(JUMPTABLE) 0
+
 /* This is how to output a label which precedes a jumptable.  Since
    Thumb instructions are 2 bytes, we may need explicit alignment here.  */
 #undef  ASM_OUTPUT_CASE_LABEL
-#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE)    \
-  do                                                           \
-    {                                                          \
-      if (TARGET_THUMB)                                                \
-        ASM_OUTPUT_ALIGN (FILE, 2);                            \
-      (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM);   \
-    }                                                          \
+#define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, JUMPTABLE)            \
+  do                                                                   \
+    {                                                                  \
+      if (TARGET_THUMB && GET_MODE (PATTERN (JUMPTABLE)) == SImode)    \
+        ASM_OUTPUT_ALIGN (FILE, 2);                                    \
+      (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM);           \
+    }                                                                  \
+  while (0)
+
+/* Make sure subsequent insns are aligned after a TBB.  */
+#define ASM_OUTPUT_CASE_END(FILE, NUM, JUMPTABLE)      \
+  do                                                   \
+    {                                                  \
+      if (GET_MODE (PATTERN (JUMPTABLE)) == QImode)    \
+       ASM_OUTPUT_ALIGN (FILE, 1);                     \
+    }                                                  \
   while (0)
 
 #define ARM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL)  \
@@ -2200,14 +2449,17 @@ extern int making_const_table;
     {                                                  \
       if (TARGET_THUMB)                                \
         {                                              \
-          if (is_called_in_ARM_mode (DECL)      \
-                         || current_function_is_thunk)         \
+          if (is_called_in_ARM_mode (DECL)             \
+             || (TARGET_THUMB1 && !TARGET_THUMB1_ONLY  \
+                 && cfun->is_thunk))   \
             fprintf (STREAM, "\t.code 32\n") ;         \
+          else if (TARGET_THUMB1)                      \
+           fprintf (STREAM, "\t.code\t16\n\t.thumb_func\n") ;  \
           else                                         \
-           fprintf (STREAM, "\t.code 16\n\t.thumb_func\n") ;   \
+           fprintf (STREAM, "\t.thumb\n\t.thumb_func\n") ;     \
         }                                              \
       if (TARGET_POKE_FUNCTION_NAME)                   \
-        arm_poke_function_name (STREAM, (char *) NAME);        \
+        arm_poke_function_name (STREAM, (const char *) NAME);  \
     }                                                  \
   while (0)
 
@@ -2246,17 +2498,28 @@ extern int making_const_table;
     }
 #endif
 \f
+/* Add two bytes to the length of conditionally executed Thumb-2
+   instructions for the IT instruction.  */
+#define ADJUST_INSN_LENGTH(insn, length) \
+  if (TARGET_THUMB2 && GET_CODE (PATTERN (insn)) == COND_EXEC) \
+    length += 2;
+
 /* Only perform branch elimination (by making instructions conditional) if
-   we're optimizing.  Otherwise it's of no use anyway.  */
+   we're optimizing.  For Thumb-2 check if any IT instructions need
+   outputting.  */
 #define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS)     \
   if (TARGET_ARM && optimize)                          \
     arm_final_prescan_insn (INSN);                     \
-  else if (TARGET_THUMB)                               \
-    thumb_final_prescan_insn (INSN)
+  else if (TARGET_THUMB2)                              \
+    thumb2_final_prescan_insn (INSN);                  \
+  else if (TARGET_THUMB1)                              \
+    thumb1_final_prescan_insn (INSN)
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)      \
-  (CODE == '@' || CODE == '|'                  \
-   || (TARGET_ARM   && (CODE == '?'))          \
+  (CODE == '@' || CODE == '|' || CODE == '.'   \
+   || CODE == '(' || CODE == ')' || CODE == '#'        \
+   || (TARGET_32BIT && (CODE == '?'))          \
+   || (TARGET_THUMB2 && (CODE == '!'))         \
    || (TARGET_THUMB && (CODE == '_')))
 
 /* Output an operand of an instruction.  */
@@ -2283,10 +2546,12 @@ extern int making_const_table;
        rtx base = XEXP (X, 0);                                         \
        rtx index = XEXP (X, 1);                                        \
        HOST_WIDE_INT offset = 0;                                       \
-       if (GET_CODE (base) != REG)                                     \
+       if (GET_CODE (base) != REG                                      \
+           || (GET_CODE (index) == REG && REGNO (index) == SP_REGNUM)) \
          {                                                             \
            /* Ensure that BASE is a register.  */                      \
             /* (one of them must be).  */                              \
+           /* Also ensure the SP is not used as in index register.  */ \
            rtx temp = base;                                            \
            base = index;                                               \
            index = temp;                                               \
@@ -2389,7 +2654,7 @@ extern int making_const_table;
 }
 
 #define PRINT_OPERAND_ADDRESS(STREAM, X)       \
-  if (TARGET_ARM)                              \
+  if (TARGET_32BIT)                            \
     ARM_PRINT_OPERAND_ADDRESS (STREAM, X)      \
   else                                         \
     THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
@@ -2426,6 +2691,9 @@ extern int making_const_table;
    : arm_gen_return_addr_mask ())
 
 \f
+/* Neon defines builtins from ARM_BUILTIN_MAX upwards, though they don't have
+   symbolic names defined here (which would require too much duplication).
+   FIXME?  */
 enum arm_builtins
 {
   ARM_BUILTIN_GETWCX,
@@ -2590,7 +2858,9 @@ enum arm_builtins
 
   ARM_BUILTIN_THREAD_POINTER,
 
-  ARM_BUILTIN_MAX
+  ARM_BUILTIN_NEON_BASE,
+
+  ARM_BUILTIN_MAX = ARM_BUILTIN_NEON_BASE  /* FIXME: Wrong!  */
 };
 
 /* Do not emit .note.GNU-stack by default.  */