OSDN Git Service

2001-07-21 H.J. Lu (hjl@gnu.org)
[pf3gnuchains/gcc-fork.git] / gcc / config / mips / mips.h
index c562307..e87177f 100644 (file)
@@ -1,5 +1,6 @@
 /* Definitions of target machine for GNU compiler.  MIPS version.
-   Copyright (C) 1989, 90-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+   1999, 2000, 2001 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
@@ -27,12 +28,9 @@ Boston, MA 02111-1307, USA.  */
 
 extern char    *asm_file_name;
 extern char    call_used_regs[];
-extern int     current_function_calls_alloca;
-extern char    *language_string;
 extern int     may_call_alloca;
 extern char   **save_argv;
 extern int     target_flags;
-extern char    *version_string;
 
 /* MIPS external variables defined in mips.c.  */
 
@@ -73,15 +71,19 @@ enum processor_type {
 };
 
 /* Recast the cpu class to be the cpu attribute.  */
-#define mips_cpu_attr ((enum attr_cpu)mips_cpu)
+#define mips_cpu_attr ((enum attr_cpu)mips_tune)
 
 /* Which ABI to use.  These are constants because abi64.h must check their
-   value at preprocessing time.  */
+   value at preprocessing time.
+
+   ABI_32 (original 32, or o32), ABI_N32 (n32), ABI_64 (n64) are all
+   defined by SGI.  ABI_O64 is o32 extended to work on a 64 bit machine. */
 
 #define ABI_32  0
 #define ABI_N32 1
 #define ABI_64  2
 #define ABI_EABI 3
+#define ABI_O64  4
 
 #ifndef MIPS_ABI_DEFAULT
 /* We define this away so that there is no extra runtime cost if the target
@@ -112,7 +114,7 @@ enum block_move_type {
 
 extern char mips_reg_names[][8];       /* register names (a0 vs. $4). */
 extern char mips_print_operand_punct[];        /* print_operand punctuation chars */
-extern char *current_function_file;    /* filename current function is in */
+extern const char *current_function_file; /* filename current function is in */
 extern int num_source_filenames;       /* current .file # */
 extern int inside_function;            /* != 0 if inside of a function */
 extern int ignore_line_number;         /* != 0 if we are to ignore next .loc */
@@ -131,17 +133,21 @@ extern int mips_branch_likely;            /* emit 'l' after br (branch likely) */
 extern int mips_dbx_regno[];           /* Map register # to debug register # */
 extern struct rtx_def *branch_cmp[2];  /* operands for compare */
 extern enum cmp_type branch_type;      /* what type of branch to use */
-extern enum processor_type mips_cpu;   /* which cpu are we scheduling for */
+extern enum processor_type mips_arch;   /* which cpu to codegen for */
+extern enum processor_type mips_tune;   /* which cpu to schedule for */
 extern enum mips_abicalls_type mips_abicalls;/* for svr4 abi pic calls */
 extern int mips_isa;                   /* architectural level */
 extern int mips16;                     /* whether generating mips16 code */
 extern int mips16_hard_float;          /* mips16 without -msoft-float */
 extern int mips_entry;                 /* generate entry/exit for mips16 */
-extern char *mips_cpu_string;          /* for -mcpu=<xxx> */
-extern char *mips_isa_string;          /* for -mips{1,2,3,4} */
-extern char *mips_abi_string;          /* for -mabi={32,n32,64} */
-extern char *mips_entry_string;                /* for -mentry */
-extern char *mips_no_mips16_string;    /* for -mno-mips16 */
+extern const char *mips_cpu_string;    /* for -mcpu=<xxx> */
+extern const char *mips_arch_string;    /* for -march=<xxx> */
+extern const char *mips_tune_string;    /* for -mtune=<xxx> */
+extern const char *mips_isa_string;    /* for -mips{1,2,3,4} */
+extern const char *mips_abi_string;    /* for -mabi={32,n32,64} */
+extern const char *mips_entry_string;  /* for -mentry */
+extern const char *mips_no_mips16_string;/* for -mno-mips16 */
+extern const char *mips_explicit_type_size_string;/* for -mexplicit-type-size */
 extern int mips_split_addresses;       /* perform high/lo_sum support */
 extern int dslots_load_total;          /* total # load related delay slots */
 extern int dslots_load_filled;         /* # filled load delay slots */
@@ -157,138 +163,10 @@ extern struct rtx_def *embedded_pic_fnaddr_rtx;  /* function address */
 extern int mips_string_length;         /* length of strings for mips16 */
 extern struct rtx_def *mips16_gp_pseudo_rtx; /* psuedo reg holding $gp */
 
-/* Functions within mips.c that we reference.  Some of these return  type
-   HOST_WIDE_INT, so define that here.  This is a copy of code in machmode.h.
-
-   ??? It would be good to try to put this as common code someplace.  */
-
-#ifndef HOST_BITS_PER_WIDE_INT
-
-#if HOST_BITS_PER_LONG > HOST_BITS_PER_INT
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_LONG
-#define HOST_WIDE_INT long
-#else
-#define HOST_BITS_PER_WIDE_INT HOST_BITS_PER_INT
-#define HOST_WIDE_INT int
-#endif
-
-#endif
-
-extern void            abort_with_insn ();
-extern int             arith32_operand ();
-extern int             arith_operand ();
-extern int             cmp_op ();
-extern HOST_WIDE_INT   compute_frame_size ();
-extern int             const_float_1_operand ();
-extern void            expand_block_move ();
-extern int             equality_op ();
-extern void            final_prescan_insn ();
-extern struct rtx_def *        function_arg ();
-extern void            function_arg_advance ();
-extern int             function_arg_partial_nregs ();
-extern int             function_arg_pass_by_reference ();
-extern void            function_epilogue ();
-extern void            function_prologue ();
-extern void            gen_conditional_branch ();
-extern void            gen_conditional_move ();
-extern struct rtx_def * gen_int_relational ();
-extern void            init_cumulative_args ();
-extern int             large_int ();
-extern void            machine_dependent_reorg ();
-extern int             mips_address_cost ();
-extern void            mips_asm_file_end ();
-extern void            mips_asm_file_start ();
-extern int             mips_can_use_return_insn ();
-extern int             mips_const_double_ok ();
-extern void            mips_count_memory_refs ();
-extern HOST_WIDE_INT   mips_debugger_offset ();
-extern void            mips_declare_object ();
-extern int             mips_epilogue_delay_slots ();
-extern void            mips_expand_epilogue ();
-extern void            mips_expand_prologue ();
-extern int             mips_check_split ();
-extern char           *mips_fill_delay_slot ();
-extern char           *mips_move_1word ();
-extern char           *mips_move_2words ();
-extern void            mips_output_double ();
-extern int             mips_output_external ();
-extern void            mips_output_float ();
-extern void            mips_output_filename ();
-extern void            mips_output_lineno ();
-extern char           *output_block_move ();
-extern void            override_options ();
-extern int             pc_or_label_operand ();
-extern void            print_operand_address ();
-extern void            print_operand ();
-extern void            print_options ();
-extern int             reg_or_0_operand ();
-extern int             simple_epilogue_p ();
-extern int             simple_memory_operand ();
-extern int             double_memory_operand ();
-extern int             small_int ();
-extern void            trace ();
-extern int             uns_arith_operand ();
-extern struct rtx_def *        embedded_pic_offset ();
-extern void            mips_order_regs_for_local_alloc ();
-extern struct rtx_def *        mips16_gp_pseudo_reg ();
-extern struct rtx_def * mips16_gp_offset ();
-extern int             mips16_gp_offset_p ();
-extern int             mips16_constant ();
-extern int             mips16_constant_after_function_p ();
-extern int             build_mips16_call_stub ();
-
-/* Recognition functions that return if a condition is true.  */
-extern int             address_operand ();
-extern int             call_insn_operand ();
-extern int             const_double_operand ();
-extern int             const_int_operand ();
-extern int             consttable_operand ();
-extern int             general_operand ();
-extern int             immediate_operand ();
-extern int             memory_address_p ();
-extern int             memory_operand ();
-extern int             nonimmediate_operand ();
-extern int             nonmemory_operand ();
-extern int             pic_address_needs_scratch ();
-extern int             register_operand ();
-extern int             scratch_operand ();
-extern int             move_operand ();
-extern int             movdi_operand ();
-extern int             se_register_operand ();
-extern int             se_reg_or_0_operand ();
-extern int             se_uns_arith_operand ();
-extern int             se_arith_operand ();
-extern int             se_nonmemory_operand ();
-extern int             se_nonimmediate_operand ();
-extern int              extend_operator ();
-extern int              highpart_shift_operator ();
-extern int             m16_uimm3_b ();
-extern int             m16_simm4_1 ();
-extern int             m16_nsimm4_1 ();
-extern int             m16_simm5_1 ();
-extern int             m16_nsimm5_1 ();
-extern int             m16_uimm5_4 ();
-extern int             m16_nuimm5_4 ();
-extern int             m16_simm8_1 ();
-extern int             m16_nsimm8_1 ();
-extern int             m16_uimm8_1 ();
-extern int             m16_nuimm8_1 ();
-extern int             m16_uimm8_m1_1 ();
-extern int             m16_uimm8_4 ();
-extern int             m16_nuimm8_4 ();
-extern int             m16_simm8_8 ();
-extern int             m16_nsimm8_8 ();
-extern int             m16_usym8_4 ();
-extern int             m16_usym5_4 ();
-
 /* Functions to change what output section we are using.  */
-extern void            data_section ();
-extern void            rdata_section ();
-extern void            readonly_data_section ();
-extern void            sdata_section ();
-extern void            text_section ();
-extern void            mips_select_rtx_section ();
-extern void            mips_select_section ();
+extern void            rdata_section PARAMS ((void));
+extern void            sdata_section PARAMS ((void));
+extern void            sbss_section PARAMS ((void));
 
 /* Stubs for half-pic support if not OSF/1 reference platform.  */
 
@@ -304,50 +182,63 @@ extern void               mips_select_section ();
 #define HALF_PIC_FINISH(STREAM)
 #endif
 
+/* Macros to silence warnings about numbers being signed in traditional
+   C and unsigned in ISO C when compiled on 32-bit hosts.  */
+
+#define BITMASK_HIGH   (((unsigned long)1) << 31)      /* 0x80000000 */
+#define BITMASK_UPPER16        ((unsigned long)0xffff << 16)   /* 0xffff0000 */
+#define BITMASK_LOWER16        ((unsigned long)0xffff)         /* 0x0000ffff */
+
 \f
 /* Run-time compilation parameters selecting different hardware subsets.  */
 
 /* Macros used in the machine description to test the flags.  */
 
                                        /* Bits for real switches */
-#define MASK_INT64     0x00000001      /* ints are 64 bits */
-#define MASK_LONG64    0x00000002      /* longs and pointers are 64 bits */
-#define MASK_SPLIT_ADDR        0x00000004      /* Address splitting is enabled.  */
-#define MASK_GPOPT     0x00000008      /* Optimize for global pointer */
-#define MASK_GAS       0x00000010      /* Gas used instead of MIPS as */
-#define MASK_NAME_REGS 0x00000020      /* Use MIPS s/w reg name convention */
-#define MASK_STATS     0x00000040      /* print statistics to stderr */
-#define MASK_MEMCPY    0x00000080      /* call memcpy instead of inline code*/
-#define MASK_SOFT_FLOAT        0x00000100      /* software floating point */
-#define MASK_FLOAT64   0x00000200      /* fp registers are 64 bits */
-#define MASK_ABICALLS  0x00000400      /* emit .abicalls/.cprestore/.cpload */
-#define MASK_HALF_PIC  0x00000800      /* Emit OSF-style pic refs to externs*/
-#define MASK_LONG_CALLS        0x00001000      /* Always call through a register */
-#define MASK_64BIT     0x00002000      /* Use 64 bit GP registers and insns */
-#define MASK_EMBEDDED_PIC 0x00004000   /* Generate embedded PIC code */
+#define MASK_INT64        0x00000001   /* ints are 64 bits */
+#define MASK_LONG64       0x00000002   /* longs are 64 bits */
+#define MASK_SPLIT_ADDR           0x00000004   /* Address splitting is enabled.  */
+#define MASK_GPOPT        0x00000008   /* Optimize for global pointer */
+#define MASK_GAS          0x00000010   /* Gas used instead of MIPS as */
+#define MASK_NAME_REGS    0x00000020   /* Use MIPS s/w reg name convention */
+#define MASK_STATS        0x00000040   /* print statistics to stderr */
+#define MASK_MEMCPY       0x00000080   /* call memcpy instead of inline code*/
+#define MASK_SOFT_FLOAT           0x00000100   /* software floating point */
+#define MASK_FLOAT64      0x00000200   /* fp registers are 64 bits */
+#define MASK_ABICALLS     0x00000400   /* emit .abicalls/.cprestore/.cpload */
+#define MASK_HALF_PIC     0x00000800   /* Emit OSF-style pic refs to externs*/
+#define MASK_LONG_CALLS           0x00001000   /* Always call through a register */
+#define MASK_64BIT        0x00002000   /* Use 64 bit GP registers and insns */
+#define MASK_EMBEDDED_PIC  0x00004000  /* Generate embedded PIC code */
 #define MASK_EMBEDDED_DATA 0x00008000  /* Reduce RAM usage, not fast code */
-#define MASK_BIG_ENDIAN        0x00010000      /* Generate big endian code */
-#define MASK_SINGLE_FLOAT 0x00020000   /* Only single precision FPU.  */
-#define MASK_MAD       0x00040000      /* Generate mad/madu as on 4650.  */
-#define MASK_4300_MUL_FIX 0x00080000    /* Work-around early Vr4300 CPU bug */
-#define MASK_MIPS3900  0x00100000      /* like -mips1 only 3900 */
-#define MASK_MIPS16    0x01000000      /* Generate mips16 code */
-
-                                       /* Dummy switches used only in spec's*/
-#define MASK_MIPS_TFILE        0x00000000      /* flag for mips-tfile usage */
+#define MASK_BIG_ENDIAN           0x00010000   /* Generate big endian code */
+#define MASK_SINGLE_FLOAT  0x00020000  /* Only single precision FPU.  */
+#define MASK_MAD          0x00040000   /* Generate mad/madu as on 4650.  */
+#define MASK_4300_MUL_FIX  0x00080000   /* Work-around early Vr4300 CPU bug */
+#define MASK_MIPS16       0x00100000   /* Generate mips16 code */
+#define MASK_NO_CHECK_ZERO_DIV \
+                          0x00200000   /* divide by zero checking */
+#define MASK_CHECK_RANGE_DIV \
+                          0x00400000   /* divide result range checking */
+#define MASK_UNINIT_CONST_IN_RODATA \
+                          0x00800000   /* Store uninitialized
+                                          consts in rodata */
 
                                        /* Debug switches, not documented */
-#define MASK_DEBUG     0x40000000      /* Eliminate version # in .s file */
-#define MASK_DEBUG_A   0x20000000      /* don't allow <label>($reg) addrs */
-#define MASK_DEBUG_B   0x10000000      /* GO_IF_LEGITIMATE_ADDRESS debug */
-#define MASK_DEBUG_C   0x08000000      /* don't expand seq, etc. */
-#define MASK_DEBUG_D   0x04000000      /* don't do define_split's */
+#define MASK_DEBUG     0               /* unused */
+#define MASK_DEBUG_A   0               /* don't allow <label>($reg) addrs */
+#define MASK_DEBUG_B   0               /* GO_IF_LEGITIMATE_ADDRESS debug */
+#define MASK_DEBUG_C   0               /* don't expand seq, etc. */
+#define MASK_DEBUG_D   0               /* don't do define_split's */
 #define MASK_DEBUG_E   0               /* function_arg debug */
-#define MASK_DEBUG_F   0
+#define MASK_DEBUG_F   0               /* ??? */
 #define MASK_DEBUG_G   0               /* don't support 64 bit arithmetic */
 #define MASK_DEBUG_H   0               /* allow ints in FP registers */
 #define MASK_DEBUG_I   0               /* unused */
 
+                                       /* Dummy switches used only in specs */
+#define MASK_MIPS_TFILE        0               /* flag for mips-tfile usage */
+
                                        /* r4000 64 bit sizes */
 #define TARGET_INT64           (target_flags & MASK_INT64)
 #define TARGET_LONG64          (target_flags & MASK_LONG64)
@@ -357,15 +248,11 @@ extern void               mips_select_section ();
                                        /* Mips vs. GNU linker */
 #define TARGET_SPLIT_ADDRESSES (target_flags & MASK_SPLIT_ADDR)
 
-/* generate mips 3900 insns */
-#define TARGET_MIPS3900         (target_flags & MASK_MIPS3900)
-
                                        /* Mips vs. GNU assembler */
 #define TARGET_GAS             (target_flags & MASK_GAS)
-#define TARGET_UNIX_ASM                (!TARGET_GAS)
-#define TARGET_MIPS_AS         TARGET_UNIX_ASM
+#define TARGET_MIPS_AS         (!TARGET_GAS)
 
-                                       /* Debug Mode */
+                                       /* Debug Modes */
 #define TARGET_DEBUG_MODE      (target_flags & MASK_DEBUG)
 #define TARGET_DEBUG_A_MODE    (target_flags & MASK_DEBUG_A)
 #define TARGET_DEBUG_B_MODE    (target_flags & MASK_DEBUG_B)
@@ -411,6 +298,11 @@ extern void                mips_select_section ();
                                           fastest code.  */
 #define TARGET_EMBEDDED_DATA   (target_flags & MASK_EMBEDDED_DATA)
 
+                                       /* always store uninitialized const
+                                          variables in rodata, requires
+                                          TARGET_EMBEDDED_DATA. */
+#define TARGET_UNINIT_CONST_IN_RODATA  (target_flags & MASK_UNINIT_CONST_IN_RODATA)
+
                                        /* generate big endian code.  */
 #define TARGET_BIG_ENDIAN      (target_flags & MASK_BIG_ENDIAN)
 
@@ -421,6 +313,9 @@ extern void         mips_select_section ();
 
 #define TARGET_4300_MUL_FIX     (target_flags & MASK_4300_MUL_FIX)
 
+#define TARGET_NO_CHECK_ZERO_DIV (target_flags & MASK_NO_CHECK_ZERO_DIV)
+#define TARGET_CHECK_RANGE_DIV  (target_flags & MASK_CHECK_RANGE_DIV)
+
 /* This is true if we must enable the assembly language file switching
    code.  */
 
@@ -434,6 +329,19 @@ extern void                mips_select_section ();
                                        /* Generate mips16 code */
 #define TARGET_MIPS16          (target_flags & MASK_MIPS16)
 
+/* Architecture target defines.  */
+#define TARGET_MIPS3900             (mips_arch == PROCESSOR_R3900)
+#define TARGET_MIPS4000             (mips_arch == PROCESSOR_R4000)
+#define TARGET_MIPS4100             (mips_arch == PROCESSOR_R4100)
+#define TARGET_MIPS4300             (mips_arch == PROCESSOR_R4300)
+
+/* Scheduling target defines.  */
+#define TUNE_MIPS3000               (mips_tune == PROCESSOR_R3000)
+#define TUNE_MIPS3900               (mips_tune == PROCESSOR_R3900)
+#define TUNE_MIPS4000               (mips_tune == PROCESSOR_R4000)
+#define TUNE_MIPS5000               (mips_tune == PROCESSOR_R5000)
+#define TUNE_MIPS6000               (mips_tune == PROCESSOR_R6000)
+
 /* Macro to define tables used to set the flags.
    This is a list in braces of pairs in braces,
    each pair being { "NAME", VALUE }
@@ -442,63 +350,134 @@ extern void              mips_select_section ();
 
 #define TARGET_SWITCHES                                                        \
 {                                                                      \
-  {"int64",              MASK_INT64 | MASK_LONG64},                    \
-  {"long64",             MASK_LONG64},                                 \
-  {"split-addresses",    MASK_SPLIT_ADDR},                             \
-  {"no-split-addresses", -MASK_SPLIT_ADDR},                            \
-  {"mips-as",           -MASK_GAS},                                    \
-  {"gas",                MASK_GAS},                                    \
-  {"rnames",             MASK_NAME_REGS},                              \
-  {"no-rnames",                 -MASK_NAME_REGS},                              \
-  {"gpOPT",              MASK_GPOPT},                                  \
-  {"gpopt",              MASK_GPOPT},                                  \
-  {"no-gpOPT",          -MASK_GPOPT},                                  \
-  {"no-gpopt",          -MASK_GPOPT},                                  \
-  {"stats",              MASK_STATS},                                  \
-  {"no-stats",          -MASK_STATS},                                  \
-  {"memcpy",             MASK_MEMCPY},                                 \
-  {"no-memcpy",                 -MASK_MEMCPY},                                 \
-  {"mips-tfile",         MASK_MIPS_TFILE},                             \
-  {"no-mips-tfile",     -MASK_MIPS_TFILE},                             \
-  {"soft-float",         MASK_SOFT_FLOAT},                             \
-  {"hard-float",        -MASK_SOFT_FLOAT},                             \
-  {"fp64",               MASK_FLOAT64},                                \
-  {"fp32",              -MASK_FLOAT64},                                \
-  {"gp64",               MASK_64BIT},                                  \
-  {"gp32",              -MASK_64BIT},                                  \
-  {"abicalls",           MASK_ABICALLS},                               \
-  {"no-abicalls",       -MASK_ABICALLS},                               \
-  {"half-pic",           MASK_HALF_PIC},                               \
-  {"no-half-pic",       -MASK_HALF_PIC},                               \
-  {"long-calls",         MASK_LONG_CALLS},                             \
-  {"no-long-calls",     -MASK_LONG_CALLS},                             \
-  {"embedded-pic",       MASK_EMBEDDED_PIC},                           \
-  {"no-embedded-pic",   -MASK_EMBEDDED_PIC},                           \
-  {"embedded-data",      MASK_EMBEDDED_DATA},                          \
-  {"no-embedded-data",  -MASK_EMBEDDED_DATA},                          \
-  {"eb",                 MASK_BIG_ENDIAN},                             \
-  {"el",                -MASK_BIG_ENDIAN},                             \
-  {"single-float",       MASK_SINGLE_FLOAT},                           \
-  {"double-float",      -MASK_SINGLE_FLOAT},                           \
-  {"mad",                MASK_MAD},                                    \
-  {"no-mad",            -MASK_MAD},                                    \
-  {"fix4300",             MASK_4300_MUL_FIX},                          \
-  {"no-fix4300",         -MASK_4300_MUL_FIX},                          \
-  {"4650",               MASK_MAD | MASK_SINGLE_FLOAT},                \
-  {"3900",               MASK_MIPS3900},                               \
-  {"debug",              MASK_DEBUG},                                  \
-  {"debuga",             MASK_DEBUG_A},                                \
-  {"debugb",             MASK_DEBUG_B},                                \
-  {"debugc",             MASK_DEBUG_C},                                \
-  {"debugd",             MASK_DEBUG_D},                                \
-  {"debuge",             MASK_DEBUG_E},                                \
-  {"debugf",             MASK_DEBUG_F},                                \
-  {"debugg",             MASK_DEBUG_G},                                \
-  {"debugh",             MASK_DEBUG_H},                                \
-  {"debugi",             MASK_DEBUG_I},                                \
+  {"no-crt0",          0,                                               \
+     N_("No default crt0.o") },                                                \
+  {"int64",              MASK_INT64 | MASK_LONG64,                     \
+     N_("Use 64-bit int type")},                                       \
+  {"long64",             MASK_LONG64,                                  \
+     N_("Use 64-bit long type")},                                      \
+  {"long32",            -(MASK_LONG64 | MASK_INT64),                   \
+     N_("Use 32-bit long type")},                                      \
+  {"split-addresses",    MASK_SPLIT_ADDR,                              \
+     N_("Optimize lui/addiu address loads")},                          \
+  {"no-split-addresses", -MASK_SPLIT_ADDR,                             \
+     N_("Don't optimize lui/addiu address loads")},                    \
+  {"mips-as",           -MASK_GAS,                                     \
+     N_("Use MIPS as")},                                               \
+  {"gas",                MASK_GAS,                                     \
+     N_("Use GNU as")},                                                        \
+  {"rnames",             MASK_NAME_REGS,                               \
+     N_("Use symbolic register names")},                               \
+  {"no-rnames",                 -MASK_NAME_REGS,                               \
+     N_("Don't use symbolic register names")},                         \
+  {"gpOPT",              MASK_GPOPT,                                   \
+     N_("Use GP relative sdata/sbss sections")},                       \
+  {"gpopt",              MASK_GPOPT,                                   \
+     N_("Use GP relative sdata/sbss sections")},                       \
+  {"no-gpOPT",          -MASK_GPOPT,                                   \
+     N_("Don't use GP relative sdata/sbss sections")},                 \
+  {"no-gpopt",          -MASK_GPOPT,                                   \
+     N_("Don't use GP relative sdata/sbss sections")},                 \
+  {"stats",              MASK_STATS,                                   \
+     N_("Output compiler statistics")},                                        \
+  {"no-stats",          -MASK_STATS,                                   \
+     N_("Don't output compiler statistics")},                          \
+  {"memcpy",             MASK_MEMCPY,                                  \
+     N_("Don't optimize block moves")},                                        \
+  {"no-memcpy",                 -MASK_MEMCPY,                                  \
+     N_("Optimize block moves")},                                      \
+  {"mips-tfile",         MASK_MIPS_TFILE,                              \
+     N_("Use mips-tfile asm postpass")},                               \
+  {"no-mips-tfile",     -MASK_MIPS_TFILE,                              \
+     N_("Don't use mips-tfile asm postpass")},                         \
+  {"soft-float",         MASK_SOFT_FLOAT,                              \
+     N_("Use software floating point")},                               \
+  {"hard-float",        -MASK_SOFT_FLOAT,                              \
+     N_("Use hardware floating point")},                               \
+  {"fp64",               MASK_FLOAT64,                                 \
+     N_("Use 64-bit FP registers")},                                   \
+  {"fp32",              -MASK_FLOAT64,                                 \
+     N_("Use 32-bit FP registers")},                                   \
+  {"gp64",               MASK_64BIT,                                   \
+     N_("Use 64-bit general registers")},                              \
+  {"gp32",              -MASK_64BIT,                                   \
+     N_("Use 32-bit general registers")},                              \
+  {"abicalls",           MASK_ABICALLS,                                \
+     N_("Use Irix PIC")},                                              \
+  {"no-abicalls",       -MASK_ABICALLS,                                \
+     N_("Don't use Irix PIC")},                                                \
+  {"half-pic",           MASK_HALF_PIC,                                \
+     N_("Use OSF PIC")},                                               \
+  {"no-half-pic",       -MASK_HALF_PIC,                                \
+     N_("Don't use OSF PIC")},                                         \
+  {"long-calls",         MASK_LONG_CALLS,                              \
+     N_("Use indirect calls")},                                                \
+  {"no-long-calls",     -MASK_LONG_CALLS,                              \
+     N_("Don't use indirect calls")},                                  \
+  {"embedded-pic",       MASK_EMBEDDED_PIC,                            \
+     N_("Use embedded PIC")},                                          \
+  {"no-embedded-pic",   -MASK_EMBEDDED_PIC,                            \
+     N_("Don't use embedded PIC")},                                    \
+  {"embedded-data",      MASK_EMBEDDED_DATA,                           \
+     N_("Use ROM instead of RAM")},                                    \
+  {"no-embedded-data",  -MASK_EMBEDDED_DATA,                           \
+     N_("Don't use ROM instead of RAM")},                              \
+  {"uninit-const-in-rodata", MASK_UNINIT_CONST_IN_RODATA,              \
+     N_("Put uninitialized constants in ROM (needs -membedded-data)")},        \
+  {"no-uninit-const-in-rodata", -MASK_UNINIT_CONST_IN_RODATA,          \
+     N_("Don't put uninitialized constants in ROM")},                  \
+  {"eb",                 MASK_BIG_ENDIAN,                              \
+     N_("Use big-endian byte order")},                                 \
+  {"el",                -MASK_BIG_ENDIAN,                              \
+     N_("Use little-endian byte order")},                              \
+  {"single-float",       MASK_SINGLE_FLOAT,                            \
+     N_("Use single (32-bit) FP only")},                               \
+  {"double-float",      -MASK_SINGLE_FLOAT,                            \
+     N_("Don't use single (32-bit) FP only")},                         \
+  {"mad",                MASK_MAD,                                     \
+     N_("Use multiply accumulate")},                                   \
+  {"no-mad",            -MASK_MAD,                                     \
+     N_("Don't use multiply accumulate")},                             \
+  {"fix4300",             MASK_4300_MUL_FIX,                           \
+     N_("Work around early 4300 hardware bug")},                       \
+  {"no-fix4300",         -MASK_4300_MUL_FIX,                           \
+     N_("Don't work around early 4300 hardware bug")},                 \
+  {"3900",               0,                                            \
+     N_("Optimize for 3900")},                                         \
+  {"4650",               0,                                            \
+     N_("Optimize for 4650")},                                         \
+  {"check-zero-division",-MASK_NO_CHECK_ZERO_DIV,                      \
+     N_("Trap on integer divide by zero")},                            \
+  {"no-check-zero-division", MASK_NO_CHECK_ZERO_DIV,                   \
+     N_("Don't trap on integer divide by zero")},                      \
+  {"check-range-division",MASK_CHECK_RANGE_DIV,                                \
+     N_("Trap on integer divide overflow")},                           \
+  {"no-check-range-division",-MASK_CHECK_RANGE_DIV,                    \
+     N_("Don't trap on integer divide overflow")},                     \
+  {"debug",              MASK_DEBUG,                                   \
+     NULL},                                                            \
+  {"debuga",             MASK_DEBUG_A,                                 \
+     NULL},                                                            \
+  {"debugb",             MASK_DEBUG_B,                                 \
+     NULL},                                                            \
+  {"debugc",             MASK_DEBUG_C,                                 \
+     NULL},                                                            \
+  {"debugd",             MASK_DEBUG_D,                                 \
+     NULL},                                                            \
+  {"debuge",             MASK_DEBUG_E,                                 \
+     NULL},                                                            \
+  {"debugf",             MASK_DEBUG_F,                                 \
+     NULL},                                                            \
+  {"debugg",             MASK_DEBUG_G,                                 \
+     NULL},                                                            \
+  {"debugh",             MASK_DEBUG_H,                                 \
+     NULL},                                                            \
+  {"debugi",             MASK_DEBUG_I,                                 \
+     NULL},                                                            \
   {"",                   (TARGET_DEFAULT                               \
                           | TARGET_CPU_DEFAULT                         \
-                          | TARGET_ENDIAN_DEFAULT)}                    \
+                          | TARGET_ENDIAN_DEFAULT),                    \
+     NULL},                                                            \
 }
 
 /* Default target_flags if no switches are specified  */
@@ -519,12 +498,50 @@ extern void               mips_select_section ();
 #endif
 #endif
 
-#ifndef MULTILIB_DEFAULTS
+#ifndef MIPS_ISA_DEFAULT
+#define MIPS_ISA_DEFAULT 1
+#endif
+
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+/* Make this compile time constant for libgcc2 */
+#ifdef __mips64
+#define TARGET_64BIT           1
+#else
+#define TARGET_64BIT           0
+#endif
+#endif /* IN_LIBGCC2 */
+
+#ifndef MULTILIB_ENDIAN_DEFAULT
 #if TARGET_ENDIAN_DEFAULT == 0
-#define MULTILIB_DEFAULTS { "EL", "mips1" }
+#define MULTILIB_ENDIAN_DEFAULT "EL"
 #else
-#define MULTILIB_DEFAULTS { "EB", "mips1" }
+#define MULTILIB_ENDIAN_DEFAULT "EB"
+#endif
+#endif
+
+#ifndef MULTILIB_ISA_DEFAULT
+#  if MIPS_ISA_DEFAULT == 1
+#    define MULTILIB_ISA_DEFAULT "mips1"
+#  else
+#    if MIPS_ISA_DEFAULT == 2
+#      define MULTILIB_ISA_DEFAULT "mips2"
+#    else
+#      if MIPS_ISA_DEFAULT == 3
+#        define MULTILIB_ISA_DEFAULT "mips3"
+#      else
+#        if MIPS_ISA_DEFAULT == 4
+#          define MULTILIB_ISA_DEFAULT "mips4"
+#        else
+#          define MULTILIB_ISA_DEFAULT "mips1"
+#        endif
+#      endif
+#    endif
+#  endif
 #endif
+
+#ifndef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT }
 #endif
 
 /* We must pass -EL to the linker by default for little endian embedded
@@ -532,11 +549,11 @@ extern void               mips_select_section ();
    linker will default to using big-endian output files.  The OUTPUT_FORMAT
    line must be in the linker script, otherwise -EB/-EL will not work.  */
 
-#ifndef LINKER_ENDIAN_SPEC
+#ifndef ENDIAN_SPEC
 #if TARGET_ENDIAN_DEFAULT == 0
-#define LINKER_ENDIAN_SPEC "%{!EB:%{!meb:-EL}}"
+#define ENDIAN_SPEC "%{!EB:%{!meb:-EL}} %{EL} %{EB}"
 #else
-#define LINKER_ENDIAN_SPEC ""
+#define ENDIAN_SPEC "%{!EL:%{!mel:-EB}} %{EB} %{EL}"
 #endif
 #endif
 
@@ -545,7 +562,7 @@ extern void         mips_select_section ();
    initializer with a subgrouping for each command option.
 
    Each subgrouping contains a string constant, that defines the
-   fixed part of the option name, and the address of a variable. 
+   fixed part of the option name, and the address of a variable.
    The variable, type `char *', is set to the variable part of the
    given option if the fixed part matches.  The actual option name
    is made by appending `-m' to the specified name.
@@ -560,16 +577,26 @@ extern void               mips_select_section ();
 #define TARGET_OPTIONS                                                 \
 {                                                                      \
   SUBTARGET_TARGET_OPTIONS                                             \
-  { "cpu=",    &mips_cpu_string        },                              \
-  { "ips",     &mips_isa_string        },                              \
-  { "entry",   &mips_entry_string      },                              \
-  { "no-mips16", &mips_no_mips16_string        }                               \
+  { "cpu=",    &mips_cpu_string,                                       \
+      N_("Specify CPU for scheduling purposes")},                      \
+  { "tune=",    &mips_tune_string,                                   \
+      N_("Specify CPU for scheduling purposes")},                       \
+  { "arch=",    &mips_arch_string,                                      \
+      N_("Specify CPU for code generation purposes")},                  \
+  { "ips",     &mips_isa_string,                                       \
+      N_("Specify a Standard MIPS ISA")},                              \
+  { "entry",   &mips_entry_string,                                     \
+      N_("Use mips16 entry/exit psuedo ops")},                         \
+  { "no-mips16", &mips_no_mips16_string,                               \
+      N_("Don't use MIPS16 instructions")},                            \
+  { "explicit-type-size", &mips_explicit_type_size_string,             \
+      NULL},                                                           \
 }
 
 /* This is meant to be redefined in the host dependent files.  */
 #define SUBTARGET_TARGET_OPTIONS
 
-#define GENERATE_BRANCHLIKELY  (!TARGET_MIPS16 && (TARGET_MIPS3900 || (mips_isa >= 2)))
+#define GENERATE_BRANCHLIKELY  (!TARGET_MIPS16 && ISA_HAS_BRANCHLIKELY)
 
 /* Generate three-operand multiply instructions for both SImode and DImode.  */
 #define GENERATE_MULT3         (TARGET_MIPS3900                                \
@@ -579,7 +606,45 @@ extern void                mips_select_section ();
    depending on the instruction set architecture level.  */
 
 #define BRANCH_LIKELY_P()      GENERATE_BRANCHLIKELY
-#define HAVE_SQRT_P()          (mips_isa >= 2)
+#define HAVE_SQRT_P()          (mips_isa != 1)
+
+/* ISA has instructions for managing 64 bit fp and gp regs (eg. mips3). */
+#define ISA_HAS_64BIT_REGS     (mips_isa == 3 || mips_isa == 4         \
+                                )
+
+/* ISA has branch likely instructions (eg. mips2). */
+/* Disable branchlikely for tx39 until compare rewrite.  They haven't
+   been generated up to this point.  */
+#define ISA_HAS_BRANCHLIKELY   (mips_isa != 1                          \
+                                /* || TARGET_MIPS3900 */)
+
+/* ISA has the conditional move instructions introduced in mips4. */
+#define ISA_HAS_CONDMOVE        (mips_isa == 4                         \
+                                )
+
+/* ISA has just the integer condition move instructions (movn,movz) */
+#define ISA_HAS_INT_CONDMOVE     0
+
+
+
+/* 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            (mips_isa == 4                          \
+                               )
+
+
+/* This is a catch all for the other new mips4 instructions: indexed load and
+   indexed prefetch instructions, the FP madd,msub,nmadd, and nmsub instructions,
+   and the FP recip and recip sqrt instructions */
+#define ISA_HAS_FP4             (mips_isa == 4                         \
+                               )
+
+/* ISA has conditional trap instructions.  */
+#define ISA_HAS_COND_TRAP      (mips_isa >= 2)
+
+/* ISA has nmadd and nmsub instructions.  */
+#define ISA_HAS_NMADD_NMSUB    (mips_isa == 4                          \
+                               )
 
 /* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or
    -mips2 sets -mfp32 and -mgp32.  This can be overridden by an explicit
@@ -649,7 +714,7 @@ do                                                                  \
        for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)       \
          fixed_regs[regno] = call_used_regs[regno] = 1;                \
       }                                                                        \
-    else if (mips_isa < 4)                                             \
+    else if (! ISA_HAS_8CC)                                            \
       {                                                                        \
        int regno;                                                      \
                                                                        \
@@ -725,7 +790,7 @@ while (0)
 #ifndef CPP_PREDEFINES
 #define CPP_PREDEFINES "-Dmips -Dunix -Dhost_mips -DMIPSEB -DR3000 -DSYSTYPE_BSD43 \
 -D_mips -D_unix -D_host_mips -D_MIPSEB -D_R3000 -D_SYSTYPE_BSD43 \
--Asystem(unix) -Asystem(bsd) -Acpu(mips) -Amachine(mips)"
+-Asystem=unix -Asystem=bsd -Acpu=mips -Amachine=mips"
 #endif
 
 /* Assembler specs.  */
@@ -748,7 +813,7 @@ while (0)
 /* GAS_ASM_SPEC is passed when using gas, rather than the MIPS
    assembler.  */
 
-#define GAS_ASM_SPEC "%{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v}"
+#define GAS_ASM_SPEC "%{march=*} %{mtune=*} %{mcpu=*} %{m4650} %{mmad:-m4650} %{m3900} %{v} %{mgp32} %{mgp64}"
 
 /* TARGET_ASM_SPEC is used to select either MIPS_AS_ASM_SPEC or
    GAS_ASM_SPEC as the default, depending upon the value of
@@ -798,11 +863,12 @@ while (0)
 /* ASM_SPEC is the set of arguments to pass to the assembler.  */
 
 #define ASM_SPEC "\
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
+%{!membedded-pic:%{G*}} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
 %{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
 %(subtarget_asm_optimizing_spec) \
 %(subtarget_asm_debugging_spec) \
 %{membedded-pic} \
+%{mfix7000} \
 %{mabi=32:-32}%{mabi=o32:-32}%{mabi=n32:-n32}%{mabi=64:-64}%{mabi=n64:-64} \
 %(target_asm_spec) \
 %(subtarget_asm_spec)"
@@ -852,9 +918,9 @@ while (0)
 
 #ifndef LINK_SPEC
 #define LINK_SPEC "\
-%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
-%{bestGnum} %{shared} %{non_shared} \
-%(linker_endian_spec)"
+%(endian_spec) \
+%{G*} %{mips1} %{mips2} %{mips3} %{mips4} \
+%{bestGnum} %{shared} %{non_shared}"
 #endif /* LINK_SPEC defined */
 
 /* Specs for the compiler proper */
@@ -865,6 +931,16 @@ while (0)
 #define SUBTARGET_CC1_SPEC ""
 #endif
 
+/* Deal with historic options.  */
+#ifndef CC1_CPU_SPEC
+#define CC1_CPU_SPEC "\
+%{!mcpu*: \
+%{m3900:-march=r3900 -mips1 -mfp32 -mgp32 \
+%n`-m3900' is deprecated. Use `-march=r3900' instead.\n} \
+%{m4650:-march=r4650 -mmad -msingle-float \
+%n`-m4650' is deprecated. Use `-march=r4650' instead.\n}}"
+#endif
+
 /* CC1_SPEC is the set of arguments to pass to the compiler proper.  */
 
 #ifndef CC1_SPEC
@@ -875,15 +951,15 @@ while (0)
 %{mips4:%{!msingle-float:%{!m4650:-mfp64}} -mgp64} \
 %{mfp64:%{msingle-float:%emay not use both -mfp64 and -msingle-float}} \
 %{mfp64:%{m4650:%emay not use both -mfp64 and -m4650}} \
-%{m4650:-mcpu=r4650} \
-%{m3900:-mips1 -mcpu=r3900 -mfp32 -mgp32} \
+%{mint64|mlong64|mlong32:-mexplicit-type-size }\
 %{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \
 %{pic-none:   -mno-half-pic} \
 %{pic-lib:    -mhalf-pic} \
 %{pic-extern: -mhalf-pic} \
 %{pic-calls:  -mhalf-pic} \
 %{save-temps: } \
-%(subtarget_cc1_spec) "
+%(subtarget_cc1_spec) \
+%(cc1_cpu_spec)"
 #endif
 
 /* Preprocessor specs.  */
@@ -893,7 +969,7 @@ while (0)
 
 #ifndef SUBTARGET_CPP_SIZE_SPEC
 #define SUBTARGET_CPP_SIZE_SPEC "\
-%{mlong64:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int} \
+%{mlong64:%{!mips1:%{!mips2:-D__SIZE_TYPE__=long\\ unsigned\\ int -D__PTRDIFF_TYPE__=long\\ int}}} \
 %{!mlong64:-D__SIZE_TYPE__=unsigned\\ int -D__PTRDIFF_TYPE__=int}"
 #endif
 
@@ -907,23 +983,25 @@ while (0)
    correctly.  Similarly for 64bit ints and __INT_MAX__.  */
 #ifndef LONG_MAX_SPEC
 #if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_LONG64)
-#define LONG_MAX_SPEC "%{!mno-long64:-D__LONG_MAX__=9223372036854775807L}"
+#define LONG_MAX_SPEC "%{!mlong32:-D__LONG_MAX__=9223372036854775807L}"
 #else
 #define LONG_MAX_SPEC "%{mlong64:-D__LONG_MAX__=9223372036854775807L}"
 #endif
 #endif
 
+/* For C++ we need to ensure that _LANGUAGE_C_PLUS_PLUS is defined independent
+   of the source file extension.  */
+#define CPLUSPLUS_CPP_SPEC "\
+-D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS \
+%(cpp) \
+"
 /* CPP_SPEC is the set of arguments to pass to the preprocessor.  */
 
 #ifndef CPP_SPEC
 #define CPP_SPEC "\
-%{.cc: -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.cxx:        -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
-%{.C:  -D__LANGUAGE_C_PLUS_PLUS -D_LANGUAGE_C_PLUS_PLUS} \
 %{.m:  -D__LANGUAGE_OBJECTIVE_C -D_LANGUAGE_OBJECTIVE_C -D__LANGUAGE_C -D_LANGUAGE_C} \
-%{.S:  -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{.s:  -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
-%{!.S: %{!.s: %{!.cc: %{!.cxx: %{!.C: %{!.m: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}} \
+%{.S|.s: -D__LANGUAGE_ASSEMBLY -D_LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
+%{!.S: %{!.s: %{!.cc: %{!.cxx: %{!.cpp: %{!.cp: %{!.c++: %{!.C: %{!.m: -D__LANGUAGE_C -D_LANGUAGE_C %{!ansi:-DLANGUAGE_C}}}}}}}}}} \
 %(subtarget_cpp_size_spec) \
 %{mips3:-U__mips -D__mips=3 -D__mips64} \
 %{mips4:-U__mips -D__mips=4 -D__mips64} \
@@ -951,17 +1029,18 @@ while (0)
 
 #define EXTRA_SPECS                                                    \
   { "subtarget_cc1_spec", SUBTARGET_CC1_SPEC },                                \
+  { "cc1_cpu_spec", CC1_CPU_SPEC},                                      \
   { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },                                \
   { "subtarget_cpp_size_spec", SUBTARGET_CPP_SIZE_SPEC },              \
   { "long_max_spec", LONG_MAX_SPEC },                                  \
   { "mips_as_asm_spec", MIPS_AS_ASM_SPEC },                            \
   { "gas_asm_spec", GAS_ASM_SPEC },                                    \
   { "target_asm_spec", TARGET_ASM_SPEC },                              \
-  { "subtarget_mips_as_asm_spec", SUBTARGET_MIPS_AS_ASM_SPEC },                \
+  { "subtarget_mips_as_asm_spec", SUBTARGET_MIPS_AS_ASM_SPEC },        \
   { "subtarget_asm_optimizing_spec", SUBTARGET_ASM_OPTIMIZING_SPEC },  \
   { "subtarget_asm_debugging_spec", SUBTARGET_ASM_DEBUGGING_SPEC },    \
   { "subtarget_asm_spec", SUBTARGET_ASM_SPEC },                                \
-  { "linker_endian_spec", LINKER_ENDIAN_SPEC },                                \
+  { "endian_spec", ENDIAN_SPEC },                                      \
   SUBTARGET_EXTRA_SPECS
 
 #ifndef SUBTARGET_EXTRA_SPECS
@@ -1014,9 +1093,9 @@ while (0)
    that the MIPS assembler does not choke.  The mips-tfile program
    will correctly put the stab into the object file.  */
 
-#define ASM_STABS_OP   ((TARGET_GAS) ? ".stabs" : " #.stabs")
-#define ASM_STABN_OP   ((TARGET_GAS) ? ".stabn" : " #.stabn")
-#define ASM_STABD_OP   ((TARGET_GAS) ? ".stabd" : " #.stabd")
+#define ASM_STABS_OP   ((TARGET_GAS) ? "\t.stabs\t" : " #.stabs\t")
+#define ASM_STABN_OP   ((TARGET_GAS) ? "\t.stabn\t" : " #.stabn\t")
+#define ASM_STABD_OP   ((TARGET_GAS) ? "\t.stabd\t" : " #.stabd\t")
 
 /* Local compiler-generated symbols must have a prefix that the assembler
    understands.   By default, this is $, although some targets (e.g.,
@@ -1041,6 +1120,7 @@ while (0)
 
 /* On Sun 4, this limit is 2048.  We use 1500 to be safe,
    since the length can run past this up to a continuation point.  */
+#undef DBX_CONTIN_LENGTH
 #define DBX_CONTIN_LENGTH 1500
 
 /* How to renumber registers for dbx and gdb. */
@@ -1057,7 +1137,16 @@ while (0)
 #define DWARF_FRAME_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)
+#define INCOMING_RETURN_ADDR_RTX  gen_rtx_REG (VOIDmode, GP_REG_FIRST + 31)
+
+/* Describe how we implement __builtin_eh_return.  */
+#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
+#define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
+
+/* Offsets recorded in opcodes are a multiple of this alignment factor.
+   The default for this in 64-bit mode is 8, which causes problems with
+   SFmode register saves.  */
+#define DWARF_CIE_DATA_ALIGNMENT 4
 
 /* Overrides for the COFF debug format.  */
 #define PUT_SDB_SCL(a)                                 \
@@ -1331,7 +1420,7 @@ do {                                                      \
 /* Width in bits of a pointer.
    See also the macro `Pmode' defined below.  */
 #ifndef POINTER_SIZE
-#define POINTER_SIZE (TARGET_LONG64 ? 64 : 32)
+#define POINTER_SIZE (Pmode == DImode ? 64 : 32)
 #endif
 
 /* Allocation boundary (in *bits*) for storing pointers in memory.  */
@@ -1393,9 +1482,7 @@ do {                                                      \
 
 #define CONSTANT_ALIGNMENT(EXP, ALIGN)                                 \
   ((TREE_CODE (EXP) == STRING_CST  || TREE_CODE (EXP) == CONSTRUCTOR)  \
-   && (ALIGN) < BITS_PER_WORD                                          \
-       ? BITS_PER_WORD                                                 \
-       : (ALIGN))
+   && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
 
 /* If defined, a C expression to compute the alignment for a static
    variable.  TYPE is the data type, and ALIGN is the alignment that
@@ -1416,12 +1503,17 @@ do {                                                    \
        || TREE_CODE (TYPE) == UNION_TYPE                               \
        || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
 
+
+/* Force right-alignment for small varargs in 32 bit little_endian mode */
+
+#define PAD_VARARGS_DOWN (TARGET_64BIT ? BYTES_BIG_ENDIAN : !BYTES_BIG_ENDIAN)
+
 /* Define this macro if an argument declared as `char' or `short' in a
    prototype should actually be passed as an `int'.  In addition to
    avoiding errors in certain cases of mismatch, it also makes for
    better code on certain machines. */
 
-#define PROMOTE_PROTOTYPES
+#define PROMOTE_PROTOTYPES 1
 
 /* Define if operations between registers always perform the operation
    on the full register even if a narrower mode is specified.  */
@@ -1430,11 +1522,16 @@ do {                                                    \
 /* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
    will either zero-extend or sign-extend.  The value of this macro should
    be the code that says which one of the two operations is implicitly
-   done, NIL if none.  */
-#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
+   done, NIL if none.
+
+   When in 64 bit mode, mips_move_1word will sign extend SImode and CCmode
+   moves.  All other referces are zero extended.  */
+#define LOAD_EXTEND_OP(MODE) \
+  (TARGET_64BIT && ((MODE) == SImode || (MODE) == CCmode) \
+   ? SIGN_EXTEND : ZERO_EXTEND)
 
 /* Define this macro if it is advisable to hold scalars in registers
-   in a wider mode than that declared by the program.  In such cases, 
+   in a wider mode than that declared by the program.  In such cases,
    the value is constrained to be within the bounds of the declared
    type, but kept valid in the wider mode.  The signedness of the
    extension may differ from that of the type.
@@ -1544,12 +1641,16 @@ do {                                                    \
    should be used instead.  */
 #define FPSW_REGNUM    ST_REG_FIRST
 
-#define GP_REG_P(REGNO) ((unsigned) ((REGNO) - GP_REG_FIRST) < GP_REG_NUM)
+#define GP_REG_P(REGNO)        \
+  ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
 #define M16_REG_P(REGNO) \
   (((REGNO) >= 2 && (REGNO) <= 7) || (REGNO) == 16 || (REGNO) == 17)
-#define FP_REG_P(REGNO) ((unsigned) ((REGNO) - FP_REG_FIRST) < FP_REG_NUM)
-#define MD_REG_P(REGNO) ((unsigned) ((REGNO) - MD_REG_FIRST) < MD_REG_NUM)
-#define ST_REG_P(REGNO) ((unsigned) ((REGNO) - ST_REG_FIRST) < ST_REG_NUM)
+#define FP_REG_P(REGNO)  \
+  ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
+#define MD_REG_P(REGNO) \
+  ((unsigned int) ((int) (REGNO) - MD_REG_FIRST) < MD_REG_NUM)
+#define ST_REG_P(REGNO) \
+  ((unsigned int) ((int) (REGNO) - ST_REG_FIRST) < ST_REG_NUM)
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
@@ -1607,6 +1708,9 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
    a fixed register, and will not be used for anything else.  */
 #define FRAME_POINTER_REGNUM (GP_REG_FIRST + 1)
 
+/* Temporary scratch register for use by the assembler.  */
+#define ASSEMBLER_SCRATCH_REGNUM (GP_REG_FIRST + 1)
+
 /* $30 is not available on the mips16, so we use $17 as the frame
    pointer.  */
 #define HARD_FRAME_POINTER_REGNUM \
@@ -1659,7 +1763,7 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
 
 /* The register number of the register used to address a table of
    static data addresses in memory.  In some cases this register is
-   defined by a processor's "application binary interface" (ABI). 
+   defined by a processor's "application binary interface" (ABI).
    When this macro is defined, RTL is generated for this register
    once, as with the stack pointer and frame pointer registers.  If
    this macro is not defined, it is up to the machine-dependent
@@ -1855,7 +1959,7 @@ extern enum reg_class mips_regno_to_class[];
 
 extern enum reg_class mips_char_to_class[];
 
-#define REG_CLASS_FROM_LETTER(C) mips_char_to_class[ (C) ]
+#define REG_CLASS_FROM_LETTER(C) mips_char_to_class[(unsigned char)(C)]
 
 /* The letters I, J, K, L, M, N, O, and P in a register constraint
    string can be used to stand for particular ranges of immediate
@@ -1917,7 +2021,7 @@ extern enum reg_class mips_char_to_class[];
    && (VALUE) == CONST0_RTX (GET_MODE (VALUE)))
 
 /* Letters in the range `Q' through `U' may be defined in a
-   machine-dependent fashion to stand for arbitrary operand types. 
+   machine-dependent fashion to stand for arbitrary operand types.
    The machine description macro `EXTRA_CONSTRAINT' is passed the
    operand as its first argument and the constraint letter as its
    second operand.
@@ -1986,10 +2090,6 @@ extern enum reg_class mips_char_to_class[];
 #define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X)                  \
   mips_secondary_reload_class (CLASS, MODE, X, 0)
 
-/* Not declared above, with the other functions, because enum
-   reg_class is not declared yet.  */
-extern enum reg_class  mips_secondary_reload_class ();
-
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.  */
 
@@ -2003,19 +2103,16 @@ extern enum reg_class   mips_secondary_reload_class ();
       : 2 * CLASS_UNITS (MODE, 8))                                     \
    : CLASS_UNITS (MODE, UNITS_PER_WORD))
 
-/* If defined, this is a C expression whose value should be
-   nonzero if the insn INSN has the effect of mysteriously
-   clobbering the contents of hard register number REGNO.  By
-   "mysterious" we mean that the insn's RTL expression doesn't
-   describe such an effect.
+/* If defined, gives a class of registers that cannot be used as the
+   operand of a SUBREG that changes the mode of the object illegally.  */
 
-   If this macro is not defined, it means that no insn clobbers
-   registers mysteriously.  This is the usual situation; all else
-   being equal, it is best for the RTL expression to show all the
-   activity.  */
+#define CLASS_CANNOT_CHANGE_MODE \
+  (TARGET_FLOAT64 && ! TARGET_64BIT ? FP_REGS : NO_REGS)
 
-/* #define INSN_CLOBBERS_REGNO_P(INSN, REGNO) */
+/* Defines illegal mode changes for CLASS_CANNOT_CHANGE_MODE.  */
 
+#define CLASS_CANNOT_CHANGE_MODE_P(FROM,TO) \
+  (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO))
 \f
 /* Stack layout; function entry, exit and calling.  */
 
@@ -2076,7 +2173,7 @@ extern enum reg_class     mips_secondary_reload_class ();
 
 #define RETURN_ADDR_RTX(count, frame)                  \
   ((count == 0)                                                \
-   ? gen_rtx (MEM, Pmode, gen_rtx (REG, Pmode, RETURN_ADDRESS_POINTER_REGNUM))\
+   ? gen_rtx_MEM (Pmode, gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM))\
    : (rtx) 0)
 
 /* Structure to be filled in by compute_frame_size with register
@@ -2116,7 +2213,7 @@ extern struct mips_frame_info current_frame_info;
 
    On some machines, the position of the argument pointer is not
    known until the compilation is completed.  In such a case, a
-   separate hard register must be used for the argument pointer. 
+   separate hard register must be used for the argument pointer.
    This register can be eliminated by replacing it with either the
    frame pointer or the argument pointer, depending on whether or not
    the frame pointer has been eliminated.
@@ -2140,6 +2237,7 @@ extern struct mips_frame_info current_frame_info;
  { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM},               \
  { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 30},                  \
  { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 17},                  \
+ { RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 31},                  \
  { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM},                                \
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30},                           \
  { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
@@ -2165,11 +2263,14 @@ extern struct mips_frame_info current_frame_info;
    */
 
 #define CAN_ELIMINATE(FROM, TO)                                                \
-  ((TO) == HARD_FRAME_POINTER_REGNUM                                   \
+  (((FROM) == RETURN_ADDRESS_POINTER_REGNUM && (! leaf_function_p ()   \
+   || (TO == GP_REG_FIRST + 31 && leaf_function_p)))                           \
+  || ((FROM) != RETURN_ADDRESS_POINTER_REGNUM                          \
+   && ((TO) == HARD_FRAME_POINTER_REGNUM                               \
    || ((TO) == STACK_POINTER_REGNUM && ! frame_pointer_needed          \
        && ! (TARGET_MIPS16 && TARGET_64BIT)                             \
        && (! TARGET_MIPS16                                             \
-          || compute_frame_size (get_frame_size ()) < 32768)))
+          || compute_frame_size (get_frame_size ()) < 32768)))))
 
 /* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'.  It
    specifies the initial difference between the specified pair of
@@ -2187,20 +2288,28 @@ extern struct mips_frame_info current_frame_info;
           && (TO) == HARD_FRAME_POINTER_REGNUM)                         \
     (OFFSET) = (current_frame_info.total_size                           \
                - current_function_outgoing_args_size                    \
-               - ((mips_abi != ABI_32 && mips_abi != ABI_EABI)          \
+               - ((mips_abi != ABI_32                                   \
+                   && mips_abi != ABI_O64                               \
+                   && mips_abi != ABI_EABI)                             \
                   ? current_function_pretend_args_size                  \
                   : 0));                                                \
   else if ((FROM) == ARG_POINTER_REGNUM)                                \
     (OFFSET) = (current_frame_info.total_size                           \
-               - ((mips_abi != ABI_32 && mips_abi != ABI_EABI)          \
+               - ((mips_abi != ABI_32                                   \
+                   && mips_abi != ABI_O64                               \
+                   && mips_abi != ABI_EABI)                             \
                   ? current_function_pretend_args_size                  \
                   : 0));                                                \
   /* Some ABIs store 64 bits to the stack, but Pmode is 32 bits,        \
      so we must add 4 bytes to the offset to get the right value.  */   \
   else if ((FROM) == RETURN_ADDRESS_POINTER_REGNUM)                     \
-    (OFFSET) = current_frame_info.gp_sp_offset                          \
+  {                                                                     \
+   if (leaf_function_p ())                                              \
+      (OFFSET) = 0;                                                     \
+   else (OFFSET) = current_frame_info.gp_sp_offset                      \
               + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))      \
                  * (BYTES_BIG_ENDIAN != 0));                            \
+  }                                                                     \
 }
 
 /* If we generate an insn to push BYTES bytes,
@@ -2217,7 +2326,7 @@ extern struct mips_frame_info current_frame_info;
 
    It is not proper to define both `PUSH_ROUNDING' and
    `ACCUMULATE_OUTGOING_ARGS'.  */
-#define ACCUMULATE_OUTGOING_ARGS
+#define ACCUMULATE_OUTGOING_ARGS 1
 
 /* Offset from the argument pointer register to the first argument's
    address.  On some machines it may depend on the data type of the
@@ -2256,9 +2365,9 @@ extern struct mips_frame_info current_frame_info;
   ((MAX_ARGS_IN_REGISTERS*UNITS_PER_WORD) - FIRST_PARM_OFFSET (FNDECL))
 
 /* Define this if it is the responsibility of the caller to
-   allocate the area reserved for arguments passed in registers. 
+   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 
+   of this macro is to determine whether the space is included in
    `current_function_outgoing_args_size'.  */
 #define OUTGOING_REG_PARM_STACK_SPACE
 
@@ -2412,14 +2521,14 @@ extern struct mips_frame_info current_frame_info;
 
 typedef struct mips_args {
   int gp_reg_found;            /* whether a gp register was found yet */
-  int arg_number;              /* argument number */
-  int arg_words;               /* # total words the arguments take */
-  int fp_arg_words;            /* # words for FP args (MIPS_EABI only) */
+  unsigned int arg_number;     /* argument number */
+  unsigned int arg_words;      /* # total words the arguments take */
+  unsigned int fp_arg_words;   /* # words for FP args (MIPS_EABI only) */
   int last_arg_fp;             /* nonzero if last arg was FP (EABI only) */
   int fp_code;                 /* Mode of FP arguments (mips16) */
-  int num_adjusts;             /* number of adjustments made */
+  unsigned int num_adjusts;    /* number of adjustments made */
                                /* Adjustments made to args pass in regs.  */
-                               /* ??? The size is doubled to work around a 
+                               /* ??? The size is doubled to work around a
                                   bug in the code that sets the adjustments
                                   in function_arg.  */
   struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS*2];
@@ -2470,7 +2579,7 @@ typedef struct mips_args {
 
 #define FUNCTION_ARG_BOUNDARY(MODE, TYPE)                              \
   (((TYPE) != 0)                                                       \
-       ? ((TYPE_ALIGN(TYPE) <= (unsigned)PARM_BOUNDARY)                \
+       ? ((TYPE_ALIGN(TYPE) <= PARM_BOUNDARY)                          \
                ? PARM_BOUNDARY                                         \
                : TYPE_ALIGN(TYPE))                                     \
        : ((GET_MODE_ALIGNMENT(MODE) <= PARM_BOUNDARY)                  \
@@ -2478,23 +2587,6 @@ typedef struct mips_args {
                : GET_MODE_ALIGNMENT(MODE)))
 
 \f
-/* This macro generates the assembly code for function entry.
-   FILE is a stdio stream to output the code to.
-   SIZE is an int: how many units of temporary storage to allocate.
-   Refer to the array `regs_ever_live' to determine which registers
-   to save; `regs_ever_live[I]' is nonzero if register number I
-   is ever used in the function.  This macro is responsible for
-   knowing which registers should not be saved even if used.  */
-
-#define FUNCTION_PROLOGUE(FILE, SIZE) function_prologue(FILE, SIZE)
-
-/* This macro generates the assembly code for function exit,
-   on machines that need it.  If FUNCTION_EPILOGUE is not defined
-   then individual return instructions are generated for each
-   return statement.  Args are same as for FUNCTION_PROLOGUE.  */
-
-#define FUNCTION_EPILOGUE(FILE, SIZE) function_epilogue(FILE, SIZE)
-
 /* Tell prologue and epilogue if register REGNO should be saved / restored.  */
 
 #define MUST_SAVE_REGISTER(regno) \
@@ -2508,6 +2600,18 @@ typedef struct mips_args {
 #endif
 
 \f
+/* Define the `__builtin_va_list' type for the ABI.  */
+#define BUILD_VA_LIST_TYPE(VALIST) \
+  (VALIST) = mips_build_va_list ()
+
+/* Implement `va_start' for varargs and stdarg.  */
+#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
+  mips_va_start (stdarg, valist, nextarg)
+
+/* Implement `va_arg'.  */
+#define EXPAND_BUILTIN_VA_ARG(valist, type) \
+  mips_va_arg (valist, type)
+\f
 /* Output assembler code to FILE to increment profiler label # LABELNO
    for profiling a function entry.  */
 
@@ -2545,7 +2649,7 @@ typedef struct mips_args {
 
 \f
 /* A C statement to output, on the stream FILE, assembler code for a
-   block of data that contains the constant parts of a trampoline. 
+   block of data that contains the constant parts of a trampoline.
    This code should not include a label--the label is taken care of
    automatically.  */
 
@@ -2595,7 +2699,7 @@ typedef struct mips_args {
 #define CACHE_FLUSH_FUNC "_flush_cache"
 #endif
 
-/* A C statement to initialize the variable parts of a trampoline. 
+/* 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
    RTX for the static chain value that should be passed to the
@@ -2606,19 +2710,19 @@ typedef struct mips_args {
   rtx addr = ADDR;                                                         \
   if (Pmode == DImode)                                                     \
     {                                                                      \
-      emit_move_insn (gen_rtx (MEM, DImode, plus_constant (addr, 32)), FUNC); \
-      emit_move_insn (gen_rtx (MEM, DImode, plus_constant (addr, 40)), CHAIN);\
+      emit_move_insn (gen_rtx_MEM (DImode, plus_constant (addr, 32)), FUNC); \
+      emit_move_insn (gen_rtx_MEM (DImode, plus_constant (addr, 40)), CHAIN);\
     }                                                                      \
   else                                                                     \
     {                                                                      \
-      emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 32)), FUNC); \
-      emit_move_insn (gen_rtx (MEM, SImode, plus_constant (addr, 36)), CHAIN);\
+      emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 32)), FUNC); \
+      emit_move_insn (gen_rtx_MEM (SImode, plus_constant (addr, 36)), 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.  */                     \
-  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, CACHE_FLUSH_FUNC),        \
+  emit_library_call (gen_rtx_SYMBOL_REF (Pmode, 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));           \
@@ -2626,11 +2730,11 @@ typedef struct mips_args {
 \f
 /* Addressing modes, and classification of registers for them.  */
 
-/* #define HAVE_POST_INCREMENT */
-/* #define HAVE_POST_DECREMENT */
+/* #define HAVE_POST_INCREMENT */
+/* #define HAVE_POST_DECREMENT */
 
-/* #define HAVE_PRE_DECREMENT */
-/* #define HAVE_PRE_INCREMENT */
+/* #define HAVE_PRE_DECREMENT */
+/* #define HAVE_PRE_INCREMENT */
 
 /* These assume that REGNO is a hard or pseudo reg number.
    They give nonzero only if REGNO is a hard reg of the suitable class
@@ -2670,21 +2774,15 @@ typedef struct mips_args {
    need to be strict.  */
 
 #ifndef REG_OK_STRICT
-
-#define REG_OK_STRICT_P 0
-#define REG_OK_FOR_INDEX_P(X) 0
 #define REG_MODE_OK_FOR_BASE_P(X, MODE) \
-  GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (X), (MODE))
-
+  mips_reg_mode_ok_for_base_p (X, MODE, 0)
 #else
-
-#define REG_OK_STRICT_P 1
-#define REG_OK_FOR_INDEX_P(X) 0
 #define REG_MODE_OK_FOR_BASE_P(X, MODE) \
-  REGNO_MODE_OK_FOR_BASE_P (REGNO (X), (MODE))
-
+  mips_reg_mode_ok_for_base_p (X, MODE, 1)
 #endif
 
+#define REG_OK_FOR_INDEX_P(X) 0
+
 \f
 /* Maximum number of registers that can appear in a valid memory address.  */
 
@@ -2699,7 +2797,7 @@ typedef struct mips_args {
    to understand.
 
    This macro must exist in two variants: a strict variant and a
-   non-strict one.  The strict variant is used in the reload pass. 
+   non-strict one.  The strict variant is used in the reload pass.
    It must be defined so that any pseudo-register that has not been
    allocated a hard register is considered a memory reference.  In
    contexts where some kind of register is required, a
@@ -2736,13 +2834,13 @@ typedef struct mips_args {
    On some machines, whether a symbolic address is legitimate
    depends on the section that the address refers to.  On these
    machines, define the macro `ENCODE_SECTION_INFO' to store the
-   information into the `symbol_ref', and then check for it here. 
+   information into the `symbol_ref', and then check for it here.
    When you see a `const', you will have to look inside it to find
    the `symbol_ref' in order to determine the section.  */
 
 #if 1
-#define GO_PRINTF(x)   trace(x)
-#define GO_PRINTF2(x,y)        trace(x,y)
+#define GO_PRINTF(x)   fprintf(stderr, (x))
+#define GO_PRINTF2(x,y)        fprintf(stderr, (x), (y))
 #define GO_DEBUG_RTX(x) debug_rtx(x)
 
 #else
@@ -2751,95 +2849,19 @@ typedef struct mips_args {
 #define GO_DEBUG_RTX(x)
 #endif
 
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)                                \
-{                                                                      \
-  register rtx xinsn = (X);                                            \
-                                                                       \
-  if (TARGET_DEBUG_B_MODE)                                             \
-    {                                                                  \
-      GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n", \
-                 (REG_OK_STRICT_P) ? "" : "not ");                     \
-      GO_DEBUG_RTX (xinsn);                                            \
-    }                                                                  \
-                                                                       \
-  /* The mips16 can only use the stack pointer as a base register when \
-     loading SImode or DImode values.  */                              \
-  if (GET_CODE (xinsn) == REG && REG_MODE_OK_FOR_BASE_P (xinsn, MODE)) \
-    goto ADDR;                                                         \
-                                                                       \
-  if (CONSTANT_ADDRESS_P (xinsn)                                       \
-      && ! (mips_split_addresses && mips_check_split (xinsn, MODE))    \
-      && (! TARGET_MIPS16 || mips16_constant (xinsn, MODE, 1, 0)))     \
-    goto ADDR;                                                         \
-                                                                       \
-  if (GET_CODE (xinsn) == LO_SUM && mips_split_addresses)              \
-    {                                                                  \
-      register rtx xlow0 = XEXP (xinsn, 0);                            \
-      register rtx xlow1 = XEXP (xinsn, 1);                            \
-                                                                       \
-      if (GET_CODE (xlow0) == REG                                      \
-         && REG_MODE_OK_FOR_BASE_P (xlow0, MODE)                       \
-         && mips_check_split (xlow1, MODE))                            \
-       goto ADDR;                                                      \
-    }                                                                  \
-                                                                       \
-  if (GET_CODE (xinsn) == PLUS)                                                \
-    {                                                                  \
-      register rtx xplus0 = XEXP (xinsn, 0);                           \
-      register rtx xplus1 = XEXP (xinsn, 1);                           \
-      register enum rtx_code code0 = GET_CODE (xplus0);                        \
-      register enum rtx_code code1 = GET_CODE (xplus1);                        \
-                                                                       \
-      /* The mips16 can only use the stack pointer as a base register  \
-         when loading SImode or DImode values.  */                     \
-      if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, MODE))       \
-       {                                                               \
-         if (code1 == CONST_INT                                        \
-             && INTVAL (xplus1) >= -32768                              \
-             && INTVAL (xplus1) + GET_MODE_SIZE (MODE) - 1 <= 32767)   \
-           goto ADDR;                                                  \
-                                                                       \
-         /* On the mips16, we represent GP relative offsets in RTL.    \
-             These are 16 bit signed values, and can serve as register \
-             offsets.  */                                              \
-         if (TARGET_MIPS16                                             \
-             && mips16_gp_offset_p (xplus1))                           \
-           goto ADDR;                                                  \
-                                                                       \
-         /* For some code sequences, you actually get better code by   \
-            pretending that the MIPS supports an address mode of a     \
-            constant address + a register, even though the real        \
-            machine doesn't support it.  This is because the           \
-            assembler can use $r1 to load just the high 16 bits, add   \
-            in the register, and fold the low 16 bits into the memory  \
-            reference, whereas the compiler generates a 4 instruction  \
-            sequence.  On the other hand, CSE is not as effective.     \
-            It would be a win to generate the lui directly, but the    \
-            MIPS assembler does not have syntax to generate the        \
-            appropriate relocation.  */                                \
-                                                                       \
-         /* Also accept CONST_INT addresses here, so no else.  */      \
-         /* Reject combining an embedded PIC text segment reference    \
-            with a register.  That requires an additional              \
-            instruction.  */                                           \
-          /* ??? Reject combining an address with a register for the MIPS  \
-            64 bit ABI, because the SGI assembler can not handle this.  */ \
-         if (!TARGET_DEBUG_A_MODE                                      \
-             && (mips_abi == ABI_32 || mips_abi == ABI_EABI)           \
-             && CONSTANT_ADDRESS_P (xplus1)                            \
-             && ! mips_split_addresses                                 \
-             && (!TARGET_EMBEDDED_PIC                                  \
-                 || code1 != CONST                                     \
-                 || GET_CODE (XEXP (xplus1, 0)) != MINUS)              \
-             && !TARGET_MIPS16)                                        \
-           goto ADDR;                                                  \
-       }                                                               \
-    }                                                                  \
-                                                                       \
-  if (TARGET_DEBUG_B_MODE)                                             \
-    GO_PRINTF ("Not a legitimate address\n");                          \
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
+{                                              \
+  if (mips_legitimate_address_p (MODE, X, 1))  \
+    goto ADDR;                                 \
 }
-
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR)        \
+{                                              \
+  if (mips_legitimate_address_p (MODE, X, 0))  \
+    goto ADDR;                                 \
+}
+#endif
 
 /* A C expression that is 1 if the RTX X is a constant which is a
    valid address.  This is defined to be the same as `CONSTANT_P (X)',
@@ -2856,7 +2878,9 @@ typedef struct mips_args {
     || GET_CODE (X) == CONST_INT || GET_CODE (X) == HIGH               \
     || (GET_CODE (X) == CONST                                          \
        && ! (flag_pic && pic_address_needs_scratch (X))                \
-       && (mips_abi == ABI_32 || mips_abi == ABI_EABI)))               \
+       && (mips_abi == ABI_32                                          \
+           || mips_abi == ABI_O64                                      \
+           || mips_abi == ABI_EABI)))                                  \
    && (!HALF_PIC_P () || !HALF_PIC_ADDRESS_P (X)))
 
 /* Define this, so that when PIC, reload won't try to reload invalid
@@ -2871,12 +2895,19 @@ typedef struct mips_args {
    to be generated at present.  Also, the MIPS assembler does not
    grok li.d Infinity.  */
 
-/* ??? SGI Irix 6 assembler fails for CONST address, so reject them.  */
+/* ??? SGI Irix 6 assembler fails for CONST address, so reject them.
+   Note that the Irix 6 assembler problem may already be fixed.
+   Note also that the GET_CODE (X) == CONST test catches the mips16
+   gp pseudo reg (see mips16_gp_pseudo_reg) deciding it is not
+   a LEGITIMATE_CONSTANT.  If we ever want mips16 and ABI_N32 or
+   ABI_64 to work together, we'll need to fix this.  */
 #define LEGITIMATE_CONSTANT_P(X)                                       \
   ((GET_CODE (X) != CONST_DOUBLE                                       \
     || mips_const_double_ok (X, GET_MODE (X)))                         \
-   && ! (GET_CODE (X) == CONST                                         \
-        && mips_abi != ABI_32 && mips_abi != ABI_EABI)                 \
+   && ! (GET_CODE (X) == CONST                                                 \
+        && ! TARGET_GAS                                                \
+        && (mips_abi == ABI_N32                                        \
+            || mips_abi == ABI_64))                                    \
    && (! TARGET_MIPS16 || mips16_constant (X, GET_MODE (X), 0, 0)))
 
 /* A C compound statement that attempts to replace X with a valid
@@ -2916,7 +2947,7 @@ typedef struct mips_args {
 
    When PIC, convert addresses of the form memory (symbol+large int) to
    memory (reg+large int).  */
-   
+
 
 #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)                            \
 {                                                                      \
@@ -2931,22 +2962,26 @@ typedef struct mips_args {
   if (mips_split_addresses && mips_check_split (X, MODE))              \
     {                                                                  \
       /* ??? Is this ever executed?  */                                        \
-      X = gen_rtx (LO_SUM, Pmode,                                      \
-                  copy_to_mode_reg (Pmode, gen_rtx (HIGH, Pmode, X)), X); \
+      X = gen_rtx_LO_SUM (Pmode,                                       \
+                         copy_to_mode_reg (Pmode,                      \
+                                           gen_rtx (HIGH, Pmode, X)),  \
+                         X);                                           \
       goto WIN;                                                                \
     }                                                                  \
                                                                        \
   if (GET_CODE (xinsn) == CONST                                                \
       && ((flag_pic && pic_address_needs_scratch (xinsn))              \
          /* ??? SGI's Irix 6 assembler can't handle CONST.  */         \
-         || (mips_abi != ABI_32 && mips_abi != ABI_EABI)))             \
+         || (mips_abi != ABI_32                                        \
+             && mips_abi != ABI_O64                                    \
+             && mips_abi != ABI_EABI)))                                \
     {                                                                  \
       rtx ptr_reg = gen_reg_rtx (Pmode);                               \
       rtx constant = XEXP (XEXP (xinsn, 0), 1);                                \
                                                                        \
       emit_move_insn (ptr_reg, XEXP (XEXP (xinsn, 0), 0));             \
                                                                        \
-      X = gen_rtx (PLUS, Pmode, ptr_reg, constant);                    \
+      X = gen_rtx_PLUS (Pmode, ptr_reg, constant);                     \
       if (SMALL_INT (constant))                                                \
        goto WIN;                                                       \
       /* Otherwise we fall through so the code below will fix the      \
@@ -2978,12 +3013,11 @@ typedef struct mips_args {
          emit_move_insn (int_reg,                                      \
                          GEN_INT (INTVAL (xplus1) & ~ 0x7fff));        \
                                                                        \
-         emit_insn (gen_rtx (SET, VOIDmode,                            \
-                             ptr_reg,                                  \
-                             gen_rtx (PLUS, Pmode, xplus0, int_reg))); \
+         emit_insn (gen_rtx_SET (VOIDmode,                             \
+                                 ptr_reg,                              \
+                                 gen_rtx_PLUS (Pmode, xplus0, int_reg))); \
                                                                        \
-         X = gen_rtx (PLUS, Pmode, ptr_reg,                            \
-                      GEN_INT (INTVAL (xplus1) & 0x7fff));             \
+         X = plus_constant (ptr_reg, INTVAL (xplus1) & 0x7fff);        \
          goto WIN;                                                     \
        }                                                               \
     }                                                                  \
@@ -3014,7 +3048,7 @@ typedef struct mips_args {
    function named by the symbol (such as what section it is in).
 
    The macro definition, if any, is executed immediately after the
-   rtl for DECL has been created and stored in `DECL_RTL (DECL)'. 
+   rtl for DECL has been created and stored in `DECL_RTL (DECL)'.
    The value of the rtl will be a `mem' whose address is a
    `symbol_ref'.
 
@@ -3024,7 +3058,7 @@ typedef struct mips_args {
    information).
 
    The best way to modify the name string is by adding text to the
-   beginning, with suitable punctuation to prevent any ambiguity. 
+   beginning, with suitable punctuation to prevent any ambiguity.
    Allocate the new name in `saveable_obstack'.  You will have to
    modify `ASM_OUTPUT_LABELREF' to remove and decode the added text
    and output the name accordingly.
@@ -3043,13 +3077,29 @@ typedef struct mips_args {
    constants which are put in the .text section.  We also record the
    total length of all such strings; this total is used to decide
    whether we need to split the constant table, and need not be
-   precisely correct. 
+   precisely correct.
 
    When not mips16 code nor embedded PIC, if a symbol is in a
    gp addresable section, SYMBOL_REF_FLAG is set prevent gcc from
    splitting the reference so that gas can generate a gp relative
    reference.
- */
+
+   When TARGET_EMBEDDED_DATA is set, we assume that all const
+   variables will be stored in ROM, which is too far from %gp to use
+   %gprel addressing.  Note that (1) we include "extern const"
+   variables in this, which mips_select_section doesn't, and (2) we
+   can't always tell if they're really const (they might be const C++
+   objects with non-const constructors), so we err on the side of
+   caution and won't use %gprel anyway (otherwise we'd have to defer
+   this decision to the linker/loader).  The handling of extern consts
+   is why the DECL_INITIAL macros differ from mips_select_section.
+
+   If you are changing this macro, you should look at
+   mips_select_section and see if it needs a similar change.  */
+
+#ifndef UNIQUE_SECTION_P
+#define UNIQUE_SECTION_P(DECL) (0)
+#endif
 
 #define ENCODE_SECTION_INFO(DECL)                                      \
 do                                                                     \
@@ -3057,13 +3107,36 @@ do                                                                      \
     if (TARGET_MIPS16)                                                 \
       {                                                                        \
        if (TREE_CODE (DECL) == STRING_CST                              \
-           && ! flag_writable_strings)                                 \
+           && ! flag_writable_strings                                  \
+           /* If this string is from a function, and the function will \
+              go in a gnu linkonce section, then we can't directly     \
+              access the string.  This gets an assembler error         \
+              "unsupported PC relative reference to different section".\
+              If we modify SELECT_SECTION to put it in function_section\
+              instead of text_section, it still fails because          \
+              DECL_SECTION_NAME isn't set until assemble_start_function.\
+              If we fix that, it still fails because strings are shared\
+              among multiple functions, and we have cross section      \
+              references again.  We force it to work by putting string \
+              addresses in the constant pool and indirecting.  */      \
+           && (! current_function_decl                                 \
+               || ! UNIQUE_SECTION_P (current_function_decl)))         \
          {                                                             \
            SYMBOL_REF_FLAG (XEXP (TREE_CST_RTL (DECL), 0)) = 1;        \
            mips_string_length += TREE_STRING_LENGTH (DECL);            \
          }                                                             \
       }                                                                        \
-    if (TARGET_EMBEDDED_PIC)                                           \
+                                                                       \
+    if (TARGET_EMBEDDED_DATA                                           \
+       && (TREE_CODE (DECL) == VAR_DECL                                \
+           && TREE_READONLY (DECL) && !TREE_SIDE_EFFECTS (DECL))       \
+           && (!DECL_INITIAL (DECL)                                    \
+               || TREE_CONSTANT (DECL_INITIAL (DECL))))                \
+      {                                                                        \
+       SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 0;                \
+      }                                                                        \
+                                                                       \
+    else if (TARGET_EMBEDDED_PIC)                                      \
       {                                                                        \
         if (TREE_CODE (DECL) == VAR_DECL)                              \
          SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;              \
@@ -3086,7 +3159,11 @@ do                                                                       \
         SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;               \
       }                                                                        \
                                                                        \
-    else if (TARGET_GP_OPT && TREE_CODE (DECL) == VAR_DECL)            \
+    /* We can not perform GP optimizations on variables which are in   \
+       specific sections, except for .sdata and .sbss which are                \
+       handled above.  */                                              \
+    else if (TARGET_GP_OPT && TREE_CODE (DECL) == VAR_DECL             \
+            && DECL_SECTION_NAME (DECL) == NULL_TREE)                  \
       {                                                                        \
        int size = int_size_in_bytes (TREE_TYPE (DECL));                \
                                                                        \
@@ -3101,6 +3178,16 @@ do                                                                       \
   }                                                                    \
 while (0)
 
+/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
+   'the start of the function that this code is output in'.  */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME)  \
+  if (strcmp (NAME, "..CURRENT_FUNCTION") == 0)                                \
+    asm_fprintf ((FILE), "%U%s",                                       \
+                XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
+  else                                                                 \
+    asm_fprintf ((FILE), "%U%s", (NAME))
+
 /* The mips16 wants the constant pool to be after the function,
    because the PC relative load instructions use unsigned offsets.  */
 
@@ -3180,10 +3267,12 @@ while (0)
 
 /* Specify the machine mode that pointers have.
    After generation of rtl, the compiler makes no further distinction
-   between pointers and any other objects of this machine mode.  */
+   between pointers and any other objects of this machine mode.
+
+   For MIPS we make pointers are the smaller of longs and gp-registers. */
 
 #ifndef Pmode
-#define Pmode ((enum machine_mode)(TARGET_LONG64 ? DImode : SImode))
+#define Pmode ((TARGET_LONG64 && TARGET_64BIT) ? DImode : SImode)
 #endif
 
 /* A function address in a call instruction
@@ -3381,10 +3470,10 @@ while (0)
       enum machine_mode xmode = GET_MODE (X);                          \
       if (xmode == SFmode || xmode == DFmode)                          \
        {                                                               \
-         if (mips_cpu == PROCESSOR_R3000                               \
-              || mips_cpu == PROCESSOR_R3900)                          \
+         if (TUNE_MIPS3000                                             \
+              || TUNE_MIPS3900)                                        \
            return COSTS_N_INSNS (2);                                   \
-         else if (mips_cpu == PROCESSOR_R6000)                         \
+         else if (TUNE_MIPS6000)                                       \
            return COSTS_N_INSNS (3);                                   \
          else                                                          \
            return COSTS_N_INSNS (6);                                   \
@@ -3407,11 +3496,11 @@ while (0)
       enum machine_mode xmode = GET_MODE (X);                          \
       if (xmode == SFmode)                                             \
        {                                                               \
-         if (mips_cpu == PROCESSOR_R3000                               \
-             || mips_cpu == PROCESSOR_R3900                            \
-             || mips_cpu == PROCESSOR_R5000)                           \
+         if (TUNE_MIPS3000                             \
+             || TUNE_MIPS3900                          \
+             || TUNE_MIPS5000)                         \
            return COSTS_N_INSNS (4);                                   \
-         else if (mips_cpu == PROCESSOR_R6000)                         \
+         else if (TUNE_MIPS6000)                               \
            return COSTS_N_INSNS (5);                                   \
          else                                                          \
            return COSTS_N_INSNS (7);                                   \
@@ -3419,23 +3508,23 @@ while (0)
                                                                        \
       if (xmode == DFmode)                                             \
        {                                                               \
-         if (mips_cpu == PROCESSOR_R3000                               \
-             || mips_cpu == PROCESSOR_R3900                            \
-             || mips_cpu == PROCESSOR_R5000)                           \
+         if (TUNE_MIPS3000                             \
+             || TUNE_MIPS3900                          \
+             || TUNE_MIPS5000)                         \
            return COSTS_N_INSNS (5);                                   \
-         else if (mips_cpu == PROCESSOR_R6000)                         \
+         else if (TUNE_MIPS6000)                               \
            return COSTS_N_INSNS (6);                                   \
          else                                                          \
            return COSTS_N_INSNS (8);                                   \
        }                                                               \
                                                                        \
-      if (mips_cpu == PROCESSOR_R3000)                                 \
+      if (TUNE_MIPS3000)                                       \
        return COSTS_N_INSNS (12);                                      \
-      else if (mips_cpu == PROCESSOR_R3900)                            \
+      else if (TUNE_MIPS3900)                          \
        return COSTS_N_INSNS (2);                                       \
-      else if (mips_cpu == PROCESSOR_R6000)                            \
+      else if (TUNE_MIPS6000)                          \
        return COSTS_N_INSNS (17);                                      \
-      else if (mips_cpu == PROCESSOR_R5000)                            \
+      else if (TUNE_MIPS5000)                          \
        return COSTS_N_INSNS (5);                                       \
       else                                                             \
        return COSTS_N_INSNS (10);                                      \
@@ -3447,10 +3536,10 @@ while (0)
       enum machine_mode xmode = GET_MODE (X);                          \
       if (xmode == SFmode)                                             \
        {                                                               \
-         if (mips_cpu == PROCESSOR_R3000                               \
-              || mips_cpu == PROCESSOR_R3900)                          \
+         if (TUNE_MIPS3000                             \
+              || TUNE_MIPS3900)                                \
            return COSTS_N_INSNS (12);                                  \
-         else if (mips_cpu == PROCESSOR_R6000)                         \
+         else if (TUNE_MIPS6000)                               \
            return COSTS_N_INSNS (15);                                  \
          else                                                          \
            return COSTS_N_INSNS (23);                                  \
@@ -3458,10 +3547,10 @@ while (0)
                                                                        \
       if (xmode == DFmode)                                             \
        {                                                               \
-         if (mips_cpu == PROCESSOR_R3000                               \
-              || mips_cpu == PROCESSOR_R3900)                          \
+         if (TUNE_MIPS3000                             \
+              || TUNE_MIPS3900)                                \
            return COSTS_N_INSNS (19);                                  \
-         else if (mips_cpu == PROCESSOR_R6000)                         \
+         else if (TUNE_MIPS6000)                               \
            return COSTS_N_INSNS (16);                                  \
          else                                                          \
            return COSTS_N_INSNS (36);                                  \
@@ -3471,12 +3560,12 @@ while (0)
                                                                        \
   case UDIV:                                                           \
   case UMOD:                                                           \
-    if (mips_cpu == PROCESSOR_R3000                                    \
-        || mips_cpu == PROCESSOR_R3900)                                        \
+    if (TUNE_MIPS3000                                  \
+        || TUNE_MIPS3900)                                      \
       return COSTS_N_INSNS (35);                                       \
-    else if (mips_cpu == PROCESSOR_R6000)                              \
+    else if (TUNE_MIPS6000)                            \
       return COSTS_N_INSNS (38);                                       \
-    else if (mips_cpu == PROCESSOR_R5000)                              \
+    else if (TUNE_MIPS5000)                            \
       return COSTS_N_INSNS (36);                                       \
     else                                                               \
       return COSTS_N_INSNS (69);                                       \
@@ -3513,7 +3602,7 @@ while (0)
    used.
 
    For example, suppose an address that is equal to the sum of a
-   register and a constant is used twice in the same basic block. 
+   register and a constant is used twice in the same basic block.
    When this macro is not defined, the address will be computed in
    a register and memory references will be indirect through that
    register.  On machines where the cost of the addressing mode
@@ -3533,7 +3622,7 @@ while (0)
    defining `ADDRESS_COST' to reflect this can cause two registers
    to be live over a region of code where only one would have been
    if `ADDRESS_COST' were not defined in that manner.  This effect
-   should be considered in the definition of this macro. 
+   should be considered in the definition of this macro.
    Equivalent costs should probably only be given to addresses with
    different numbers of registers on machines with lots of registers.
 
@@ -3557,9 +3646,23 @@ while (0)
    that the constraints of the insn are met.  Setting a cost of
    other than 2 will allow reload to verify that the constraints are
    met.  You should do this if the `movM' pattern's constraints do
-   not allow such copying.  */
-
-#define REGISTER_MOVE_COST(FROM, TO)   \
+   not allow such copying.
+
+   ??? We make make the cost of moving from HI/LO/HILO/MD into general
+   registers the same as for one of moving general registers to
+   HI/LO/HILO/MD for TARGET_MIPS16 in order to prevent allocating a
+   pseudo to HI/LO/HILO/MD.  This might hurt optimizations though, it
+   isn't clear if it is wise.  And it might not work in all cases.  We
+   could solve the DImode LO reg problem by using a multiply, just like
+   reload_{in,out}si.  We could solve the SImode/HImode HI reg problem
+   by using divide instructions.  divu puts the remainder in the HI
+   reg, so doing a divide by -1 will move the value in the HI reg for
+   all values except -1.  We could handle that case by using a signed
+   divide, e.g.  -1 / 2 (or maybe 1 / -2?).  We'd have to emit a
+   compare/branch to test the input value to see which instruction we
+   need to use.  This gets pretty messy, but it is feasible. */
+
+#define REGISTER_MOVE_COST(MODE, FROM, TO)     \
   ((FROM) == M16_REGS && GR_REG_CLASS_P (TO) ? 2                       \
    : (FROM) == M16_NA_REGS && GR_REG_CLASS_P (TO) ? 2                  \
    : GR_REG_CLASS_P (FROM) && (TO) == M16_REGS ? 2                     \
@@ -3570,10 +3673,7 @@ while (0)
    : (FROM) == FP_REGS && GR_REG_CLASS_P (TO) ? 4                      \
    : (((FROM) == HI_REG || (FROM) == LO_REG                            \
        || (FROM) == MD_REGS || (FROM) == HILO_REG)                     \
-      && ((TO) == M16_REGS || (TO) == M16_NA_REGS)) ? 6                        \
-   : (((FROM) == HI_REG || (FROM) == LO_REG                            \
-       || (FROM) == MD_REGS || (FROM) == HILO_REG)                     \
-      && GR_REG_CLASS_P (TO)) ? (TARGET_MIPS16 ? 8 : 6)                        \
+      && GR_REG_CLASS_P (TO)) ? (TARGET_MIPS16 ? 12 : 6)               \
    : (((TO) == HI_REG || (TO) == LO_REG                                        \
        || (TO) == MD_REGS || (TO) == HILO_REG)                         \
       && GR_REG_CLASS_P (FROM)) ? (TARGET_MIPS16 ? 12 : 6)             \
@@ -3583,7 +3683,7 @@ while (0)
 
 /* ??? Fix this to be right for the R8000.  */
 #define MEMORY_MOVE_COST(MODE,CLASS,TO_P) \
-  (((mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000) ? 6 : 4) \
+  (((TUNE_MIPS4000 || TUNE_MIPS6000) ? 6 : 4) \
    + memory_move_secondary_cost ((MODE), (CLASS), (TO_P)))
 
 /* Define if copies to/from condition code registers should be avoided.
@@ -3599,7 +3699,7 @@ while (0)
 /* ??? Fix this to be right for the R8000.  */
 #define BRANCH_COST                                                    \
   ((! TARGET_MIPS16                                                    \
-    && (mips_cpu == PROCESSOR_R4000 || mips_cpu == PROCESSOR_R6000))   \
+    && (TUNE_MIPS4000 || TUNE_MIPS6000))       \
    ? 2 : 1)
 
 /* A C statement (sans semicolon) to update the integer variable COST
@@ -3611,6 +3711,14 @@ while (0)
 #define ADJUST_COST(INSN,LINK,DEP_INSN,COST)                           \
   if (REG_NOTE_KIND (LINK) != 0)                                       \
     (COST) = 0; /* Anti or output dependence.  */
+
+/* If defined, modifies the length assigned to instruction INSN as a
+   function of the context in which it is used.  LENGTH is an lvalue
+   that contains the initially computed length of the insn and should
+   be updated with the correct length of the insn.  */
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+  ((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH)))
+
 \f
 /* Optionally define this if you have added predicates to
    `MACHINE.c'.  This macro is called within an initializer of an
@@ -3627,7 +3735,7 @@ while (0)
 
    Defining this macro does not affect the generated code (however,
    incorrect definitions that omit an rtl code that may be matched
-   by the predicate can cause the compiler to malfunction). 
+   by the predicate can cause the compiler to malfunction).
    Instead, it allows the table built by `genrecog' to be more
    compact and efficient, thus speeding up the compiler.  The most
    important predicates to include in the list specified by this
@@ -3637,7 +3745,8 @@ while (0)
   {"uns_arith_operand",                { REG, CONST_INT, SUBREG }},            \
   {"arith_operand",            { REG, CONST_INT, SUBREG }},            \
   {"arith32_operand",          { REG, CONST_INT, SUBREG }},            \
-  {"reg_or_0_operand",         { REG, CONST_INT, SUBREG }},            \
+  {"reg_or_0_operand",         { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \
+  {"true_reg_or_0_operand",    { REG, CONST_INT, CONST_DOUBLE, SUBREG }}, \
   {"small_int",                        { CONST_INT }},                         \
   {"large_int",                        { CONST_INT }},                         \
   {"mips_const_double_ok",     { CONST_DOUBLE }},                      \
@@ -3646,6 +3755,7 @@ while (0)
   {"equality_op",              { EQ, NE }},                            \
   {"cmp_op",                   { EQ, NE, GT, GE, GTU, GEU, LT, LE,     \
                                  LTU, LEU }},                          \
+  {"trap_cmp_op",              { EQ, NE, GE, GEU, LT, LTU }},          \
   {"pc_or_label_operand",      { PC, LABEL_REF }},                     \
   {"call_insn_operand",                { CONST_INT, CONST, SYMBOL_REF, REG}},  \
   {"move_operand",             { CONST_INT, CONST_DOUBLE, CONST,       \
@@ -3655,7 +3765,7 @@ while (0)
                                  SYMBOL_REF, LABEL_REF, SUBREG, REG,   \
                                  MEM, SIGN_EXTEND }},                  \
   {"se_register_operand",      { SUBREG, REG, SIGN_EXTEND }},          \
-  {"se_reg_or_0_operand",      { REG, CONST_INT, SUBREG,               \
+  {"se_reg_or_0_operand",      { REG, CONST_INT, CONST_DOUBLE, SUBREG, \
                                  SIGN_EXTEND }},                       \
   {"se_uns_arith_operand",     { REG, CONST_INT, SUBREG,               \
                                  SIGN_EXTEND }},                       \
@@ -3670,6 +3780,11 @@ while (0)
   {"extend_operator",           { SIGN_EXTEND, ZERO_EXTEND }},          \
   {"highpart_shift_operator",   { ASHIFTRT, LSHIFTRT, ROTATERT, ROTATE }},
 
+/* A list of predicates that do special things with modes, and so
+   should not elicit warnings for VOIDmode match_operand.  */
+
+#define SPECIAL_MODE_PREDICATES \
+  "pc_or_label_operand",
 
 \f
 /* If defined, a C statement to be executed just prior to the
@@ -3701,6 +3816,7 @@ while (0)
    declaration when the code is processed, it generates a two
    instruction sequence.  */
 
+#undef ASM_FILE_START
 #define ASM_FILE_START(STREAM) mips_asm_file_start (STREAM)
 
 /* Output to assembler file text saying following lines
@@ -3895,15 +4011,6 @@ while (0)
   { "$fp",     30 + GP_REG_FIRST }                                     \
 }
 
-/* Define results of standard character escape sequences.  */
-#define TARGET_BELL    007
-#define TARGET_BS      010
-#define TARGET_TAB     011
-#define TARGET_NEWLINE 012
-#define TARGET_VT      013
-#define TARGET_FF      014
-#define TARGET_CR      015
-
 /* A C compound statement to output to stdio stream STREAM the
    assembler syntax for an instruction operand X.  X is an RTL
    expression.
@@ -4012,6 +4119,7 @@ while (0)
 #define LABEL_AFTER_LOC(STREAM)
 #endif
 
+#undef ASM_OUTPUT_SOURCE_LINE
 #define ASM_OUTPUT_SOURCE_LINE(STREAM, LINE)                           \
   mips_output_lineno (STREAM, LINE)
 
@@ -4045,13 +4153,14 @@ do {                                                                    \
 /* A C statement (sans semicolon) to output to the stdio stream
    STREAM any text necessary for declaring the name NAME of an
    initialized variable which is being defined.  This macro must
-   output the label definition (perhaps using `ASM_OUTPUT_LABEL'). 
+   output the label definition (perhaps using `ASM_OUTPUT_LABEL').
    The argument DECL is the `VAR_DECL' tree node representing the
    variable.
 
    If this macro is not defined, then the variable name is defined
    in the usual manner as a label (by means of `ASM_OUTPUT_LABEL').  */
 
+#undef ASM_DECLARE_OBJECT_NAME
 #define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL)                    \
 do                                                                     \
  {                                                                     \
@@ -4073,8 +4182,28 @@ while (0)
 
 /* This says how to define a global common symbol.  */
 
-#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED)                 \
-  mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u\n", (SIZE))
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON(STREAM, DECL, NAME, SIZE, ALIGN) \
+  do {                                                                 \
+    /* If the target wants uninitialized const declarations in         \
+       .rdata then don't put them in .comm */                          \
+    if (TARGET_EMBEDDED_DATA && TARGET_UNINIT_CONST_IN_RODATA          \
+       && TREE_CODE (DECL) == VAR_DECL && TREE_READONLY (DECL)         \
+       && (DECL_INITIAL (DECL) == 0                                    \
+           || DECL_INITIAL (DECL) == error_mark_node))                 \
+      {                                                                        \
+       if (TREE_PUBLIC (DECL) && DECL_NAME (DECL))                     \
+         ASM_GLOBALIZE_LABEL (STREAM, NAME);                           \
+                                                                       \
+       READONLY_DATA_SECTION ();                                       \
+       ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT));  \
+       mips_declare_object (STREAM, NAME, "", ":\n\t.space\t%u\n",     \
+           (SIZE));                                                    \
+      }                                                                        \
+    else                                                               \
+      mips_declare_object (STREAM, NAME, "\n\t.comm\t", ",%u\n",       \
+         (SIZE));                                                      \
+  } while (0)
+
 
 /* This says how to define a local common symbol (ie, not visible to
    linker).  */
@@ -4092,6 +4221,7 @@ while (0)
   mips_output_external(STREAM,DECL,NAME)
 
 /* This says what to print at the end of the assembly file */
+#undef ASM_FILE_END
 #define ASM_FILE_END(STREAM) mips_asm_file_end(STREAM)
 
 
@@ -4102,6 +4232,7 @@ while (0)
 
    Also, switch files if we are optimizing the global pointer.  */
 
+#undef ASM_DECLARE_FUNCTION_NAME
 #define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL)                    \
 {                                                                      \
   extern FILE *asm_out_text_file;                                      \
@@ -4124,6 +4255,7 @@ while (0)
 /* This is how to output an internal numbered label where
    PREFIX is the class of label and NUM is the number within the class.  */
 
+#undef ASM_OUTPUT_INTERNAL_LABEL
 #define ASM_OUTPUT_INTERNAL_LABEL(STREAM,PREFIX,NUM)                   \
   fprintf (STREAM, "%s%s%d:\n", LOCAL_LABEL_PREFIX, PREFIX, NUM)
 
@@ -4132,6 +4264,7 @@ while (0)
    PREFIX is the class of label and NUM is the number within the class.
    This is suitable for output with `assemble_name'.  */
 
+#undef ASM_GENERATE_INTERNAL_LABEL
 #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM)                  \
   sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
 
@@ -4156,11 +4289,20 @@ do {                                                                    \
   fprintf (STREAM, "\n");                                              \
 } while (0)
 
-/* Likewise for 64 bit, `char' and `short' constants.  */
+/* Likewise for 64 bit, `char' and `short' constants.
+
+   FIXME: operand_subword can't handle some complex constant expressions
+   that output_addr_const can (for example it does not call
+   simplify_subtraction).  Since GAS can handle dword, even for mipsII,
+   rely on that to avoid operand_subword for most of the cases where this
+   matters.  Try gcc.c-torture/compile/930326-1.c with -mips2 -mlong64,
+   or the same case with the type of 'i' changed to long long.
+
+*/
 
 #define ASM_OUTPUT_DOUBLE_INT(STREAM,VALUE)                            \
 do {                                                                   \
-  if (TARGET_64BIT)                                                    \
+  if (TARGET_64BIT || TARGET_GAS)                                      \
     {                                                                  \
       fprintf (STREAM, "\t.dword\t");                                  \
       if (HOST_BITS_PER_WIDE_INT < 64 || GET_CODE (VALUE) != CONST_INT)        \
@@ -4222,7 +4364,7 @@ do {                                                                      \
     fprintf (STREAM, "\t%s\t%sL%d-%sLS%d\n",                           \
             Pmode == DImode ? ".dword" : ".word",                      \
             LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL);       \
-  else if (mips_abi == ABI_32)                                         \
+  else if (mips_abi == ABI_32 || mips_abi == ABI_O64)                  \
     fprintf (STREAM, "\t%s\t%sL%d\n",                                  \
             Pmode == DImode ? ".gpdword" : ".gpword",                  \
             LOCAL_LABEL_PREFIX, VALUE);                                \
@@ -4238,6 +4380,7 @@ do {                                                                      \
    JUMP_TABLES_IN_TEXT_SECTION, because it is not conditional.
    Instead, we use ASM_OUTPUT_CASE_LABEL to switch back to the .text
    section if appropriate.  */
+#undef ASM_OUTPUT_CASE_LABEL
 #define ASM_OUTPUT_CASE_LABEL(FILE, PREFIX, NUM, INSN)                 \
 do {                                                                   \
   if (TARGET_EMBEDDED_PIC || TARGET_MIPS16)                            \
@@ -4255,87 +4398,23 @@ do {                                                                    \
 /* This is how to output an assembler line to advance the location
    counter by SIZE bytes.  */
 
+#undef ASM_OUTPUT_SKIP
 #define ASM_OUTPUT_SKIP(STREAM,SIZE)                                   \
   fprintf (STREAM, "\t.space\t%u\n", (SIZE))
 
 /* This is how to output a string.  */
+#undef ASM_OUTPUT_ASCII
 #define ASM_OUTPUT_ASCII(STREAM, STRING, LEN)                          \
-do {                                                                   \
-  register int i, c, len = (LEN), cur_pos = 17;                                \
-  register unsigned char *string = (unsigned char *)(STRING);          \
-  fprintf ((STREAM), "\t.ascii\t\"");                                  \
-  for (i = 0; i < len; i++)                                            \
-    {                                                                  \
-      register int c = string[i];                                      \
-                                                                       \
-      switch (c)                                                       \
-       {                                                               \
-       case '\"':                                                      \
-       case '\\':                                                      \
-         putc ('\\', (STREAM));                                        \
-         putc (c, (STREAM));                                           \
-         cur_pos += 2;                                                 \
-         break;                                                        \
-                                                                       \
-       case TARGET_NEWLINE:                                            \
-         fputs ("\\n", (STREAM));                                      \
-         if (i+1 < len                                                 \
-             && (((c = string[i+1]) >= '\040' && c <= '~')             \
-                 || c == TARGET_TAB))                                  \
-           cur_pos = 32767;            /* break right here */          \
-         else                                                          \
-           cur_pos += 2;                                               \
-         break;                                                        \
-                                                                       \
-       case TARGET_TAB:                                                \
-         fputs ("\\t", (STREAM));                                      \
-         cur_pos += 2;                                                 \
-         break;                                                        \
-                                                                       \
-       case TARGET_FF:                                                 \
-         fputs ("\\f", (STREAM));                                      \
-         cur_pos += 2;                                                 \
-         break;                                                        \
-                                                                       \
-       case TARGET_BS:                                                 \
-         fputs ("\\b", (STREAM));                                      \
-         cur_pos += 2;                                                 \
-         break;                                                        \
-                                                                       \
-       case TARGET_CR:                                                 \
-         fputs ("\\r", (STREAM));                                      \
-         cur_pos += 2;                                                 \
-         break;                                                        \
-                                                                       \
-       default:                                                        \
-         if (c >= ' ' && c < 0177)                                     \
-           {                                                           \
-             putc (c, (STREAM));                                       \
-             cur_pos++;                                                \
-           }                                                           \
-         else                                                          \
-           {                                                           \
-             fprintf ((STREAM), "\\%03o", c);                          \
-             cur_pos += 4;                                             \
-           }                                                           \
-       }                                                               \
-                                                                       \
-      if (cur_pos > 72 && i+1 < len)                                   \
-       {                                                               \
-         cur_pos = 17;                                                 \
-         fprintf ((STREAM), "\"\n\t.ascii\t\"");                       \
-       }                                                               \
-    }                                                                  \
-  fprintf ((STREAM), "\"\n");                                          \
-} while (0)
+  mips_output_ascii (STREAM, STRING, LEN)
 
 /* Handle certain cpp directives used in header files on sysV.  */
 #define SCCS_DIRECTIVE
 
 /* Output #ident as a in the read-only data section.  */
+#undef ASM_OUTPUT_IDENT
 #define ASM_OUTPUT_IDENT(FILE, STRING)                                 \
 {                                                                      \
-  char *p = STRING;                                                    \
+  const char *p = STRING;                                              \
   int size = strlen (p) + 1;                                           \
   rdata_section ();                                                    \
   assemble_string (p, size);                                           \
@@ -4351,11 +4430,13 @@ do {                                                                    \
 #define DATA_SECTION_ASM_OP    "\t.data"       /* large data */
 #define SDATA_SECTION_ASM_OP   "\t.sdata"      /* small data */
 #define RDATA_SECTION_ASM_OP   "\t.rdata"      /* read-only data */
+#undef READONLY_DATA_SECTION
 #define READONLY_DATA_SECTION  rdata_section
 #define SMALL_DATA_SECTION     sdata_section
 
 /* What other sections we support other than the normal .data/.text.  */
 
+#undef EXTRA_SECTIONS
 #define EXTRA_SECTIONS in_sdata, in_rdata
 
 /* Define the additional functions to select our additional sections.  */
@@ -4368,6 +4449,7 @@ do {                                                                      \
    if the constant is too large for sdata, and it's readonly, it
    will go into the .rdata section. */
 
+#undef EXTRA_SECTION_FUNCTIONS
 #define EXTRA_SECTION_FUNCTIONS                                                \
 void                                                                   \
 sdata_section ()                                                       \
@@ -4392,8 +4474,10 @@ rdata_section ()                                                 \
 /* Given a decl node or constant node, choose the section to output it in
    and select that section.  */
 
+#undef SELECT_RTX_SECTION
 #define SELECT_RTX_SECTION(MODE,RTX)   mips_select_rtx_section (MODE, RTX)
 
+#undef SELECT_SECTION
 #define SELECT_SECTION(DECL, RELOC)    mips_select_section (DECL, RELOC)
 
 \f
@@ -4439,12 +4523,6 @@ do                                                                       \
   }                                                                    \
 while (0)
 
-/* Define the parentheses used to group arithmetic operations
-   in assembler code.  */
-
-#define ASM_OPEN_PAREN "("
-#define ASM_CLOSE_PAREN ")"
-
 /* How to start an assembler comment.
    The leading space is important (the mips native assembler requires it).  */
 #ifndef ASM_COMMENT_START
@@ -4479,7 +4557,9 @@ while (0)
 /* See mips_expand_prologue's use of loadgp for when this should be
    true.  */
 
-#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS && mips_abi != ABI_32)
+#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (TARGET_ABICALLS               \
+                                        && mips_abi != ABI_32          \
+                                        && mips_abi != ABI_O64)
 \f
 /* In mips16 mode, we need to look through the function to check for
    PC relative loads that are out of range.  */
@@ -4500,59 +4580,59 @@ do                                                                      \
     else                                                               \
       {                                                                        \
        add_optab->handlers[(int) SFmode].libfunc =                     \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_addsf3");               \
+         init_one_libfunc ("__mips16_addsf3");                         \
        sub_optab->handlers[(int) SFmode].libfunc =                     \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_subsf3");               \
+         init_one_libfunc ("__mips16_subsf3");                         \
        smul_optab->handlers[(int) SFmode].libfunc =                    \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_mulsf3");               \
+         init_one_libfunc ("__mips16_mulsf3");                         \
        flodiv_optab->handlers[(int) SFmode].libfunc =                  \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_divsf3");               \
+         init_one_libfunc ("__mips16_divsf3");                         \
                                                                        \
-       eqsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_eqsf2");  \
-       nesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_nesf2");  \
-       gtsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_gtsf2");  \
-       gesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_gesf2");  \
-       ltsf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_ltsf2");  \
-       lesf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__mips16_lesf2");  \
+       eqsf2_libfunc = init_one_libfunc ("__mips16_eqsf2");            \
+       nesf2_libfunc = init_one_libfunc ("__mips16_nesf2");            \
+       gtsf2_libfunc = init_one_libfunc ("__mips16_gtsf2");            \
+       gesf2_libfunc = init_one_libfunc ("__mips16_gesf2");            \
+       ltsf2_libfunc = init_one_libfunc ("__mips16_ltsf2");            \
+       lesf2_libfunc = init_one_libfunc ("__mips16_lesf2");            \
                                                                        \
        floatsisf_libfunc =                                             \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_floatsisf");            \
+         init_one_libfunc ("__mips16_floatsisf");                      \
        fixsfsi_libfunc =                                               \
-         gen_rtx (SYMBOL_REF, Pmode, "__mips16_fixsfsi");              \
+         init_one_libfunc ("__mips16_fixsfsi");                        \
                                                                        \
        if (TARGET_DOUBLE_FLOAT)                                        \
          {                                                             \
            add_optab->handlers[(int) DFmode].libfunc =                 \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_adddf3");           \
+             init_one_libfunc ("__mips16_adddf3");                     \
            sub_optab->handlers[(int) DFmode].libfunc =                 \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_subdf3");           \
+             init_one_libfunc ("__mips16_subdf3");                     \
            smul_optab->handlers[(int) DFmode].libfunc =                \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_muldf3");           \
+             init_one_libfunc ("__mips16_muldf3");                     \
            flodiv_optab->handlers[(int) DFmode].libfunc =              \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_divdf3");           \
+             init_one_libfunc ("__mips16_divdf3");                     \
                                                                        \
            extendsfdf2_libfunc =                                       \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_extendsfdf2");      \
+             init_one_libfunc ("__mips16_extendsfdf2");                \
            truncdfsf2_libfunc =                                        \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_truncdfsf2");       \
+             init_one_libfunc ("__mips16_truncdfsf2");                 \
                                                                        \
            eqdf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_eqdf2");            \
+             init_one_libfunc ("__mips16_eqdf2");                      \
            nedf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_nedf2");            \
+             init_one_libfunc ("__mips16_nedf2");                      \
            gtdf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_gtdf2");            \
+             init_one_libfunc ("__mips16_gtdf2");                      \
            gedf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_gedf2");            \
+             init_one_libfunc ("__mips16_gedf2");                      \
            ltdf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_ltdf2");            \
+             init_one_libfunc ("__mips16_ltdf2");                      \
            ledf2_libfunc =                                             \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_ledf2");            \
+             init_one_libfunc ("__mips16_ledf2");                      \
                                                                        \
            floatsidf_libfunc =                                         \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_floatsidf");        \
+             init_one_libfunc ("__mips16_floatsidf");                  \
            fixdfsi_libfunc =                                           \
-             gen_rtx (SYMBOL_REF, Pmode, "__mips16_fixdfsi");          \
+             init_one_libfunc ("__mips16_fixdfsi");                    \
          }                                                             \
       }                                                                        \
   }                                                                    \