OSDN Git Service

2009-04-02 Chao-ying Fu <fu@mips.com>
[pf3gnuchains/gcc-fork.git] / gcc / config / mips / mips.h
index 2425d13..fbcfdca 100644 (file)
@@ -1,6 +1,7 @@
 /* Definitions of target machine for GNU compiler.  MIPS version.
    Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
-   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by A. Lichnewsky (lich@inria.inria.fr).
    Changed by Michael Meissner (meissner@osf.org).
    64-bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
@@ -10,7 +11,7 @@ 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)
+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,
@@ -19,9 +20,8 @@ MERCHANTABILITY or 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/>.  */
 
 
 #include "config/vxworks-dummy.h"
@@ -47,7 +47,10 @@ enum processor_type {
   PROCESSOR_74KF2_1,
   PROCESSOR_74KF1_1,
   PROCESSOR_74KF3_2,
+  PROCESSOR_LOONGSON_2E,
+  PROCESSOR_LOONGSON_2F,
   PROCESSOR_M4K,
+  PROCESSOR_OCTEON,
   PROCESSOR_R3900,
   PROCESSOR_R6000,
   PROCESSOR_R4000,
@@ -64,9 +67,11 @@ enum processor_type {
   PROCESSOR_R7000,
   PROCESSOR_R8000,
   PROCESSOR_R9000,
+  PROCESSOR_R10000,
   PROCESSOR_SB1,
   PROCESSOR_SB1A,
   PROCESSOR_SR71000,
+  PROCESSOR_XLR,
   PROCESSOR_MAX
 };
 
@@ -97,6 +102,14 @@ struct mips_rtx_cost_data
 #define ABI_EABI 3
 #define ABI_O64  4
 
+/* Masks that affect tuning.
+
+   PTF_AVOID_BRANCHLIKELY
+       Set if it is usually not profitable to use branch-likely instructions
+       for this target, typically because the branches are always predicted
+       taken and so incur a large overhead when not taken.  */
+#define PTF_AVOID_BRANCHLIKELY 0x1
+
 /* Information about one recognized processor.  Defined here for the
    benefit of TARGET_CPU_CPP_BUILTINS.  */
 struct mips_cpu_info {
@@ -112,32 +125,17 @@ struct mips_cpu_info {
 
   /* The ISA level that the processor implements.  */
   int isa;
+
+  /* A mask of PTF_* values.  */
+  unsigned int tune_flags;
 };
 
-#ifndef USED_FOR_TARGET
-extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */
-extern const char *current_function_file; /* filename current function is in */
-extern int num_source_filenames;       /* current .file # */
-extern int mips_section_threshold;     /* # bytes of data/sdata cutoff */
-extern int sym_lineno;                 /* sgi next label # for each stmt */
-extern int set_noreorder;              /* # of nested .set noreorder's  */
-extern int set_nomacro;                        /* # of nested .set nomacro's  */
-extern int set_noat;                   /* # of nested .set noat's  */
-extern int set_volatile;               /* # of nested .set volatile's  */
-extern int mips_branch_likely;         /* emit 'l' after br (branch likely) */
-extern int mips_dbx_regno[];           /* Map register # to debug register # */
-extern bool mips_split_p[];
-extern GTY(()) rtx cmp_operands[2];
-extern enum processor_type mips_arch;   /* which cpu to codegen for */
-extern enum processor_type mips_tune;   /* which cpu to schedule for */
-extern int mips_isa;                   /* architectural level */
-extern int mips_abi;                   /* which ABI to use */
-extern int mips16_hard_float;          /* mips16 without -msoft-float */
-extern const struct mips_cpu_info mips_cpu_info_table[];
-extern const struct mips_cpu_info *mips_arch_info;
-extern const struct mips_cpu_info *mips_tune_info;
-extern const struct mips_rtx_cost_data *mips_cost;
-#endif
+/* Enumerates the setting of the -mcode-readable option.  */
+enum mips_code_readable_setting {
+  CODE_READABLE_NO,
+  CODE_READABLE_PCREL,
+  CODE_READABLE_YES
+};
 
 /* Macros to silence warnings about numbers being signed in traditional
    C and unsigned in ISO C when compiled on 32-bit hosts.  */
@@ -152,6 +150,15 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* True if we are generating position-independent VxWorks RTP code.  */
 #define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic)
 
+/* True if the output file is marked as ".abicalls; .option pic0"
+   (-call_nonpic).  */
+#define TARGET_ABICALLS_PIC0 \
+  (TARGET_ABSOLUTE_ABICALLS && TARGET_PLT)
+
+/* True if the output file is marked as ".abicalls; .option pic2" (-KPIC).  */
+#define TARGET_ABICALLS_PIC2 \
+  (TARGET_ABICALLS && !TARGET_ABICALLS_PIC0)
+
 /* True if the call patterns should be split into a jalr followed by
    an instruction to restore $gp.  It is only safe to split the load
    from the call when every use of $gp is explicit.  */
@@ -204,15 +211,28 @@ extern const struct mips_rtx_cost_data *mips_cost;
    Although GAS does understand .gpdword, the SGI linker mishandles
    the relocations GAS generates (R_MIPS_GPREL32 followed by R_MIPS_64).
    We therefore disable GP-relative switch tables for n64 on IRIX targets.  */
-#define TARGET_GPWORD (TARGET_ABICALLS && !(mips_abi == ABI_64 && TARGET_IRIX))
+#define TARGET_GPWORD                          \
+  (TARGET_ABICALLS                             \
+   && !TARGET_ABSOLUTE_ABICALLS                        \
+   && !(mips_abi == ABI_64 && TARGET_IRIX))
 
 /* Generate mips16 code */
 #define TARGET_MIPS16          ((target_flags & MASK_MIPS16) != 0)
-/* Generate mips16e code. Default 16bit ASE for mips32/mips32r2/mips64 */
+/* Generate mips16e code. Default 16bit ASE for mips32* and mips64* */
 #define GENERATE_MIPS16E       (TARGET_MIPS16 && mips_isa >= 32)
 /* Generate mips16e register save/restore sequences.  */
 #define GENERATE_MIPS16E_SAVE_RESTORE (GENERATE_MIPS16E && mips_abi == ABI_32)
 
+/* True if we're generating a form of MIPS16 code in which general
+   text loads are allowed.  */
+#define TARGET_MIPS16_TEXT_LOADS \
+  (TARGET_MIPS16 && mips_code_readable == CODE_READABLE_YES)
+
+/* True if we're generating a form of MIPS16 code in which PC-relative
+   loads are allowed.  */
+#define TARGET_MIPS16_PCREL_LOADS \
+  (TARGET_MIPS16 && mips_code_readable >= CODE_READABLE_PCREL)
+
 /* Generic ISA defines.  */
 #define ISA_MIPS1                  (mips_isa == 1)
 #define ISA_MIPS2                  (mips_isa == 2)
@@ -221,8 +241,12 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define ISA_MIPS32                 (mips_isa == 32)
 #define ISA_MIPS32R2               (mips_isa == 33)
 #define ISA_MIPS64                  (mips_isa == 64)
+#define ISA_MIPS64R2               (mips_isa == 65)
 
 /* Architecture target defines.  */
+#define TARGET_LOONGSON_2E          (mips_arch == PROCESSOR_LOONGSON_2E)
+#define TARGET_LOONGSON_2F          (mips_arch == PROCESSOR_LOONGSON_2F)
+#define TARGET_LOONGSON_2EF         (TARGET_LOONGSON_2E || TARGET_LOONGSON_2F)
 #define TARGET_MIPS3900             (mips_arch == PROCESSOR_R3900)
 #define TARGET_MIPS4000             (mips_arch == PROCESSOR_R4000)
 #define TARGET_MIPS4120             (mips_arch == PROCESSOR_R4120)
@@ -231,11 +255,22 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define TARGET_MIPS5500             (mips_arch == PROCESSOR_R5500)
 #define TARGET_MIPS7000             (mips_arch == PROCESSOR_R7000)
 #define TARGET_MIPS9000             (mips_arch == PROCESSOR_R9000)
+#define TARGET_OCTEON              (mips_arch == PROCESSOR_OCTEON)
 #define TARGET_SB1                  (mips_arch == PROCESSOR_SB1                \
                                     || mips_arch == PROCESSOR_SB1A)
 #define TARGET_SR71K                (mips_arch == PROCESSOR_SR71000)
 
 /* Scheduling target defines.  */
+#define TUNE_20KC                  (mips_tune == PROCESSOR_20KC)
+#define TUNE_24K                   (mips_tune == PROCESSOR_24KC        \
+                                    || mips_tune == PROCESSOR_24KF2_1  \
+                                    || mips_tune == PROCESSOR_24KF1_1)
+#define TUNE_74K                    (mips_tune == PROCESSOR_74KC       \
+                                    || mips_tune == PROCESSOR_74KF2_1  \
+                                    || mips_tune == PROCESSOR_74KF1_1  \
+                                    || mips_tune == PROCESSOR_74KF3_2)
+#define TUNE_LOONGSON_2EF           (mips_tune == PROCESSOR_LOONGSON_2E        \
+                                    || mips_tune == PROCESSOR_LOONGSON_2F)
 #define TUNE_MIPS3000               (mips_tune == PROCESSOR_R3000)
 #define TUNE_MIPS3900               (mips_tune == PROCESSOR_R3900)
 #define TUNE_MIPS4000               (mips_tune == PROCESSOR_R4000)
@@ -247,12 +282,15 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define TUNE_MIPS6000               (mips_tune == PROCESSOR_R6000)
 #define TUNE_MIPS7000               (mips_tune == PROCESSOR_R7000)
 #define TUNE_MIPS9000               (mips_tune == PROCESSOR_R9000)
+#define TUNE_OCTEON                (mips_tune == PROCESSOR_OCTEON)
 #define TUNE_SB1                    (mips_tune == PROCESSOR_SB1                \
                                     || mips_tune == PROCESSOR_SB1A)
-#define TUNE_74K                    (mips_tune == PROCESSOR_74KC       \
-                                    || mips_tune == PROCESSOR_74KF2_1  \
-                                    || mips_tune == PROCESSOR_74KF1_1  \
-                                    || mips_tune == PROCESSOR_74KF3_2)
+
+/* Whether vector modes and intrinsics for ST Microelectronics
+   Loongson-2E/2F processors should be enabled.  In o32 pairs of
+   floating-point registers provide 64-bit values.  */
+#define TARGET_LOONGSON_VECTORS            (TARGET_HARD_FLOAT_ABI              \
+                                    && TARGET_LOONGSON_2EF)
 
 /* True if the pre-reload scheduler should try to create chains of
    multiply-add or multiply-subtract instructions.  For example,
@@ -287,16 +325,19 @@ extern const struct mips_rtx_cost_data *mips_cost;
    than others, so this macro is defined on an opt-in basis.  */
 #define TUNE_MACC_CHAINS           (TUNE_MIPS5500              \
                                     || TUNE_MIPS4120           \
-                                    || TUNE_MIPS4130)
+                                    || TUNE_MIPS4130           \
+                                    || TUNE_24K)
 
 #define TARGET_OLDABI              (mips_abi == ABI_32 || mips_abi == ABI_O64)
 #define TARGET_NEWABI              (mips_abi == ABI_N32 || mips_abi == ABI_64)
 
-/* Similar to TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT, but reflect the ABI
-   in use rather than whether the FPU is directly accessible.  */
-#define TARGET_HARD_FLOAT_ABI (TARGET_HARD_FLOAT || mips16_hard_float)
-#define TARGET_SOFT_FLOAT_ABI (!TARGET_HARD_FLOAT_ABI)
-
+/* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is
+   directly accessible, while the command-line options select
+   TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI to reflect the ABI
+   in use.  */
+#define TARGET_HARD_FLOAT (TARGET_HARD_FLOAT_ABI && !TARGET_MIPS16)
+#define TARGET_SOFT_FLOAT (TARGET_SOFT_FLOAT_ABI || TARGET_MIPS16)
+  
 /* IRIX specific stuff.  */
 #define TARGET_IRIX       0
 #define TARGET_IRIX6      0
@@ -321,157 +362,219 @@ extern const struct mips_rtx_cost_data *mips_cost;
   while (0)
 
 /* Target CPU builtins.  */
-#define TARGET_CPU_CPP_BUILTINS()                              \
-  do                                                           \
-    {                                                          \
-      /* Everyone but IRIX defines this to mips.  */            \
-      if (!TARGET_IRIX)                                         \
-        builtin_assert ("machine=mips");                        \
-                                                                \
-      builtin_assert ("cpu=mips");                             \
-      builtin_define ("__mips__");                                     \
-      builtin_define ("_mips");                                        \
-                                                               \
-      /* We do this here because __mips is defined below       \
-        and so we can't use builtin_define_std.  */            \
-      if (!flag_iso)                                           \
-       builtin_define ("mips");                                \
-                                                               \
-      if (TARGET_64BIT)                                                \
-       builtin_define ("__mips64");                            \
-                                                               \
-      if (!TARGET_IRIX)                                                \
-       {                                                       \
-         /* Treat _R3000 and _R4000 like register-size         \
-            defines, which is how they've historically         \
-            been used.  */                                     \
-         if (TARGET_64BIT)                                     \
-           {                                                   \
-             builtin_define_std ("R4000");                     \
-             builtin_define ("_R4000");                        \
-           }                                                   \
-         else                                                  \
-           {                                                   \
-             builtin_define_std ("R3000");                     \
-             builtin_define ("_R3000");                        \
-           }                                                   \
-       }                                                       \
-      if (TARGET_FLOAT64)                                      \
-       builtin_define ("__mips_fpr=64");                       \
-      else                                                     \
-       builtin_define ("__mips_fpr=32");                       \
-                                                               \
-      if (TARGET_MIPS16)                                       \
-       builtin_define ("__mips16");                            \
-                                                               \
-      if (TARGET_MIPS3D)                                       \
-       builtin_define ("__mips3d");                            \
-                                                                \
-      if (TARGET_SMARTMIPS)                                    \
-       builtin_define ("__mips_smartmips");                    \
-                                                               \
-      if (TARGET_DSP)                                          \
-       builtin_define ("__mips_dsp");                          \
-                                                               \
-      if (TARGET_DSPR2)                                                \
-       builtin_define ("__mips_dspr2");                        \
-                                                               \
-      MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info);   \
-      MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info);   \
-                                                               \
-      if (ISA_MIPS1)                                           \
-       {                                                       \
-         builtin_define ("__mips=1");                          \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS1");         \
-       }                                                       \
-      else if (ISA_MIPS2)                                      \
-       {                                                       \
-         builtin_define ("__mips=2");                          \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS2");         \
-       }                                                       \
-      else if (ISA_MIPS3)                                      \
-       {                                                       \
-         builtin_define ("__mips=3");                          \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS3");         \
-       }                                                       \
-      else if (ISA_MIPS4)                                      \
-       {                                                       \
-         builtin_define ("__mips=4");                          \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS4");         \
-       }                                                       \
-      else if (ISA_MIPS32)                                     \
-       {                                                       \
-         builtin_define ("__mips=32");                         \
-         builtin_define ("__mips_isa_rev=1");                  \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");        \
-       }                                                       \
-      else if (ISA_MIPS32R2)                                   \
-       {                                                       \
-         builtin_define ("__mips=32");                         \
-         builtin_define ("__mips_isa_rev=2");                  \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");        \
-       }                                                       \
-      else if (ISA_MIPS64)                                     \
-       {                                                       \
-         builtin_define ("__mips=64");                         \
-         builtin_define ("__mips_isa_rev=1");                  \
-         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");        \
-       }                                                       \
-                                                               \
-      /* These defines reflect the ABI in use, not whether the  \
-        FPU is directly accessible.  */                        \
-      if (TARGET_HARD_FLOAT_ABI)                               \
-       builtin_define ("__mips_hard_float");                   \
-      else                                                     \
-       builtin_define ("__mips_soft_float");                   \
-                                                               \
-      if (TARGET_SINGLE_FLOAT)                                 \
-       builtin_define ("__mips_single_float");                 \
-                                                               \
-      if (TARGET_PAIRED_SINGLE_FLOAT)                          \
-       builtin_define ("__mips_paired_single_float");          \
-                                                               \
-      if (TARGET_BIG_ENDIAN)                                   \
-       {                                                       \
-         builtin_define_std ("MIPSEB");                        \
-         builtin_define ("_MIPSEB");                           \
-       }                                                       \
-      else                                                     \
-       {                                                       \
-         builtin_define_std ("MIPSEL");                        \
-         builtin_define ("_MIPSEL");                           \
-       }                                                       \
-                                                               \
-        /* Macros dependent on the C dialect.  */              \
-      if (preprocessing_asm_p ())                              \
-       {                                                       \
-          builtin_define_std ("LANGUAGE_ASSEMBLY");            \
-         builtin_define ("_LANGUAGE_ASSEMBLY");                \
-       }                                                       \
-      else if (c_dialect_cxx ())                               \
-        {                                                      \
-         builtin_define ("_LANGUAGE_C_PLUS_PLUS");             \
-          builtin_define ("__LANGUAGE_C_PLUS_PLUS");           \
-          builtin_define ("__LANGUAGE_C_PLUS_PLUS__");         \
-        }                                                      \
-      else                                                     \
-       {                                                       \
-          builtin_define_std ("LANGUAGE_C");                   \
-         builtin_define ("_LANGUAGE_C");                       \
-       }                                                       \
-      if (c_dialect_objc ())                                   \
-        {                                                      \
-         builtin_define ("_LANGUAGE_OBJECTIVE_C");             \
-          builtin_define ("__LANGUAGE_OBJECTIVE_C");           \
-         /* Bizarre, but needed at least for Irix.  */         \
-         builtin_define_std ("LANGUAGE_C");                    \
-         builtin_define ("_LANGUAGE_C");                       \
-        }                                                      \
-                                                               \
-      if (mips_abi == ABI_EABI)                                        \
-       builtin_define ("__mips_eabi");                         \
-                                                               \
-} while (0)
+#define TARGET_CPU_CPP_BUILTINS()                                      \
+  do                                                                   \
+    {                                                                  \
+      /* Everyone but IRIX defines this to mips.  */                   \
+      if (!TARGET_IRIX)                                                \
+       builtin_assert ("machine=mips");                                \
+                                                                       \
+      builtin_assert ("cpu=mips");                                     \
+      builtin_define ("__mips__");                                             \
+      builtin_define ("_mips");                                                \
+                                                                       \
+      /* We do this here because __mips is defined below and so we     \
+        can't use builtin_define_std.  We don't ever want to define    \
+        "mips" for VxWorks because some of the VxWorks headers         \
+        construct include filenames from a root directory macro,       \
+        an architecture macro and a filename, where the architecture   \
+        macro expands to 'mips'.  If we define 'mips' to 1, the        \
+        architecture macro expands to 1 as well.  */                   \
+      if (!flag_iso && !TARGET_VXWORKS)                                        \
+       builtin_define ("mips");                                        \
+                                                                       \
+      if (TARGET_64BIT)                                                        \
+       builtin_define ("__mips64");                                    \
+                                                                       \
+      if (!TARGET_IRIX)                                                        \
+       {                                                               \
+         /* Treat _R3000 and _R4000 like register-size                 \
+            defines, which is how they've historically                 \
+            been used.  */                                             \
+         if (TARGET_64BIT)                                             \
+           {                                                           \
+             builtin_define_std ("R4000");                             \
+             builtin_define ("_R4000");                                \
+           }                                                           \
+         else                                                          \
+           {                                                           \
+             builtin_define_std ("R3000");                             \
+             builtin_define ("_R3000");                                \
+           }                                                           \
+       }                                                               \
+      if (TARGET_FLOAT64)                                              \
+       builtin_define ("__mips_fpr=64");                               \
+      else                                                             \
+       builtin_define ("__mips_fpr=32");                               \
+                                                                       \
+      if (mips_base_mips16)                                            \
+       builtin_define ("__mips16");                                    \
+                                                                       \
+      if (TARGET_MIPS3D)                                               \
+       builtin_define ("__mips3d");                                    \
+                                                                       \
+      if (TARGET_SMARTMIPS)                                            \
+       builtin_define ("__mips_smartmips");                            \
+                                                                       \
+      if (TARGET_DSP)                                                  \
+       {                                                               \
+         builtin_define ("__mips_dsp");                                \
+         if (TARGET_DSPR2)                                             \
+           {                                                           \
+             builtin_define ("__mips_dspr2");                          \
+             builtin_define ("__mips_dsp_rev=2");                      \
+           }                                                           \
+         else                                                          \
+           builtin_define ("__mips_dsp_rev=1");                        \
+       }                                                               \
+                                                                       \
+      MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info);           \
+      MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info);           \
+                                                                       \
+      if (ISA_MIPS1)                                                   \
+       {                                                               \
+         builtin_define ("__mips=1");                                  \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS1");                 \
+       }                                                               \
+      else if (ISA_MIPS2)                                              \
+       {                                                               \
+         builtin_define ("__mips=2");                                  \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS2");                 \
+       }                                                               \
+      else if (ISA_MIPS3)                                              \
+       {                                                               \
+         builtin_define ("__mips=3");                                  \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS3");                 \
+       }                                                               \
+      else if (ISA_MIPS4)                                              \
+       {                                                               \
+         builtin_define ("__mips=4");                                  \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS4");                 \
+       }                                                               \
+      else if (ISA_MIPS32)                                             \
+       {                                                               \
+         builtin_define ("__mips=32");                                 \
+         builtin_define ("__mips_isa_rev=1");                          \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");                \
+       }                                                               \
+      else if (ISA_MIPS32R2)                                           \
+       {                                                               \
+         builtin_define ("__mips=32");                                 \
+         builtin_define ("__mips_isa_rev=2");                          \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32");                \
+       }                                                               \
+      else if (ISA_MIPS64)                                             \
+       {                                                               \
+         builtin_define ("__mips=64");                                 \
+         builtin_define ("__mips_isa_rev=1");                          \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");                \
+       }                                                               \
+      else if (ISA_MIPS64R2)                                           \
+       {                                                               \
+         builtin_define ("__mips=64");                                 \
+         builtin_define ("__mips_isa_rev=2");                          \
+         builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64");                \
+       }                                                               \
+                                                                       \
+      switch (mips_abi)                                                        \
+       {                                                               \
+       case ABI_32:                                                    \
+         builtin_define ("_ABIO32=1");                                 \
+         builtin_define ("_MIPS_SIM=_ABIO32");                         \
+         break;                                                        \
+                                                                       \
+       case ABI_N32:                                                   \
+         builtin_define ("_ABIN32=2");                                 \
+         builtin_define ("_MIPS_SIM=_ABIN32");                         \
+         break;                                                        \
+                                                                       \
+       case ABI_64:                                                    \
+         builtin_define ("_ABI64=3");                                  \
+         builtin_define ("_MIPS_SIM=_ABI64");                          \
+         break;                                                        \
+                                                                       \
+       case ABI_O64:                                                   \
+         builtin_define ("_ABIO64=4");                                 \
+         builtin_define ("_MIPS_SIM=_ABIO64");                         \
+         break;                                                        \
+       }                                                               \
+                                                                       \
+      builtin_define_with_int_value ("_MIPS_SZINT", INT_TYPE_SIZE);    \
+      builtin_define_with_int_value ("_MIPS_SZLONG", LONG_TYPE_SIZE);  \
+      builtin_define_with_int_value ("_MIPS_SZPTR", POINTER_SIZE);     \
+      builtin_define_with_int_value ("_MIPS_FPSET",                    \
+                                    32 / MAX_FPRS_PER_FMT);            \
+                                                                       \
+      /* These defines reflect the ABI in use, not whether the         \
+        FPU is directly accessible.  */                                \
+      if (TARGET_HARD_FLOAT_ABI)                                       \
+       builtin_define ("__mips_hard_float");                           \
+      else                                                             \
+       builtin_define ("__mips_soft_float");                           \
+                                                                       \
+      if (TARGET_SINGLE_FLOAT)                                         \
+       builtin_define ("__mips_single_float");                         \
+                                                                       \
+      if (TARGET_PAIRED_SINGLE_FLOAT)                                  \
+       builtin_define ("__mips_paired_single_float");                  \
+                                                                       \
+      if (TARGET_BIG_ENDIAN)                                           \
+       {                                                               \
+         builtin_define_std ("MIPSEB");                                \
+         builtin_define ("_MIPSEB");                                   \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         builtin_define_std ("MIPSEL");                                \
+         builtin_define ("_MIPSEL");                                   \
+       }                                                               \
+                                                                        \
+      /* Whether calls should go through $25.  The separate __PIC__    \
+        macro indicates whether abicalls code might use a GOT.  */     \
+      if (TARGET_ABICALLS)                                             \
+       builtin_define ("__mips_abicalls");                             \
+                                                                       \
+      /* Whether Loongson vector modes are enabled.  */                 \
+      if (TARGET_LOONGSON_VECTORS)                                     \
+        builtin_define ("__mips_loongson_vector_rev");                  \
+                                                                       \
+      /* Historical Octeon macro.  */                                  \
+      if (TARGET_OCTEON)                                               \
+       builtin_define ("__OCTEON__");                                  \
+                                                                       \
+      /* Macros dependent on the C dialect.  */                                \
+      if (preprocessing_asm_p ())                                      \
+       {                                                               \
+         builtin_define_std ("LANGUAGE_ASSEMBLY");                     \
+         builtin_define ("_LANGUAGE_ASSEMBLY");                        \
+       }                                                               \
+      else if (c_dialect_cxx ())                                       \
+       {                                                               \
+         builtin_define ("_LANGUAGE_C_PLUS_PLUS");                     \
+         builtin_define ("__LANGUAGE_C_PLUS_PLUS");                    \
+         builtin_define ("__LANGUAGE_C_PLUS_PLUS__");                  \
+       }                                                               \
+      else                                                             \
+       {                                                               \
+         builtin_define_std ("LANGUAGE_C");                            \
+         builtin_define ("_LANGUAGE_C");                               \
+       }                                                               \
+      if (c_dialect_objc ())                                           \
+       {                                                               \
+         builtin_define ("_LANGUAGE_OBJECTIVE_C");                     \
+         builtin_define ("__LANGUAGE_OBJECTIVE_C");                    \
+         /* Bizarre, but needed at least for Irix.  */                 \
+         builtin_define_std ("LANGUAGE_C");                            \
+         builtin_define ("_LANGUAGE_C");                               \
+       }                                                               \
+                                                                       \
+      if (mips_abi == ABI_EABI)                                                \
+       builtin_define ("__mips_eabi");                                 \
+                                                                       \
+      if (TARGET_CACHE_BUILTIN)                                                \
+       builtin_define ("__GCC_HAVE_BUILTIN_MIPS_CACHE");               \
+    }                                                                  \
+  while (0)
 
 /* Default target_flags if no switches are specified  */
 
@@ -508,6 +611,17 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #endif
 #endif /* IN_LIBGCC2 */
 
+/* Force the call stack unwinders in unwind.inc not to be MIPS16 code
+   when compiled with hardware floating point.  This is because MIPS16
+   code cannot save and restore the floating-point registers, which is
+   important if in a mixed MIPS16/non-MIPS16 environment.  */
+
+#ifdef IN_LIBGCC2
+#if __mips_hard_float
+#define LIBGCC2_UNWIND_ATTRIBUTE __attribute__((__nomips16__))
+#endif
+#endif /* IN_LIBGCC2 */
+
 #define TARGET_LIBGCC_SDATA_SECTION ".sdata"
 
 #ifndef MULTILIB_ENDIAN_DEFAULT
@@ -540,7 +654,11 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #              if MIPS_ISA_DEFAULT == 64
 #                define MULTILIB_ISA_DEFAULT "mips64"
 #              else
-#                define MULTILIB_ISA_DEFAULT "mips1"
+#               if MIPS_ISA_DEFAULT == 65
+#                 define MULTILIB_ISA_DEFAULT "mips64r2"
+#               else
+#                  define MULTILIB_ISA_DEFAULT "mips1"
+#               endif
 #              endif
 #            endif
 #          endif
@@ -578,18 +696,38 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define MIPS_ARCH_OPTION_SPEC \
   MIPS_ISA_LEVEL_OPTION_SPEC "|march=*"
 
-/* A spec that infers a -mips argument from an -march argument.  */
+/* A spec that infers a -mips argument from an -march argument,
+   or injects the default if no architecture is specified.  */
 
 #define MIPS_ISA_LEVEL_SPEC \
   "%{" MIPS_ISA_LEVEL_OPTION_SPEC ":;: \
      %{march=mips1|march=r2000|march=r3000|march=r3900:-mips1} \
      %{march=mips2|march=r6000:-mips2} \
-     %{march=mips3|march=r4*|march=vr4*|march=orion:-mips3} \
-     %{march=mips4|march=r8000|march=vr5*|march=rm7000|march=rm9000:-mips4} \
-     %{march=mips32|march=4kc|march=4km|march=4kp:-mips32} \
-     %{march=mips32r2|march=m4k|march=4ke*|march=24k* \
+     %{march=mips3|march=r4*|march=vr4*|march=orion|march=loongson2*:-mips3} \
+     %{march=mips4|march=r8000|march=vr5*|march=rm7000|march=rm9000 \
+       |march=r10000|march=r12000|march=r14000|march=r16000:-mips4} \
+     %{march=mips32|march=4kc|march=4km|march=4kp|march=4ksc:-mips32} \
+     %{march=mips32r2|march=m4k|march=4ke*|march=4ksd|march=24k* \
        |march=34k*|march=74k*: -mips32r2} \
-     %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000: -mips64}}"
+     %{march=mips64|march=5k*|march=20k*|march=sb1*|march=sr71000: -mips64} \
+     %{march=mips64r2|march=octeon: -mips64r2} \
+     %{!march=*: -" MULTILIB_ISA_DEFAULT "}}"
+
+/* A spec that infers a -mhard-float or -msoft-float setting from an
+   -march argument.  Note that soft-float and hard-float code are not
+   link-compatible.  */
+
+#define MIPS_ARCH_FLOAT_SPEC \
+  "%{mhard-float|msoft-float|march=mips*:; \
+     march=vr41*|march=m4k|march=4k*|march=24kc|march=24kec \
+     |march=34kc|march=74kc|march=5kc|march=octeon: -msoft-float; \
+     march=*: -mhard-float}"
+
+/* A spec condition that matches 32-bit options.  It only works if
+   MIPS_ISA_LEVEL_SPEC has been applied.  */
+
+#define MIPS_32BIT_OPTION_SPEC \
+  "mips1|mips2|mips32*|mgp32"
 
 /* Support for a compile-time default CPU, et cetera.  The rules are:
    --with-arch is ignored if -march is specified or a -mips is specified
@@ -605,15 +743,21 @@ extern const struct mips_rtx_cost_data *mips_cost;
   {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
   {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
   {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
-  {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }
+  {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
+  {"llsc", "%{!mllsc:%{!mno-llsc:-m%(VALUE)}}" }, \
+  {"mips-plt", "%{!mplt:%{!mno-plt:-m%(VALUE)}}" }
+
 
+/* A spec that infers the -mdsp setting from an -march argument.  */
+#define BASE_DRIVER_SELF_SPECS \
+  "%{!mno-dsp:%{march=24ke*|march=34k*|march=74k*: -mdsp}}"
+
+#define DRIVER_SELF_SPECS BASE_DRIVER_SELF_SPECS
 
 #define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
                                && ISA_HAS_COND_TRAP)
 
-#define GENERATE_BRANCHLIKELY   (TARGET_BRANCHLIKELY                    \
-                                && !TARGET_SR71K                       \
-                                && !TARGET_MIPS16)
+#define GENERATE_BRANCHLIKELY   (TARGET_BRANCHLIKELY && !TARGET_MIPS16)
 
 /* True if the ABI can only work with 64-bit integer registers.  We
    generally allow ad-hoc variations for TARGET_SINGLE_FLOAT, but
@@ -623,14 +767,21 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* Likewise for 32-bit regs.  */
 #define ABI_NEEDS_32BIT_REGS   (mips_abi == ABI_32)
 
-/* True if symbols are 64 bits wide.  At present, n64 is the only
-   ABI for which this is true.  */
-#define ABI_HAS_64BIT_SYMBOLS  (mips_abi == ABI_64 && !TARGET_SYM32)
+/* True if the file format uses 64-bit symbols.  At present, this is
+   only true for n64, which uses 64-bit ELF.  */
+#define FILE_HAS_64BIT_SYMBOLS (mips_abi == ABI_64)
+
+/* True if symbols are 64 bits wide.  This is usually determined by
+   the ABI's file format, but it can be overridden by -msym32.  Note that
+   overriding the size with -msym32 changes the ABI of relocatable objects,
+   although it doesn't change the ABI of a fully-linked object.  */
+#define ABI_HAS_64BIT_SYMBOLS  (FILE_HAS_64BIT_SYMBOLS && !TARGET_SYM32)
 
 /* ISA has instructions for managing 64-bit fp and gp regs (e.g. mips3).  */
 #define ISA_HAS_64BIT_REGS     (ISA_MIPS3                              \
                                 || ISA_MIPS4                           \
-                                || ISA_MIPS64)
+                                || ISA_MIPS64                          \
+                                || ISA_MIPS64R2)
 
 /* ISA has branch likely instructions (e.g. mips2).  */
 /* Disable branchlikely for tx39 until compare rewrite.  They haven't
@@ -646,32 +797,52 @@ extern const struct mips_rtx_cost_data *mips_cost;
                                  || TARGET_MAD                         \
                                  || ISA_MIPS32                         \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
-/* ISA has the conditional move instructions introduced in mips4.  */
-#define ISA_HAS_CONDMOVE       ((ISA_MIPS4                             \
+/* ISA has a three-operand multiplication instruction.  */
+#define ISA_HAS_DMUL3          (TARGET_64BIT                           \
+                                && TARGET_OCTEON                       \
+                                && !TARGET_MIPS16)
+
+/* ISA has the floating-point conditional move instructions introduced
+   in mips4.  */
+#define ISA_HAS_FP_CONDMOVE    ((ISA_MIPS4                             \
                                  || ISA_MIPS32                         \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS5500                    \
                                 && !TARGET_MIPS16)
 
+/* ISA has the integer conditional move instructions introduced in mips4 and
+   ST Loongson 2E/2F.  */
+#define ISA_HAS_CONDMOVE        (ISA_HAS_FP_CONDMOVE || TARGET_LOONGSON_2EF)
+
+/* ISA has LDC1 and SDC1.  */
+#define ISA_HAS_LDC1_SDC1      (!ISA_MIPS1 && !TARGET_MIPS16)
+
 /* ISA has the mips4 FP condition code instructions: FP-compare to CC,
    branch on CC, and move (both FP and non-FP) on CC.  */
 #define ISA_HAS_8CC            (ISA_MIPS4                              \
                                 || ISA_MIPS32                          \
                                 || ISA_MIPS32R2                        \
-                                || ISA_MIPS64)
+                                || ISA_MIPS64                          \
+                                || ISA_MIPS64R2)
 
 /* This is a catch all for other mips4 instructions: indexed load, the
    FP madd and msub instructions, and the FP recip and recip sqrt
    instructions.  */
 #define ISA_HAS_FP4            ((ISA_MIPS4                             \
                                  || (ISA_MIPS32R2 && TARGET_FLOAT64)   \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
+/* ISA has paired-single instructions.  */
+#define ISA_HAS_PAIRED_SINGLE  (ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2)
+
 /* ISA has conditional trap instructions.  */
 #define ISA_HAS_COND_TRAP      (!ISA_MIPS1                             \
                                 && !TARGET_MIPS16)
@@ -679,22 +850,39 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* ISA has integer multiply-accumulate instructions, madd and msub.  */
 #define ISA_HAS_MADD_MSUB      ((ISA_MIPS32                            \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
 /* Integer multiply-accumulate instructions should be generated.  */
 #define GENERATE_MADD_MSUB      (ISA_HAS_MADD_MSUB && !TUNE_74K)
 
-/* ISA has floating-point nmadd and nmsub instructions.  */
-#define ISA_HAS_NMADD_NMSUB    ((ISA_MIPS4                             \
-                                 || ISA_MIPS64)                        \
+/* ISA has floating-point madd and msub instructions 'd = a * b [+-] c'.  */
+#define ISA_HAS_FP_MADD4_MSUB4  ISA_HAS_FP4
+
+/* ISA has floating-point madd and msub instructions 'c = a * b [+-] c'.  */
+#define ISA_HAS_FP_MADD3_MSUB3  TARGET_LOONGSON_2EF
+
+/* ISA has floating-point nmadd and nmsub instructions
+   'd = -((a * b) [+-] c)'.  */
+#define ISA_HAS_NMADD4_NMSUB4(MODE)                                    \
+                               ((ISA_MIPS4                             \
+                                 || (ISA_MIPS32R2 && (MODE) == V2SFmode) \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && (!TARGET_MIPS5400 || TARGET_MAD)    \
                                 && !TARGET_MIPS16)
 
+/* ISA has floating-point nmadd and nmsub instructions
+   'c = -((a * b) [+-] c)'.  */
+#define ISA_HAS_NMADD3_NMSUB3(MODE)                                    \
+                                TARGET_LOONGSON_2EF
+
 /* ISA has count leading zeroes/ones instruction (not implemented).  */
 #define ISA_HAS_CLZ_CLO                ((ISA_MIPS32                            \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
 /* ISA has three operand multiply instructions that put
@@ -734,6 +922,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 
 /* ISA has the "ror" (rotate right) instructions.  */
 #define ISA_HAS_ROR            ((ISA_MIPS32R2                          \
+                                 || ISA_MIPS64R2                       \
                                  || TARGET_MIPS5400                    \
                                  || TARGET_MIPS5500                    \
                                  || TARGET_SR71K                       \
@@ -742,9 +931,11 @@ extern const struct mips_rtx_cost_data *mips_cost;
 
 /* ISA has data prefetch instructions.  This controls use of 'pref'.  */
 #define ISA_HAS_PREFETCH       ((ISA_MIPS4                             \
+                                 || TARGET_LOONGSON_2EF                \
                                  || ISA_MIPS32                         \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
 /* ISA has data indexed prefetch instructions.  This controls use of
@@ -753,7 +944,8 @@ extern const struct mips_rtx_cost_data *mips_cost;
    enabled.)  */
 #define ISA_HAS_PREFETCHX      ((ISA_MIPS4                             \
                                  || ISA_MIPS32R2                       \
-                                 || ISA_MIPS64)                        \
+                                 || ISA_MIPS64                         \
+                                 || ISA_MIPS64R2)                      \
                                 && !TARGET_MIPS16)
 
 /* True if trunc.w.s and trunc.w.d are real (not synthetic)
@@ -762,19 +954,29 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define ISA_HAS_TRUNC_W                (!ISA_MIPS1)
 
 /* ISA includes the MIPS32r2 seb and seh instructions.  */
-#define ISA_HAS_SEB_SEH                (ISA_MIPS32R2                           \
+#define ISA_HAS_SEB_SEH                ((ISA_MIPS32R2          \
+                                 || ISA_MIPS64R2)      \
                                 && !TARGET_MIPS16)
 
 /* ISA includes the MIPS32/64 rev 2 ext and ins instructions.  */
-#define ISA_HAS_EXT_INS                (ISA_MIPS32R2                           \
+#define ISA_HAS_EXT_INS                ((ISA_MIPS32R2          \
+                                 || ISA_MIPS64R2)      \
                                 && !TARGET_MIPS16)
 
 /* ISA has instructions for accessing top part of 64-bit fp regs.  */
-#define ISA_HAS_MXHC1          (TARGET_FLOAT64 && ISA_MIPS32R2)
+#define ISA_HAS_MXHC1          (TARGET_FLOAT64         \
+                                && (ISA_MIPS32R2       \
+                                    || ISA_MIPS64R2))
 
 /* ISA has lwxs instruction (load w/scaled index address.  */
 #define ISA_HAS_LWXS           (TARGET_SMARTMIPS && !TARGET_MIPS16)
 
+/* The DSP ASE is available.  */
+#define ISA_HAS_DSP            (TARGET_DSP && !TARGET_MIPS16)
+
+/* Revision 2 of the DSP ASE is available.  */
+#define ISA_HAS_DSPR2          (TARGET_DSPR2 && !TARGET_MIPS16)
+
 /* True if the result of a load is not available to the next instruction.
    A nop will then be needed between instructions like "lw $4,..."
    and "addiu $4,$4,1".  */
@@ -783,10 +985,12 @@ extern const struct mips_rtx_cost_data *mips_cost;
                                 && !TARGET_MIPS16)
 
 /* Likewise mtc1 and mfc1.  */
-#define ISA_HAS_XFER_DELAY     (mips_isa <= 3)
+#define ISA_HAS_XFER_DELAY     (mips_isa <= 3                  \
+                                && !TARGET_LOONGSON_2EF)
 
 /* Likewise floating-point comparisons.  */
-#define ISA_HAS_FCMP_DELAY     (mips_isa <= 3)
+#define ISA_HAS_FCMP_DELAY     (mips_isa <= 3                  \
+                                && !TARGET_LOONGSON_2EF)
 
 /* True if mflo and mfhi can be immediately followed by instructions
    which write to the HI and LO registers.
@@ -803,7 +1007,54 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define ISA_HAS_HILO_INTERLOCKS        (ISA_MIPS32                             \
                                 || ISA_MIPS32R2                        \
                                 || ISA_MIPS64                          \
-                                || TARGET_MIPS5500)
+                                || ISA_MIPS64R2                        \
+                                || TARGET_MIPS5500                     \
+                                || TARGET_LOONGSON_2EF)
+
+/* ISA includes synci, jr.hb and jalr.hb.  */
+#define ISA_HAS_SYNCI ((ISA_MIPS32R2           \
+                       || ISA_MIPS64R2)        \
+                      && !TARGET_MIPS16)
+
+/* ISA includes sync.  */
+#define ISA_HAS_SYNC ((mips_isa >= 2 || TARGET_MIPS3900) && !TARGET_MIPS16)
+#define GENERATE_SYNC                  \
+  (target_flags_explicit & MASK_LLSC   \
+   ? TARGET_LLSC && !TARGET_MIPS16     \
+   : ISA_HAS_SYNC)
+
+/* ISA includes ll and sc.  Note that this implies ISA_HAS_SYNC
+   because the expanders use both ISA_HAS_SYNC and ISA_HAS_LL_SC
+   instructions.  */
+#define ISA_HAS_LL_SC (mips_isa >= 2 && !TARGET_MIPS16)
+#define GENERATE_LL_SC                 \
+  (target_flags_explicit & MASK_LLSC   \
+   ? TARGET_LLSC && !TARGET_MIPS16     \
+   : ISA_HAS_LL_SC)
+
+/* ISA includes the baddu instruction.  */
+#define ISA_HAS_BADDU          (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* ISA includes the bbit* instructions.  */
+#define ISA_HAS_BBIT           (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* ISA includes the cins instruction.  */
+#define ISA_HAS_CINS           (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* ISA includes the exts instruction.  */
+#define ISA_HAS_EXTS           (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* ISA includes the seq and sne instructions.  */
+#define ISA_HAS_SEQ_SNE                (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* ISA includes the pop instruction.  */
+#define ISA_HAS_POP            (TARGET_OCTEON && !TARGET_MIPS16)
+
+/* The CACHE instruction is available in non-MIPS16 code.  */
+#define TARGET_CACHE_BUILTIN (mips_isa >= 3)
+
+/* The CACHE instruction is available.  */
+#define ISA_HAS_CACHE (TARGET_CACHE_BUILTIN && !TARGET_MIPS16)
 \f
 /* Add -G xx support.  */
 
@@ -811,7 +1062,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define SWITCH_TAKES_ARG(CHAR)                                         \
   (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
 
-#define OVERRIDE_OPTIONS override_options ()
+#define OVERRIDE_OPTIONS mips_override_options ()
 
 #define CONDITIONAL_REGISTER_USAGE mips_conditional_register_usage ()
 
@@ -884,7 +1135,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #undef ASM_SPEC
 #define ASM_SPEC "\
 %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
-%{mips32} %{mips32r2} %{mips64} \
+%{mips32*} %{mips64*} \
 %{mips16} %{mno-mips16:-no-mips16} \
 %{mips3d} %{mno-mips3d:-no-mips3d} \
 %{mdmx} %{mno-mdmx:-no-mdmx} \
@@ -895,7 +1146,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 %{mfix-vr4120} %{mfix-vr4130} \
 %(subtarget_asm_optimizing_spec) \
 %(subtarget_asm_debugging_spec) \
-%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
+%{mabi=*} %{!mabi=*: %(asm_abi_default_spec)} \
 %{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
 %{mfp32} %{mfp64} \
 %{mshared} %{mno-shared} \
@@ -910,7 +1161,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #ifndef LINK_SPEC
 #define LINK_SPEC "\
 %(endian_spec) \
-%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \
+%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32*} %{mips64*} \
 %{bestGnum} %{shared} %{non_shared}"
 #endif  /* LINK_SPEC defined */
 
@@ -967,14 +1218,20 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #endif
 \f
 #define DBX_DEBUGGING_INFO 1           /* generate stabs (OSF/rose) */
-#define MIPS_DEBUGGING_INFO 1          /* MIPS specific debugging info */
 #define DWARF2_DEBUGGING_INFO 1         /* dwarf2 debugging info */
 
 #ifndef PREFERRED_DEBUGGING_TYPE
 #define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
 #endif
 
-#define DWARF2_ADDR_SIZE (ABI_HAS_64BIT_SYMBOLS ? 8 : 4)
+/* The size of DWARF addresses should be the same as the size of symbols
+   in the target file format.  They shouldn't depend on things like -msym32,
+   because many DWARF consumers do not allow the mixture of address sizes
+   that one would then get from linking -msym32 code with -msym64 code.
+
+   Note that the default POINTER_SIZE test is not appropriate for MIPS.
+   EABI64 has 64-bit pointers but uses 32-bit ELF.  */
+#define DWARF2_ADDR_SIZE (FILE_HAS_64BIT_SYMBOLS ? 8 : 4)
 
 /* By default, turn on GDB extensions.  */
 #define DEFAULT_GDB_EXTENSIONS 1
@@ -1000,18 +1257,14 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define DBX_CONTIN_LENGTH 1500
 
 /* How to renumber registers for dbx and gdb.  */
-#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ]
+#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[REGNO]
 
 /* The mapping from gcc register number to DWARF 2 CFA column number.  */
-#define DWARF_FRAME_REGNUM(REG)        (REG)
+#define DWARF_FRAME_REGNUM(REGNO) mips_dwarf_regno[REGNO]
 
 /* The DWARF 2 CFA column which tracks the return address.  */
 #define DWARF_FRAME_RETURN_COLUMN (GP_REG_FIRST + 31)
 
-/* The DWARF 2 CFA column which tracks the return address from a
-   signal handler context.  */
-#define SIGNAL_UNWIND_RETURN_COLUMN (FP_REG_LAST + 1)
-
 /* Before the prologue, RA lives in r31.  */
 #define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
 
@@ -1070,7 +1323,8 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* The number of consecutive floating-point registers needed to store the
    smallest format supported by the FPU.  */
 #define MIN_FPRS_PER_FMT \
-  (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 ? 1 : MAX_FPRS_PER_FMT) 
+  (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2 \
+   ? 1 : MAX_FPRS_PER_FMT)
 
 /* The largest size of value that can be held in floating-point
    registers and moved with a single instruction.  */
@@ -1087,7 +1341,8 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* The number of bytes in a double.  */
 #define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
 
-#define UNITS_PER_SIMD_WORD (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD)
+#define UNITS_PER_SIMD_WORD(MODE) \
+  (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD)
 
 /* Set the sizes of the core types.  */
 #define SHORT_TYPE_SIZE 16
@@ -1099,6 +1354,19 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define DOUBLE_TYPE_SIZE 64
 #define LONG_DOUBLE_TYPE_SIZE (TARGET_NEWABI ? 128 : 64)
 
+/* Define the sizes of fixed-point types.  */
+#define SHORT_FRACT_TYPE_SIZE 8
+#define FRACT_TYPE_SIZE 16
+#define LONG_FRACT_TYPE_SIZE 32
+#define LONG_LONG_FRACT_TYPE_SIZE 64
+
+#define SHORT_ACCUM_TYPE_SIZE 16
+#define ACCUM_TYPE_SIZE 32
+#define LONG_ACCUM_TYPE_SIZE 64
+/* FIXME.  LONG_LONG_ACCUM_TYPE_SIZE should be 128 bits, but GCC
+   doesn't support 128-bit integers for MIPS32 currently.  */
+#define LONG_LONG_ACCUM_TYPE_SIZE (TARGET_64BIT ? 128 : 64)
+
 /* long double is not a fixed mode, but the idea is that, if we
    support long double, we also want a 128-bit integer type.  */
 #define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
@@ -1193,7 +1461,13 @@ extern const struct mips_rtx_cost_data *mips_cost;
        || TREE_CODE (TYPE) == UNION_TYPE                               \
        || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
 
-
+/* We need this for the same reason as DATA_ALIGNMENT, namely to cause
+   character arrays to be word-aligned so that `strcpy' calls that copy
+   constants to character arrays can be done inline, and 'strcmp' can be
+   optimised to use word loads. */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
+  DATA_ALIGNMENT (TYPE, ALIGN)
+  
 #define PAD_VARARGS_DOWN \
   (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
 
@@ -1222,13 +1496,17 @@ extern const struct mips_rtx_cost_data *mips_cost;
       (MODE) = Pmode;                           \
     }
 
+/* Pmode is always the same as ptr_mode, but not always the same as word_mode.
+   Extensions of pointers to word_mode must be signed.  */
+#define POINTERS_EXTEND_UNSIGNED false
+
 /* Define if loading short immediate values into registers sign extends.  */
 #define SHORT_IMMEDIATES_SIGN_EXTEND
 
 /* The [d]clz instructions have the natural values at 0.  */
 
 #define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
-  ((VALUE) = GET_MODE_BITSIZE (MODE), true)
+  ((VALUE) = GET_MODE_BITSIZE (MODE), 2)
 \f
 /* Standard register usage.  */
 
@@ -1242,7 +1520,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
    - 3 fake registers:
        - ARG_POINTER_REGNUM
        - FRAME_POINTER_REGNUM
-       - FAKE_CALL_REGNO (see the comment above load_callsi for details)
+       - GOT_VERSION_REGNUM (see the comment above load_call<mode> for details)
    - 3 dummy entries that were used at various times in the past.
    - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
    - 6 DSP control registers  */
@@ -1255,7 +1533,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
 
    Regarding coprocessor registers: without evidence to the contrary,
    it's best to assume that each coprocessor register has a unique
-   use.  This can be overridden, in, e.g., override_options() or
+   use.  This can be overridden, in, e.g., mips_override_options or
    CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate
    for a particular target.  */
 
@@ -1322,7 +1600,7 @@ extern const struct mips_rtx_cost_data *mips_cost;
   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,                      \
   1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                      \
   /* Others.  */                                                        \
-  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, 0,                      \
   /* COP0 registers */                                                 \
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                      \
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,                      \
@@ -1344,6 +1622,9 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define GP_REG_LAST  31
 #define GP_REG_NUM   (GP_REG_LAST - GP_REG_FIRST + 1)
 #define GP_DBX_FIRST 0
+#define K0_REG_NUM   (GP_REG_FIRST + 26)
+#define K1_REG_NUM   (GP_REG_FIRST + 27)
+#define KERNEL_REG_P(REGNO)    (IN_RANGE (REGNO, K0_REG_NUM, K1_REG_NUM))
 
 #define FP_REG_FIRST 32
 #define FP_REG_LAST  63
@@ -1355,6 +1636,12 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define MD_REG_NUM   (MD_REG_LAST - MD_REG_FIRST + 1)
 #define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM)
 
+/* The DWARF 2 CFA column which tracks the return address from a
+   signal handler context.  This means that to maintain backwards
+   compatibility, no hard register can be assigned this column if it
+   would need to be handled by the DWARF unwinder.  */
+#define DWARF_ALT_FRAME_RETURN_COLUMN 66
+
 #define ST_REG_FIRST 67
 #define ST_REG_LAST  74
 #define ST_REG_NUM   (ST_REG_LAST - ST_REG_FIRST + 1)
@@ -1365,6 +1652,10 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define COP0_REG_LAST 111
 #define COP0_REG_NUM (COP0_REG_LAST - COP0_REG_FIRST + 1)
 
+#define COP0_STATUS_REG_NUM    (COP0_REG_FIRST + 12)
+#define COP0_CAUSE_REG_NUM     (COP0_REG_FIRST + 13)
+#define COP0_EPC_REG_NUM       (COP0_REG_FIRST + 14)
+
 #define COP2_REG_FIRST 112
 #define COP2_REG_LAST 143
 #define COP2_REG_NUM (COP2_REG_LAST - COP2_REG_FIRST + 1)
@@ -1380,14 +1671,19 @@ extern const struct mips_rtx_cost_data *mips_cost;
 #define DSP_ACC_REG_NUM (DSP_ACC_REG_LAST - DSP_ACC_REG_FIRST + 1)
 
 #define AT_REGNUM      (GP_REG_FIRST + 1)
-#define HI_REGNUM      (MD_REG_FIRST + 0)
-#define LO_REGNUM      (MD_REG_FIRST + 1)
-#define AC1HI_REGNUM   (DSP_ACC_REG_FIRST + 0)
-#define AC1LO_REGNUM   (DSP_ACC_REG_FIRST + 1)
-#define AC2HI_REGNUM   (DSP_ACC_REG_FIRST + 2)
-#define AC2LO_REGNUM   (DSP_ACC_REG_FIRST + 3)
-#define AC3HI_REGNUM   (DSP_ACC_REG_FIRST + 4)
-#define AC3LO_REGNUM   (DSP_ACC_REG_FIRST + 5)
+#define HI_REGNUM      (TARGET_BIG_ENDIAN ? MD_REG_FIRST : MD_REG_FIRST + 1)
+#define LO_REGNUM      (TARGET_BIG_ENDIAN ? MD_REG_FIRST + 1 : MD_REG_FIRST)
+
+/* A few bitfield locations for the coprocessor registers.  */
+/* Request Interrupt Priority Level is from bit 10 to bit 15 of
+   the cause register for the EIC interrupt mode.  */
+#define CAUSE_IPL      10
+/* Interrupt Priority Level is from bit 10 to bit 15 of the status register.  */
+#define SR_IPL         10
+/* Exception Level is at bit 1 of the status register.  */
+#define SR_EXL         1
+/* Interrupt Enable is at bit 0 of the status register.  */
+#define SR_IE          0
 
 /* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC.
    If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG
@@ -1418,10 +1714,6 @@ extern const struct mips_rtx_cost_data *mips_cost;
 /* Test if REGNO is hi, lo, or one of the 6 new DSP accumulators.  */
 #define ACC_REG_P(REGNO) \
   (MD_REG_P (REGNO) || DSP_ACC_REG_P (REGNO))
-/* Test if REGNO is HI or the first register of 3 new DSP accumulator pairs.  */
-#define ACC_HI_REG_P(REGNO) \
-  ((REGNO) == HI_REGNUM || (REGNO) == AC1HI_REGNUM || (REGNO) == AC2HI_REGNUM \
-   || (REGNO) == AC3HI_REGNUM)
 
 #define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
 
@@ -1441,25 +1733,10 @@ extern const struct mips_rtx_cost_data *mips_cost;
 
 #define HARD_REGNO_NREGS(REGNO, MODE) mips_hard_regno_nregs (REGNO, MODE)
 
-/* To make the code simpler, HARD_REGNO_MODE_OK just references an
-   array built in override_options.  Because machmodes.h is not yet
-   included before this file is processed, the MODE bound can't be
-   expressed here.  */
-
-extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
-
 #define HARD_REGNO_MODE_OK(REGNO, MODE)                                        \
   mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ]
 
-/* Value is 1 if it is a good idea to tie two pseudo registers
-   when one has mode MODE1 and one has mode MODE2.
-   If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
-   for any hard reg, then this must be 0 for correct output.  */
-#define MODES_TIEABLE_P(MODE1, MODE2)                                  \
-  ((GET_MODE_CLASS (MODE1) == MODE_FLOAT ||                            \
-    GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT)                      \
-   == (GET_MODE_CLASS (MODE2) == MODE_FLOAT ||                         \
-       GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
+#define MODES_TIEABLE_P mips_modes_tieable_p
 
 /* Register to use for pushing function arguments.  */
 #define STACK_POINTER_REGNUM (GP_REG_FIRST + 29)
@@ -1474,25 +1751,41 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 #define HARD_FRAME_POINTER_REGNUM \
   (TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30)
 
-/* Value should be nonzero if functions must have frame pointers.
-   Zero means the frame pointer need not be set up (and parms
-   may be accessed via the stack pointer) in functions that seem suitable.
-   This is computed in `reload', in reload1.c.  */
-#define FRAME_POINTER_REQUIRED (current_function_calls_alloca)
+#define FRAME_POINTER_REQUIRED (mips_frame_pointer_required ())
 
 /* Register in which static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2)
+#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 15)
+
+/* Registers used as temporaries in prologue/epilogue code:
+
+   - If a MIPS16 PIC function needs access to _gp, it first loads
+     the value into MIPS16_PIC_TEMP and then copies it to $gp.
+
+   - The prologue can use MIPS_PROLOGUE_TEMP as a general temporary
+     register.  The register must not conflict with MIPS16_PIC_TEMP.
+
+   - The epilogue can use MIPS_EPILOGUE_TEMP as a general temporary
+     register.
 
-/* Registers used as temporaries in prologue/epilogue code.  If we're
-   generating mips16 code, these registers must come from the core set
-   of 8.  The prologue register mustn't conflict with any incoming
-   arguments, the static chain pointer, or the frame pointer.  The
-   epilogue temporary mustn't conflict with the return registers, the
-   frame pointer, the EH stack adjustment, or the EH data registers.  */
+   If we're generating MIPS16 code, these registers must come from the
+   core set of 8.  The prologue registers mustn't conflict with any
+   incoming arguments, the static chain pointer, or the frame pointer.
+   The epilogue temporary mustn't conflict with the return registers,
+   the PIC call register ($25), the frame pointer, the EH stack adjustment,
+   or the EH data registers.
 
-#define MIPS_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 3)
-#define MIPS_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8))
+   If we're generating interrupt handlers, we use K0 as a temporary register
+   in prologue/epilogue code.  */
 
+#define MIPS16_PIC_TEMP_REGNUM (GP_REG_FIRST + 2)
+#define MIPS_PROLOGUE_TEMP_REGNUM \
+  (cfun->machine->interrupt_handler_p ? K0_REG_NUM : GP_REG_FIRST + 3)
+#define MIPS_EPILOGUE_TEMP_REGNUM              \
+  (cfun->machine->interrupt_handler_p          \
+   ? K0_REG_NUM                                        \
+   : GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8))
+
+#define MIPS16_PIC_TEMP gen_rtx_REG (Pmode, MIPS16_PIC_TEMP_REGNUM)
 #define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM)
 #define MIPS_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_EPILOGUE_TEMP_REGNUM)
 
@@ -1540,7 +1833,6 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 enum reg_class
 {
   NO_REGS,                     /* no registers in set */
-  M16_NA_REGS,                 /* mips16 regs not used to pass args */
   M16_REGS,                    /* mips16 directly accessible registers */
   T_REG,                       /* mips16 T register ($24) */
   M16_T_REGS,                  /* mips16 registers plus T register */
@@ -1549,23 +1841,20 @@ enum reg_class
   LEA_REGS,                    /* Every GPR except $25 */
   GR_REGS,                     /* integer registers */
   FP_REGS,                     /* floating point registers */
-  HI_REG,                      /* hi register */
-  LO_REG,                      /* lo register */
+  MD0_REG,                     /* first multiply/divide register */
+  MD1_REG,                     /* second multiply/divide register */
   MD_REGS,                     /* multiply/divide registers (hi/lo) */
   COP0_REGS,                   /* generic coprocessor classes */
   COP2_REGS,
   COP3_REGS,
-  HI_AND_GR_REGS,              /* union classes */
-  LO_AND_GR_REGS,
-  HI_AND_FP_REGS,
-  COP0_AND_GR_REGS,
-  COP2_AND_GR_REGS,
-  COP3_AND_GR_REGS,
-  ALL_COP_REGS,
-  ALL_COP_AND_GR_REGS,
   ST_REGS,                     /* status registers (fp status) */
   DSP_ACC_REGS,                        /* DSP accumulator registers */
   ACC_REGS,                    /* Hi/Lo and DSP accumulator registers */
+  FRAME_REGS,                  /* $arg and $frame */
+  GR_AND_MD0_REGS,             /* union classes */
+  GR_AND_MD1_REGS,
+  GR_AND_MD_REGS,
+  GR_AND_ACC_REGS,
   ALL_REGS,                    /* all registers */
   LIM_REG_CLASSES              /* max value + 1 */
 };
@@ -1581,7 +1870,6 @@ enum reg_class
 #define REG_CLASS_NAMES                                                        \
 {                                                                      \
   "NO_REGS",                                                           \
-  "M16_NA_REGS",                                                       \
   "M16_REGS",                                                          \
   "T_REG",                                                             \
   "M16_T_REGS",                                                                \
@@ -1590,24 +1878,21 @@ enum reg_class
   "LEA_REGS",                                                          \
   "GR_REGS",                                                           \
   "FP_REGS",                                                           \
-  "HI_REG",                                                            \
-  "LO_REG",                                                            \
+  "MD0_REG",                                                           \
+  "MD1_REG",                                                           \
   "MD_REGS",                                                           \
   /* coprocessor registers */                                          \
   "COP0_REGS",                                                         \
   "COP2_REGS",                                                         \
   "COP3_REGS",                                                         \
-  "HI_AND_GR_REGS",                                                    \
-  "LO_AND_GR_REGS",                                                    \
-  "HI_AND_FP_REGS",                                                    \
-  "COP0_AND_GR_REGS",                                                  \
-  "COP2_AND_GR_REGS",                                                  \
-  "COP3_AND_GR_REGS",                                                  \
-  "ALL_COP_REGS",                                                      \
-  "ALL_COP_AND_GR_REGS",                                               \
   "ST_REGS",                                                           \
   "DSP_ACC_REGS",                                                      \
   "ACC_REGS",                                                          \
+  "FRAME_REGS",                                                                \
+  "GR_AND_MD0_REGS",                                                   \
+  "GR_AND_MD1_REGS",                                                   \
+  "GR_AND_MD_REGS",                                                    \
+  "GR_AND_ACC_REGS",                                                   \
   "ALL_REGS"                                                           \
 }
 
@@ -1624,34 +1909,30 @@ enum reg_class
 
 #define REG_CLASS_CONTENTS                                                                             \
 {                                                                                                      \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* no registers */      \
-  { 0x0003000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* mips16 nonarg regs */\
-  { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* mips16 registers */  \
-  { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* mips16 T register */ \
-  { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* mips16 and T regs */ \
-  { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* SVR4 PIC function address register */ \
-  { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* only $v1 */ \
-  { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* Every other GPR except $25 */   \
-  { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* integer registers */ \
-  { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* floating registers*/ \
-  { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },  /* hi register */       \
-  { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },  /* lo register */       \
-  { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 },  /* mul/div registers */ \
-  { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 },   /* cop0 registers */    \
-  { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 },   /* cop2 registers */    \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff },   /* cop3 registers */    \
-  { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },  /* union classes */     \
-  { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },                          \
-  { 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },                          \
-  { 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 },                          \
-  { 0xffffffff, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 },                          \
-  { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff },                           \
-  { 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff },                           \
-  { 0xffffffff, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff },                           \
-  { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 },  /* status registers */  \
-  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 },  /* dsp accumulator registers */ \
-  { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 },  /* hi/lo and dsp accumulator registers */       \
-  { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0fffffff }   /* all registers */     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* NO_REGS */           \
+  { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* M16_REGS */          \
+  { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* T_REG */             \
+  { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* M16_T_REGS */        \
+  { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* PIC_FN_ADDR_REG */   \
+  { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* V1_REG */            \
+  { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* LEA_REGS */          \
+  { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* GR_REGS */           \
+  { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },  /* FP_REGS */           \
+  { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },  /* MD0_REG */           \
+  { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },  /* MD1_REG */           \
+  { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 },  /* MD_REGS */           \
+  { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 },   /* COP0_REGS */                \
+  { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 },   /* COP2_REGS */                \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff },   /* COP3_REGS */                \
+  { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 },  /* ST_REGS */           \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 },  /* DSP_ACC_REGS */      \
+  { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 },  /* ACC_REGS */          \
+  { 0x00000000, 0x00000000, 0x00006000, 0x00000000, 0x00000000, 0x00000000 },  /* FRAME_REGS */        \
+  { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 },  /* GR_AND_MD0_REGS */   \
+  { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 },  /* GR_AND_MD1_REGS */   \
+  { 0xffffffff, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 },  /* GR_AND_MD_REGS */    \
+  { 0xffffffff, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 },  /* GR_AND_ACC_REGS */   \
+  { 0xffffffff, 0xffffffff, 0xffff67ff, 0xffffffff, 0xffffffff, 0x0fffffff }   /* ALL_REGS */          \
 }
 
 
@@ -1660,8 +1941,6 @@ enum reg_class
    choose a class which is "minimal", meaning that no smaller class
    also contains the register.  */
 
-extern const enum reg_class mips_regno_to_class[];
-
 #define REGNO_REG_CLASS(REGNO) mips_regno_to_class[ (REGNO) ]
 
 /* A macro whose definition is the name of the class to which a
@@ -1685,35 +1964,50 @@ extern const enum reg_class mips_regno_to_class[];
 
 #define SMALL_REGISTER_CLASSES (TARGET_MIPS16)
 
-/* This macro is used later on in the file.  */
-#define GR_REG_CLASS_P(CLASS)                                          \
-  ((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG       \
-   || (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS                  \
-   || (CLASS) == V1_REG                                                        \
-   || (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS)
-
-/* This macro is also used later on in the file.  */
-#define COP_REG_CLASS_P(CLASS)                                         \
-  ((CLASS)  == COP0_REGS || (CLASS) == COP2_REGS || (CLASS) == COP3_REGS)
-
-/* REG_ALLOC_ORDER is to order in which to allocate registers.  This
-   is the default value (allocate the registers in numeric order).  We
-   define it just so that we can override it for the mips16 target in
-   ORDER_REGS_FOR_LOCAL_ALLOC.  */
+/* We generally want to put call-clobbered registers ahead of
+   call-saved ones.  (IRA expects this.)  */
 
 #define REG_ALLOC_ORDER                                                        \
-{  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,      \
-  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,      \
+{ /* Accumulator registers.  When GPRs and accumulators have equal     \
+     cost, we generally prefer to use accumulators.  For example,      \
+     a division of multiplication result is better allocated to LO,    \
+     so that we put the MFLO at the point of use instead of at the     \
+     point of definition.  It's also needed if we're to take advantage \
+     of the extra accumulators available with -mdspr2.  In some cases, \
+     it can also help to reduce register pressure.  */                 \
+  64, 65,176,177,178,179,180,181,                                      \
+  /* Call-clobbered GPRs.  */                                          \
+  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,           \
+  24, 25, 31,                                                          \
+  /* The global pointer.  This is call-clobbered for o32 and o64       \
+     abicalls, call-saved for n32 and n64 abicalls, and a program      \
+     invariant otherwise.  Putting it between the call-clobbered       \
+     and call-saved registers should cope with all eventualities.  */  \
+  28,                                                                  \
+  /* Call-saved GPRs.  */                                              \
+  16, 17, 18, 19, 20, 21, 22, 23, 30,                                  \
+  /* GPRs that can never be exposed to the register allocator.  */     \
+  0,  26, 27, 29,                                                      \
+  /* Call-clobbered FPRs.  */                                          \
   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, 63,      \
-  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,      \
+  48, 49, 50, 51,                                                      \
+  /* FPRs that are usually call-saved.  The odd ones are actually      \
+     call-clobbered for n32, but listing them ahead of the even                \
+     registers might encourage the register allocator to fragment      \
+     the available FPR pairs.  We need paired FPRs to store long       \
+     doubles, so it isn't clear that using a different order           \
+     for n32 would be a win.  */                                       \
+  52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,                      \
+  /* None of the remaining classes have defined call-saved             \
+     registers.  */                                                    \
+  66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,              \
   80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 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,127,     \
   128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,     \
   144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,     \
   160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,     \
-  176,177,178,179,180,181,182,183,184,185,186,187                      \
+  182,183,184,185,186,187                                              \
 }
 
 /* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
@@ -1765,32 +2059,14 @@ extern const enum reg_class mips_regno_to_class[];
 #define PREFERRED_RELOAD_CLASS(X,CLASS)                                        \
   mips_preferred_reload_class (X, CLASS)
 
-/* Certain machines have the property that some registers cannot be
-   copied to some other registers without using memory.  Define this
-   macro on those machines to be a C expression that is nonzero if
-   objects of mode MODE in registers of CLASS1 can only be copied to
-   registers of class CLASS2 by storing a register of CLASS1 into
-   memory and loading that memory location into a register of CLASS2.
-
-   Do not define this macro if its value would always be zero.  */
-#if 0
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE)                  \
-  ((!TARGET_DEBUG_H_MODE                                               \
-    && GET_MODE_CLASS (MODE) == MODE_INT                               \
-    && ((CLASS1 == FP_REGS && GR_REG_CLASS_P (CLASS2))                 \
-       || (GR_REG_CLASS_P (CLASS1) && CLASS2 == FP_REGS)))             \
-   || (TARGET_FLOAT64 && !TARGET_64BIT && (MODE) == DFmode             \
-       && ((GR_REG_CLASS_P (CLASS1) && CLASS2 == FP_REGS)              \
-          || (GR_REG_CLASS_P (CLASS2) && CLASS1 == FP_REGS))))
-#endif
 /* The HI and LO registers can only be reloaded via the general
    registers.  Condition code registers can only be loaded to the
    general registers, and from the floating point registers.  */
 
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)                   \
-  mips_secondary_reload_class (CLASS, MODE, X, 1)
+  mips_secondary_reload_class (CLASS, MODE, X, true)
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)                  \
-  mips_secondary_reload_class (CLASS, MODE, X, 0)
+  mips_secondary_reload_class (CLASS, MODE, X, false)
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
@@ -1805,29 +2081,40 @@ extern const enum reg_class mips_regno_to_class[];
 #define STACK_GROWS_DOWNWARD
 
 /* The offset of the first local variable from the beginning of the frame.
-   See compute_frame_size for details about the frame layout.
-
-   ??? If flag_profile_values is true, and we are generating 32-bit code, then
-   we assume that we will need 16 bytes of argument space.  This is because
-   the value profiling code may emit calls to cmpdi2 in leaf functions.
-   Without this hack, the local variables will start at sp+8 and the gp save
-   area will be at sp+16, and thus they will overlap.  compute_frame_size is
-   OK because it uses STARTING_FRAME_OFFSET to compute cprestore_size, which
-   will end up as 24 instead of 8.  This won't be needed if profiling code is
-   inserted before virtual register instantiation.  */
+   See mips_compute_frame_info for details about the frame layout.  */
 
 #define STARTING_FRAME_OFFSET                                          \
-  ((flag_profile_values && ! TARGET_64BIT                              \
-    ? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \
-    : current_function_outgoing_args_size)                             \
+  (crtl->outgoing_args_size                                    \
    + (TARGET_CALL_CLOBBERED_GP ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
 
 #define RETURN_ADDR_RTX mips_return_addr
 
-/* Since the mips16 ISA mode is encoded in the least-significant bit
-   of the address, mask it off return addresses for purposes of
-   finding exception handling regions.  */
+/* Mask off the MIPS16 ISA bit in unwind addresses.
+
+   The reason for this is a little subtle.  When unwinding a call,
+   we are given the call's return address, which on most targets
+   is the address of the following instruction.  However, what we
+   actually want to find is the EH region for the call itself.
+   The target-independent unwind code therefore searches for "RA - 1".
+
+   In the MIPS16 case, RA is always an odd-valued (ISA-encoded) address.
+   RA - 1 is therefore the real (even-valued) start of the return
+   instruction.  EH region labels are usually odd-valued MIPS16 symbols
+   too, so a search for an even address within a MIPS16 region would
+   usually work.
+
+   However, there is an exception.  If the end of an EH region is also
+   the end of a function, the end label is allowed to be even.  This is
+   necessary because a following non-MIPS16 function may also need EH
+   information for its first instruction.
 
+   Thus a MIPS16 region may be terminated by an ISA-encoded or a
+   non-ISA-encoded address.  This probably isn't ideal, but it is
+   the traditional (legacy) behavior.  It is therefore only safe
+   to search MIPS EH regions for an _odd-valued_ address.
+
+   Masking off the ISA bit means that the target-independent code
+   will search for "(RA & -2) - 1", which is guaranteed to be odd.  */
 #define MASK_RETURN_ADDR GEN_INT (-2)
 
 
@@ -1847,18 +2134,10 @@ extern const enum reg_class mips_regno_to_class[];
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30},                           \
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
 
-/* We can always eliminate to the hard frame pointer.  We can eliminate
-   to the stack pointer unless a frame pointer is needed.
-
-   In mips16 mode, we need a frame pointer for a large frame; otherwise,
-   reload may be unable to compute the address of a local variable,
-   since there is no way to add a large constant to the stack pointer
-   without using a temporary register.  */
-#define CAN_ELIMINATE(FROM, TO)                                                \
-  ((TO) == HARD_FRAME_POINTER_REGNUM                                   \
-   || ((TO) == STACK_POINTER_REGNUM && !frame_pointer_needed           \
-       && (!TARGET_MIPS16                                              \
-          || compute_frame_size (get_frame_size ()) < 32768)))
+/* Make sure that we're not trying to eliminate to the wrong hard frame
+   pointer.  */
+#define CAN_ELIMINATE(FROM, TO) \
+  ((TO) == HARD_FRAME_POINTER_REGNUM || (TO) == STACK_POINTER_REGNUM)
 
 #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
   (OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
@@ -1879,8 +2158,8 @@ extern const enum reg_class mips_regno_to_class[];
    allocate the area reserved for arguments passed in registers.
    If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
    of this macro is to determine whether the space is included in
-   `current_function_outgoing_args_size'.  */
-#define OUTGOING_REG_PARM_STACK_SPACE 1
+   `crtl->outgoing_args_size'.  */
+#define OUTGOING_REG_PARM_STACK_SPACE(FNTYPE) 1
 
 #define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64)
 \f
@@ -1902,10 +2181,10 @@ extern const enum reg_class mips_regno_to_class[];
 #define FP_ARG_LAST  (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
 
 #define LIBCALL_VALUE(MODE) \
-  mips_function_value (NULL_TREE, NULL, (MODE))
+  mips_function_value (NULL_TREE, MODE)
 
 #define FUNCTION_VALUE(VALTYPE, FUNC) \
-  mips_function_value ((VALTYPE), (FUNC), VOIDmode)
+  mips_function_value (VALTYPE, VOIDmode)
 
 /* 1 if N is a possible register number for a function value.
    On the MIPS, R2 R3 and F0 F2 are the only register thus used.
@@ -1945,9 +2224,9 @@ extern const enum reg_class mips_regno_to_class[];
    allocate floating-point registers.
 
    So for the standard ABIs, the first N words are allocated to integer
-   registers, and function_arg decides on an argument-by-argument basis
-   whether that argument should really go in an integer register, or in
-   a floating-point one.  */
+   registers, and mips_function_arg decides on an argument-by-argument
+   basis whether that argument should really go in an integer register,
+   or in a floating-point one.  */
 
 typedef struct mips_args {
   /* Always true for varargs functions.  Otherwise true if at least
@@ -1990,14 +2269,14 @@ typedef struct mips_args {
    For a library call, FNTYPE is 0.  */
 
 #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \
-  init_cumulative_args (&CUM, FNTYPE, LIBNAME)                         \
+  mips_init_cumulative_args (&CUM, FNTYPE)
 
 /* Update the data in CUM to advance over an argument
    of mode MODE and data type TYPE.
    (TYPE is null for libcalls where that information may not be available.)  */
 
-#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED)                   \
-  function_arg_advance (&CUM, MODE, TYPE, NAMED)
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+  mips_function_arg_advance (&CUM, MODE, TYPE, NAMED)
 
 /* Determine where to put an argument to a function.
    Value is zero to push the argument on the stack,
@@ -2013,14 +2292,14 @@ typedef struct mips_args {
     (otherwise it is an extra parameter matching an ellipsis).  */
 
 #define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
-  function_arg( &CUM, MODE, TYPE, NAMED)
+  mips_function_arg (&CUM, MODE, TYPE, NAMED)
 
-#define FUNCTION_ARG_BOUNDARY function_arg_boundary
+#define FUNCTION_ARG_BOUNDARY mips_function_arg_boundary
 
-#define FUNCTION_ARG_PADDING(MODE, TYPE)               \
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
   (mips_pad_arg_upward (MODE, TYPE) ? upward : downward)
 
-#define BLOCK_REG_PADDING(MODE, TYPE, FIRST)           \
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
   (mips_pad_reg_upward (MODE, TYPE) ? upward : downward)
 
 /* True if using EABI and varargs can be passed in floating-point
@@ -2030,10 +2309,7 @@ typedef struct mips_args {
        (mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE)
 
 \f
-/* Say that the epilogue uses the return address register.  Note that
-   in the case of sibcalls, the values "used by the epilogue" are
-   considered live at the start of the called function.  */
-#define EPILOGUE_USES(REGNO) ((REGNO) == 31)
+#define EPILOGUE_USES(REGNO)   mips_epilogue_uses (REGNO)
 
 /* Treat LOC as a byte offset from the stack pointer and round it up
    to the next fully-aligned offset.  */
@@ -2041,10 +2317,6 @@ typedef struct mips_args {
   (TARGET_NEWABI ? ((LOC) + 15) & -16 : ((LOC) + 7) & -8)
 
 \f
-/* Implement `va_start' for varargs and stdarg.  */
-#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
-  mips_va_start (valist, nextarg)
-\f
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
@@ -2052,9 +2324,21 @@ typedef struct mips_args {
 {                                                                      \
   if (TARGET_MIPS16)                                                   \
     sorry ("mips16 function profiling");                               \
+  if (TARGET_LONG_CALLS)                                               \
+    {                                                                  \
+      /*  For TARGET_LONG_CALLS use $3 for the address of _mcount.  */ \
+      if (Pmode == DImode)                                             \
+       fprintf (FILE, "\tdla\t%s,_mcount\n", reg_names[GP_REG_FIRST + 3]); \
+      else                                                             \
+       fprintf (FILE, "\tla\t%s,_mcount\n", reg_names[GP_REG_FIRST + 3]); \
+    }                                                                  \
   fprintf (FILE, "\t.set\tnoat\n");                                    \
   fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n",   \
           reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]);  \
+  /* _mcount treats $2 as the static chain register.  */               \
+  if (cfun->static_chain_decl != NULL)                                 \
+    fprintf (FILE, "\tmove\t%s,%s\n", reg_names[2],                    \
+            reg_names[STATIC_CHAIN_REGNUM]);                           \
   if (!TARGET_NEWABI)                                                  \
     {                                                                  \
       fprintf (FILE,                                                   \
@@ -2064,10 +2348,20 @@ typedef struct mips_args {
               reg_names[STACK_POINTER_REGNUM],                         \
               Pmode == DImode ? 16 : 8);                               \
     }                                                                  \
-  fprintf (FILE, "\tjal\t_mcount\n");                                   \
+  if (TARGET_LONG_CALLS)                                               \
+    fprintf (FILE, "\tjalr\t%s\n", reg_names[GP_REG_FIRST + 3]);       \
+  else                                                                 \
+    fprintf (FILE, "\tjal\t_mcount\n");                                        \
   fprintf (FILE, "\t.set\tat\n");                                      \
+  /* _mcount treats $2 as the static chain register.  */               \
+  if (cfun->static_chain_decl != NULL)                                 \
+    fprintf (FILE, "\tmove\t%s,%s\n", reg_names[STATIC_CHAIN_REGNUM],  \
+            reg_names[2]);                                             \
 }
 
+/* The profiler preserves all interesting registers, including $31.  */
+#define MIPS_SAVE_REG_FOR_PROFILING_P(REGNO) false
+
 /* No mips port has ever used the profiler counter word, so don't emit it
    or the label for it.  */
 
@@ -2102,20 +2396,19 @@ typedef struct mips_args {
   fprintf (STREAM, "\t.word\t0x00000000\t\t# nop\n");                  \
   if (ptr_mode == DImode)                                              \
     {                                                                  \
-      fprintf (STREAM, "\t.word\t0xdfe30014\t\t# ld     $3,20($31)\n");        \
-      fprintf (STREAM, "\t.word\t0xdfe2001c\t\t# ld     $2,28($31)\n");        \
-      fprintf (STREAM, "\t.word\t0x0060c82d\t\t# dmove  $25,$3\n");    \
+      fprintf (STREAM, "\t.word\t0xdff90014\t\t# ld     $25,20($31)\n"); \
+      fprintf (STREAM, "\t.word\t0xdfef001c\t\t# ld     $15,28($31)\n"); \
     }                                                                  \
   else                                                                 \
     {                                                                  \
-      fprintf (STREAM, "\t.word\t0x8fe30014\t\t# lw     $3,20($31)\n");        \
-      fprintf (STREAM, "\t.word\t0x8fe20018\t\t# lw     $2,24($31)\n");        \
-      fprintf (STREAM, "\t.word\t0x0060c821\t\t# move   $25,$3\n");    \
+      fprintf (STREAM, "\t.word\t0x8ff90010\t\t# lw     $25,16($31)\n"); \
+      fprintf (STREAM, "\t.word\t0x8fef0014\t\t# lw     $15,20($31)\n"); \
     }                                                                  \
-  fprintf (STREAM, "\t.word\t0x00600008\t\t# jr     $3\n");            \
+  fprintf (STREAM, "\t.word\t0x03200008\t\t# jr     $25\n");           \
   if (ptr_mode == DImode)                                              \
     {                                                                  \
       fprintf (STREAM, "\t.word\t0x0020f82d\t\t# dmove   $31,$1\n");   \
+      fprintf (STREAM, "\t.word\t0x00000000\t\t# <padding>\n");                \
       fprintf (STREAM, "\t.dword\t0x00000000\t\t# <function address>\n"); \
       fprintf (STREAM, "\t.dword\t0x00000000\t\t# <static chain value>\n"); \
     }                                                                  \
@@ -2130,7 +2423,7 @@ typedef struct mips_args {
 /* A C expression for the size in bytes of the trampoline, as an
    integer.  */
 
-#define TRAMPOLINE_SIZE (32 + GET_MODE_SIZE (ptr_mode) * 2)
+#define TRAMPOLINE_SIZE (ptr_mode == DImode ? 48 : 36)
 
 /* Alignment required for trampolines, in bits.  */
 
@@ -2143,6 +2436,13 @@ typedef struct mips_args {
 #define CACHE_FLUSH_FUNC "_flush_cache"
 #endif
 
+#define MIPS_ICACHE_SYNC(ADDR, SIZE)                                   \
+  /* Flush both caches.  We need to flush the data cache in case       \
+     the system has a write-back cache.  */                            \
+  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func),        \
+                    0, VOIDmode, 3, ADDR, Pmode, SIZE, Pmode,          \
+                    GEN_INT (3), TYPE_MODE (integer_type_node))
+
 /* A C statement to initialize the variable parts of a trampoline.
    ADDR is an RTX for the address of the trampoline; FNADDR is an
    RTX for the address of the nested function; STATIC_CHAIN is an
@@ -2151,21 +2451,16 @@ typedef struct mips_args {
 
 #define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN)                           \
 {                                                                          \
-  rtx func_addr, chain_addr;                                               \
+  rtx func_addr, chain_addr, end_addr;                                      \
                                                                            \
-  func_addr = plus_constant (ADDR, 32);                                            \
+  func_addr = plus_constant (ADDR, ptr_mode == DImode ? 32 : 28);          \
   chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode));        \
-  emit_move_insn (gen_rtx_MEM (ptr_mode, func_addr), FUNC);                \
-  emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN);              \
-                                                                           \
-  /* Flush both caches.  We need to flush the data cache in case           \
-     the system has a write-back cache.  */                                \
-  /* ??? Should check the return value for errors.  */                     \
-  if (mips_cache_flush_func && mips_cache_flush_func[0])                   \
-    emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func),   \
-                      0, VOIDmode, 3, ADDR, Pmode,                         \
-                      GEN_INT (TRAMPOLINE_SIZE), TYPE_MODE (integer_type_node),\
-                      GEN_INT (3), TYPE_MODE (integer_type_node));         \
+  mips_emit_move (gen_rtx_MEM (ptr_mode, func_addr), FUNC);                \
+  mips_emit_move (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN);              \
+  end_addr = gen_reg_rtx (Pmode);                                          \
+  emit_insn (gen_add3_insn (end_addr, copy_rtx (ADDR),                     \
+                            GEN_INT (TRAMPOLINE_SIZE)));                   \
+  emit_insn (gen_clear_cache (copy_rtx (ADDR), end_addr));                 \
 }
 \f
 /* Addressing modes, and classification of registers for them.  */
@@ -2259,26 +2554,33 @@ typedef struct mips_args {
 #define SYMBOL_REF_LONG_CALL_P(X)                                      \
   ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
 
-/* Specify the machine mode that this machine uses
-   for the index in the tablejump instruction.
-   ??? Using HImode in mips16 mode can cause overflow.  */
-#define CASE_VECTOR_MODE \
-  (TARGET_MIPS16 ? HImode : ptr_mode)
+/* This flag marks functions that cannot be lazily bound.  */
+#define SYMBOL_FLAG_BIND_NOW (SYMBOL_FLAG_MACH_DEP << 1)
+#define SYMBOL_REF_BIND_NOW_P(RTX) \
+  ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_BIND_NOW) != 0)
 
-/* Define as C expression which evaluates to nonzero 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 (TARGET_MIPS16)
+/* True if we're generating a form of MIPS16 code in which jump tables
+   are stored in the text section and encoded as 16-bit PC-relative
+   offsets.  This is only possible when general text loads are allowed,
+   since the table access itself will be an "lh" instruction.  */
+/* ??? 16-bit offsets can overflow in large functions.  */
+#define TARGET_MIPS16_SHORT_JUMP_TABLES TARGET_MIPS16_TEXT_LOADS
+
+#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16_SHORT_JUMP_TABLES
+
+#define CASE_VECTOR_MODE (TARGET_MIPS16_SHORT_JUMP_TABLES ? HImode : ptr_mode)
+
+#define CASE_VECTOR_PC_RELATIVE TARGET_MIPS16_SHORT_JUMP_TABLES
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #ifndef DEFAULT_SIGNED_CHAR
 #define DEFAULT_SIGNED_CHAR 1
 #endif
 
-/* Max number of bytes we can move from memory to memory
-   in one reasonably fast instruction.  */
-#define MOVE_MAX (TARGET_64BIT ? 8 : 4)
+/* Although LDC1 and SDC1 provide 64-bit moves on 32-bit targets,
+   we generally don't want to use them for copying arbitrary data.
+   A single N-word move is usually the same cost as N single-word moves.  */
+#define MOVE_MAX UNITS_PER_WORD
 #define MAX_MOVE_MAX 8
 
 /* Define this macro as a C expression which is nonzero if
@@ -2318,11 +2620,6 @@ typedef struct mips_args {
 #define FUNCTION_MODE SImode
 
 \f
-/* The cost of loading values from the constant pool.  It should be
-   larger than the cost of any constant we want to synthesize in-line.  */
-
-#define CONSTANT_POOL_COST COSTS_N_INSNS (8)
-
 /* A C expression for the cost of moving data from a register in
    class FROM to one in class TO.  The classes are expressed using
    the enumeration values such as `GENERAL_REGS'.  A value of 2 is
@@ -2357,7 +2654,7 @@ typedef struct mips_args {
 /* A C expression for the cost of a branch instruction.  A value of
    1 is the default; other values are interpreted relative to that.  */
 
-#define BRANCH_COST mips_cost->branch_cost
+#define BRANCH_COST(speed_p, predictable_p) mips_branch_cost
 #define LOGICAL_OP_NON_SHORT_CIRCUIT 0
 
 /* If defined, modifies the length assigned to instruction INSN as a
@@ -2387,7 +2684,7 @@ typedef struct mips_args {
    ? "%*" INSN "\t%" #OPNO "%/"                                        \
    : REG_P (OPERANDS[OPNO])                                    \
    ? "%*" INSN "r\t%" #OPNO "%/"                               \
-   : TARGET_ABICALLS                                           \
+   : TARGET_ABICALLS_PIC2                                      \
    ? (".option\tpic0\n\t"                                      \
       "%*" INSN "\t%" #OPNO "%/\n\t"                           \
       ".option\tpic2")                                         \
@@ -2481,44 +2778,9 @@ typedef struct mips_args {
 
 #define ALL_COP_ADDITIONAL_REGISTER_NAMES
 
-/* A C compound statement to output to stdio stream STREAM the
-   assembler syntax for an instruction operand X.  X is an RTL
-   expression.
-
-   CODE is a value that can be used to specify one of several ways
-   of printing the operand.  It is used when identical operands
-   must be printed differently depending on the context.  CODE
-   comes from the `%' specification that was used to request
-   printing of the operand.  If the specification was just `%DIGIT'
-   then CODE is 0; if the specification was `%LTR DIGIT' then CODE
-   is the ASCII code for LTR.
-
-   If X is a register, this macro should print the register's name.
-   The names can be found in an array `reg_names' whose type is
-   `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.
-
-   When the machine description has a specification `%PUNCT' (a `%'
-   followed by a punctuation character), this macro is called with
-   a null pointer for X and the punctuation character for CODE.
-
-   See mips.c for the MIPS specific codes.  */
-
-#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
-
-/* A C expression which evaluates to true if CODE is a valid
-   punctuation character for use in the `PRINT_OPERAND' macro.  If
-   `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no
-   punctuation characters (except for the standard one, `%') are
-   used in this way.  */
-
+#define PRINT_OPERAND mips_print_operand
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE) mips_print_operand_punct[CODE]
-
-/* A C compound statement to output to stdio stream STREAM the
-   assembler syntax for an instruction operand that is a memory
-   reference whose address is ADDR.  ADDR is an RTL expression.  */
-
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-
+#define PRINT_OPERAND_ADDRESS mips_print_operand_address
 
 /* A C statement, to be executed after all slot-filler instructions
    have been output.  If necessary, call `dbr_sequence_length' to
@@ -2550,10 +2812,8 @@ do                                                                       \
   }                                                                    \
 while (0)
 
-
 /* How to tell the debugger about changes of source files.  */
-#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME)                       \
-  mips_output_filename (STREAM, NAME)
+#define ASM_OUTPUT_SOURCE_FILENAME mips_output_filename
 
 /* mips-tfile does not understand .stabd directives.  */
 #define DBX_OUTPUT_SOURCE_LINE(STREAM, LINE, COUNTER) do {     \
@@ -2577,7 +2837,7 @@ while (0)
 
 #undef ASM_DECLARE_OBJECT_NAME
 #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
-  mips_declare_object (STREAM, NAME, "", ":\n", 0)
+  mips_declare_object (STREAM, NAME, "", ":\n")
 
 /* Globalizing directive for a label.  */
 #define GLOBAL_ASM_OP "\t.globl\t"
@@ -2612,10 +2872,6 @@ while (0)
 #undef ASM_DECLARE_FUNCTION_NAME
 #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL)
 
-#ifndef FUNCTION_NAME_ALREADY_DECLARED
-#define FUNCTION_NAME_ALREADY_DECLARED 0
-#endif
-
 /* This is how to store into the string LABEL
    the symbol_ref name of an internal numbered label where
    PREFIX is the class of label and NUM is the number within the class.
@@ -2625,6 +2881,32 @@ while (0)
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)                  \
   sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
 
+/* Print debug labels as "foo = ." rather than "foo:" because they should
+   represent a byte pointer rather than an ISA-encoded address.  This is
+   particularly important for code like:
+
+       $LFBxxx = .
+               .cfi_startproc
+               ...
+               .section .gcc_except_table,...
+               ...
+               .uleb128 foo-$LFBxxx
+
+   The .uleb128 requies $LFBxxx to match the FDE start address, which is
+   likewise a byte pointer rather than an ISA-encoded address.
+
+   At the time of writing, this hook is not used for the function end
+   label:
+
+       $LFExxx:
+               .end foo
+
+   But this doesn't matter, because GAS doesn't treat a pre-.end label
+   as a MIPS16 one anyway.  */
+
+#define ASM_OUTPUT_DEBUG_LABEL(FILE, PREFIX, NUM)                      \
+  fprintf (FILE, "%s%s%d = .\n", LOCAL_LABEL_PREFIX, PREFIX, NUM)
+
 /* This is how to output an element of a case-vector that is absolute.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE)                         \
@@ -2639,7 +2921,7 @@ while (0)
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL)             \
 do {                                                                   \
-  if (TARGET_MIPS16)                                                   \
+  if (TARGET_MIPS16_SHORT_JUMP_TABLES)                                 \
     fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n",                         \
             LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL);       \
   else if (TARGET_GPWORD)                                              \
@@ -2662,10 +2944,6 @@ do {                                                                     \
             LOCAL_LABEL_PREFIX, VALUE);                                \
 } while (0)
 
-/* When generating MIPS16 code, we want the jump table to be in the text
-   section so that we can load its address using a PC-relative addition.  */
-#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16
-
 /* This is how to output an assembler line
    that says to advance the location counter
    to a multiple of 2**LOG bytes.  */
@@ -2682,8 +2960,7 @@ do {                                                                      \
 
 /* This is how to output a string.  */
 #undef ASM_OUTPUT_ASCII
-#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN)                          \
-  mips_output_ascii (STREAM, STRING, LEN, "\t.ascii\t")
+#define ASM_OUTPUT_ASCII mips_output_ascii
 
 /* Output #ident as a in the read-only data section.  */
 #undef  ASM_OUTPUT_IDENT
@@ -2710,8 +2987,8 @@ do {                                                                      \
 #define ASM_OUTPUT_REG_PUSH(STREAM,REGNO)                              \
 do                                                                     \
   {                                                                    \
-    fprintf (STREAM, "\t%s\t%s,%s,8\n\t%s\t%s,0(%s)\n",                        \
-            TARGET_64BIT ? "dsubu" : "subu",                           \
+    fprintf (STREAM, "\t%s\t%s,%s,-8\n\t%s\t%s,0(%s)\n",               \
+            TARGET_64BIT ? "daddiu" : "addiu",                         \
             reg_names[STACK_POINTER_REGNUM],                           \
             reg_names[STACK_POINTER_REGNUM],                           \
             TARGET_64BIT ? "sd" : "sw",                                \
@@ -2753,6 +3030,85 @@ while (0)
 
 #undef PTRDIFF_TYPE
 #define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int")
+
+/* The maximum number of bytes that can be copied by one iteration of
+   a movmemsi loop; see mips_block_move_loop.  */
+#define MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER \
+  (UNITS_PER_WORD * 4)
+
+/* The maximum number of bytes that can be copied by a straight-line
+   implementation of movmemsi; see mips_block_move_straight.  We want
+   to make sure that any loop-based implementation will iterate at
+   least twice.  */
+#define MIPS_MAX_MOVE_BYTES_STRAIGHT \
+  (MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER * 2)
+
+/* The base cost of a memcpy call, for MOVE_RATIO and friends.  These
+   values were determined experimentally by benchmarking with CSiBE.
+   In theory, the call overhead is higher for TARGET_ABICALLS (especially
+   for o32 where we have to restore $gp afterwards as well as make an
+   indirect call), but in practice, bumping this up higher for
+   TARGET_ABICALLS doesn't make much difference to code size.  */
+
+#define MIPS_CALL_RATIO 8
+
+/* Any loop-based implementation of movmemsi will have at least
+   MIPS_MAX_MOVE_BYTES_STRAIGHT / UNITS_PER_WORD memory-to-memory
+   moves, so allow individual copies of fewer elements.
+
+   When movmemsi is not available, use a value approximating
+   the length of a memcpy call sequence, so that move_by_pieces
+   will generate inline code if it is shorter than a function call.
+   Since move_by_pieces_ninsns counts memory-to-memory moves, but
+   we'll have to generate a load/store pair for each, halve the
+   value of MIPS_CALL_RATIO to take that into account.  */
+
+#define MOVE_RATIO(speed)                              \
+  (HAVE_movmemsi                                       \
+   ? MIPS_MAX_MOVE_BYTES_STRAIGHT / MOVE_MAX           \
+   : MIPS_CALL_RATIO / 2)
+
+/* movmemsi is meant to generate code that is at least as good as
+   move_by_pieces.  However, movmemsi effectively uses a by-pieces
+   implementation both for moves smaller than a word and for word-aligned
+   moves of no more than MIPS_MAX_MOVE_BYTES_STRAIGHT bytes.  We should
+   allow the tree-level optimisers to do such moves by pieces, as it
+   often exposes other optimization opportunities.  We might as well
+   continue to use movmemsi at the rtl level though, as it produces
+   better code when scheduling is disabled (such as at -O).  */
+
+#define MOVE_BY_PIECES_P(SIZE, ALIGN)                          \
+  (HAVE_movmemsi                                               \
+   ? (!currently_expanding_to_rtl                              \
+      && ((ALIGN) < BITS_PER_WORD                              \
+         ? (SIZE) < UNITS_PER_WORD                             \
+         : (SIZE) <= MIPS_MAX_MOVE_BYTES_STRAIGHT))            \
+   : (move_by_pieces_ninsns (SIZE, ALIGN, MOVE_MAX_PIECES + 1) \
+      < (unsigned int) MOVE_RATIO (false)))
+
+/* For CLEAR_RATIO, when optimizing for size, give a better estimate
+   of the length of a memset call, but use the default otherwise.  */
+
+#define CLEAR_RATIO(speed)\
+  ((speed) ? 15 : MIPS_CALL_RATIO)
+
+/* This is similar to CLEAR_RATIO, but for a non-zero constant, so when
+   optimizing for size adjust the ratio to account for the overhead of
+   loading the constant and replicating it across the word.  */
+
+#define SET_RATIO(speed) \
+  ((speed) ? 15 : MIPS_CALL_RATIO - 2)
+
+/* STORE_BY_PIECES_P can be used when copying a constant string, but
+   in that case each word takes 3 insns (lui, ori, sw), or more in
+   64-bit mode, instead of 2 (lw, sw).  For now we always fail this
+   and let the move_by_pieces code copy the string from read-only
+   memory.  In the future, this could be tuned further for multi-issue
+   CPUs that can issue stores down one pipe and arithmetic instructions
+   down another; in that case, the lui/ori/sw combination would be a
+   win for long enough strings.  */
+
+#define STORE_BY_PIECES_P(SIZE, ALIGN) 0
 \f
 #ifndef __mips16
 /* Since the bits of the _init and _fini function is spread across
@@ -2788,3 +3144,318 @@ while (0)
 #ifndef HAVE_AS_TLS
 #define HAVE_AS_TLS 0
 #endif
+
+/* Return an asm string that atomically:
+
+     - Compares memory reference %1 to register %2 and, if they are
+       equal, changes %1 to %3.
+
+     - Sets register %0 to the old value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc" instructions
+   and OP is the instruction that should be used to load %3 into a
+   register.  */
+#define MIPS_COMPARE_AND_SWAP(SUFFIX, OP)      \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\tbne\t%0,%z2,2f\n"                         \
+  "\t" OP "\t%@,%3\n"                          \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)\n"                           \
+  "2:\n"
+
+/* Return an asm string that atomically:
+
+     - Given that %2 contains a bit mask and %3 the inverted mask and
+       that %4 and %5 have already been ANDed with %2.
+
+     - Compares the bits in memory reference %1 selected by mask %2 to
+       register %4 and, if they are equal, changes the selected bits
+       in memory to %5.
+
+     - Sets register %0 to the old value of memory reference %1.
+
+    OPS are the instructions needed to OR %5 with %@.  */
+#define MIPS_COMPARE_AND_SWAP_12(OPS)          \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll\t%0,%1\n"                            \
+  "\tand\t%@,%0,%2\n"                          \
+  "\tbne\t%@,%z4,2f\n"                         \
+  "\tand\t%@,%0,%3\n"                          \
+  OPS                                          \
+  "\tsc\t%@,%1\n"                              \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)\n"                           \
+  "2:\n"
+
+#define MIPS_COMPARE_AND_SWAP_12_ZERO_OP ""
+#define MIPS_COMPARE_AND_SWAP_12_NONZERO_OP "\tor\t%@,%@,%5\n"
+
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %0 to %0 INSN %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  */
+#define MIPS_SYNC_OP(SUFFIX, INSN)             \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%@,%0\n"                  \
+  "\t" INSN "\t%@,%@,%1\n"                     \
+  "\tsc" SUFFIX "\t%@,%0\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Given that %1 contains a bit mask and %2 the inverted mask and
+       that %3 has already been ANDed with %1.
+
+     - Sets the selected bits of memory reference %0 to %0 INSN %3.
+
+     - Uses scratch register %4.
+
+    AND_OP is an instruction done after INSN to mask INSN's result
+    with the mask.  For most operations, this is an AND with the
+    inclusive mask (%1).  For nand operations -- where the result of
+    INSN is already correctly masked -- it instead performs a bitwise
+    not.  */
+#define MIPS_SYNC_OP_12(INSN, AND_OP)          \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll\t%4,%0\n"                            \
+  "\tand\t%@,%4,%2\n"                          \
+  "\t" INSN "\t%4,%4,%z3\n"                    \
+  AND_OP                                       \
+  "\tor\t%@,%@,%4\n"                           \
+  "\tsc\t%@,%0\n"                              \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_OP_12_AND "\tand\t%4,%4,%1\n"
+#define MIPS_SYNC_OP_12_XOR "\txor\t%4,%4,%1\n"
+
+/* Return an asm string that atomically:
+
+     - Given that %2 contains a bit mask and %3 the inverted mask and
+       that %4 has already been ANDed with %2.
+
+     - Sets the selected bits of memory reference %1 to %1 INSN %4.
+
+     - Sets %0 to the original value of %1.
+
+     - Uses scratch register %5.
+
+    AND_OP is an instruction done after INSN to mask INSN's result
+    with the mask.  For most operations, this is an AND with the
+    inclusive mask (%1).  For nand operations -- where the result of
+    INSN is already correctly masked -- it instead performs a bitwise
+    not.  */
+#define MIPS_SYNC_OLD_OP_12(INSN, AND_OP)      \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll\t%0,%1\n"                            \
+  "\tand\t%@,%0,%3\n"                          \
+  "\t" INSN "\t%5,%0,%z4\n"                    \
+  AND_OP                                       \
+  "\tor\t%@,%@,%5\n"                           \
+  "\tsc\t%@,%1\n"                              \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_OLD_OP_12_AND "\tand\t%5,%5,%2\n"
+#define MIPS_SYNC_OLD_OP_12_XOR "\txor\t%5,%5,%2\n"
+
+/* Return an asm string that atomically:
+
+     - Given that %2 contains a bit mask and %3 the inverted mask and
+       that %4 has already been ANDed with %2.
+
+     - Sets the selected bits of memory reference %1 to %1 INSN %4.
+
+     - Sets %0 to the new value of %1.
+
+    AND_OP is an instruction done after INSN to mask INSN's result
+    with the mask.  For most operations, this is an AND with the
+    inclusive mask (%1).  For nand operations -- where the result of
+    INSN is already correctly masked -- it instead performs a bitwise
+    not.  */
+#define MIPS_SYNC_NEW_OP_12(INSN, AND_OP)      \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll\t%0,%1\n"                            \
+  "\tand\t%@,%0,%3\n"                          \
+  "\t" INSN "\t%0,%0,%z4\n"                    \
+  AND_OP                                       \
+  "\tor\t%@,%@,%0\n"                           \
+  "\tsc\t%@,%1\n"                              \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_NEW_OP_12_AND "\tand\t%0,%0,%2\n"
+#define MIPS_SYNC_NEW_OP_12_XOR "\txor\t%0,%0,%2\n"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %1 to %1 INSN %2.
+
+     - Sets register %0 to the old value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  */
+#define MIPS_SYNC_OLD_OP(SUFFIX, INSN)         \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\t" INSN "\t%@,%0,%2\n"                     \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %1 to %1 INSN %2.
+
+     - Sets register %0 to the new value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  */
+#define MIPS_SYNC_NEW_OP(SUFFIX, INSN)         \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\t" INSN "\t%@,%0,%2\n"                     \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b%~\n"                      \
+  "\t" INSN "\t%0,%0,%2\n"                     \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %0 to ~(%0 AND %1).
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  INSN is the and instruction needed to and a register
+   with %2.  */
+#define MIPS_SYNC_NAND(SUFFIX, INSN)           \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%@,%0\n"                  \
+  "\t" INSN "\t%@,%@,%1\n"                     \
+  "\tnor\t%@,%@,%.\n"                          \
+  "\tsc" SUFFIX "\t%@,%0\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %1 to ~(%1 AND %2).
+
+     - Sets register %0 to the old value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  INSN is the and instruction needed to and a register
+   with %2.  */
+#define MIPS_SYNC_OLD_NAND(SUFFIX, INSN)       \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\t" INSN "\t%@,%0,%2\n"                     \
+  "\tnor\t%@,%@,%.\n"                          \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %1 to ~(%1 AND %2).
+
+     - Sets register %0 to the new value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  INSN is the and instruction needed to and a register
+   with %2.  */
+#define MIPS_SYNC_NEW_NAND(SUFFIX, INSN)       \
+  "%(%<%[%|sync\n"                             \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\t" INSN "\t%0,%0,%2\n"                     \
+  "\tnor\t%@,%0,%.\n"                          \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b%~\n"                      \
+  "\tnor\t%0,%0,%.\n"                          \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Sets memory reference %1 to %2.
+
+     - Sets register %0 to the old value of memory reference %1.
+
+   SUFFIX is the suffix that should be added to "ll" and "sc"
+   instructions.  OP is the and instruction that should be used to
+   load %2 into a register.  */
+#define MIPS_SYNC_EXCHANGE(SUFFIX, OP)         \
+  "%(%<%[%|\n"                                 \
+  "1:\tll" SUFFIX "\t%0,%1\n"                  \
+  "\t" OP "\t%@,%2\n"                          \
+  "\tsc" SUFFIX "\t%@,%1\n"                    \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+/* Return an asm string that atomically:
+
+     - Given that %2 contains an inclusive mask, %3 and exclusive mask
+       and %4 has already been ANDed with the inclusive mask.
+
+     - Sets bits selected by the inclusive mask of memory reference %1
+       to %4.
+
+     - Sets register %0 to the old value of memory reference %1.
+
+    OPS are the instructions needed to OR %4 with %@.
+
+    Operand %2 is unused, but needed as to give the test_and_set_12
+    insn the five operands expected by the expander.  */
+#define MIPS_SYNC_EXCHANGE_12(OPS)              \
+  "%(%<%[%|\n"                                 \
+  "1:\tll\t%0,%1\n"                            \
+  "\tand\t%@,%0,%3\n"                          \
+  OPS                                          \
+  "\tsc\t%@,%1\n"                              \
+  "\tbeq%?\t%@,%.,1b\n"                                \
+  "\tnop\n"                                    \
+  "\tsync%-%]%>%)"
+
+#define MIPS_SYNC_EXCHANGE_12_ZERO_OP ""
+#define MIPS_SYNC_EXCHANGE_12_NONZERO_OP "\tor\t%@,%@,%4\n"
+
+#ifndef USED_FOR_TARGET
+extern const enum reg_class mips_regno_to_class[];
+extern bool mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
+extern bool mips_print_operand_punct[256];
+extern const char *current_function_file; /* filename current function is in */
+extern int num_source_filenames;       /* current .file # */
+extern int set_noreorder;              /* # of nested .set noreorder's  */
+extern int set_nomacro;                        /* # of nested .set nomacro's  */
+extern int mips_dbx_regno[];
+extern int mips_dwarf_regno[];
+extern bool mips_split_p[];
+extern bool mips_split_hi_p[];
+extern GTY(()) rtx cmp_operands[2];
+extern enum processor_type mips_arch;   /* which cpu to codegen for */
+extern enum processor_type mips_tune;   /* which cpu to schedule for */
+extern int mips_isa;                   /* architectural level */
+extern int mips_abi;                   /* which ABI to use */
+extern const struct mips_cpu_info *mips_arch_info;
+extern const struct mips_cpu_info *mips_tune_info;
+extern const struct mips_rtx_cost_data *mips_cost;
+extern bool mips_base_mips16;
+extern enum mips_code_readable_setting mips_code_readable;
+#endif
+
+/* Enable querying of DFA units.  */
+#define CPU_UNITS_QUERY 1