OSDN Git Service

* function.h (struct function): Add profile.
[pf3gnuchains/gcc-fork.git] / gcc / config / mips / mips.c
index 583cf73..83df738 100644 (file)
@@ -54,6 +54,10 @@ Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "target-def.h"
 
+#ifdef HALF_PIC_DEBUG
+#include "halfpic.h"
+#endif
+
 #ifdef __GNU_STAB__
 #define STAB_CODE_TYPE enum __stab_debug_code
 #else
@@ -64,7 +68,7 @@ extern tree   lookup_name PARAMS ((tree));
 
 /* Enumeration for all of the relational tests, so that we can build
    arrays indexed by the test type, and not worry about the order
-   of EQ, NE, etc. */
+   of EQ, NE, etc.  */
 
 enum internal_test {
     ITEST_EQ,
@@ -94,6 +98,8 @@ static void block_move_call                   PARAMS ((rtx, rtx, rtx));
 static rtx mips_add_large_offset_to_sp         PARAMS ((HOST_WIDE_INT,
                                                         FILE *));
 static void mips_annotate_frame_insn           PARAMS ((rtx, rtx));
+static rtx mips_frame_set                      PARAMS ((enum machine_mode,
+                                                        int, int));
 static void mips_emit_frame_related_store      PARAMS ((rtx, rtx,
                                                         HOST_WIDE_INT));
 static void save_restore_insns                 PARAMS ((int, rtx,
@@ -112,6 +118,7 @@ static void abort_with_insn                 PARAMS ((rtx, const char *))
   ATTRIBUTE_NORETURN;
 static int symbolic_expression_p                PARAMS ((rtx));
 static void mips_add_gc_roots                   PARAMS ((void));
+static bool mips_assemble_integer        PARAMS ((rtx, unsigned int, int));
 static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
 static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
 static enum processor_type mips_parse_cpu       PARAMS ((const char *));
@@ -143,7 +150,7 @@ int num_source_filenames = 0;
    start and end boundaries).  */
 int sdb_label_count = 0;
 
-/* Next label # for each statement for Silicon Graphics IRIS systems. */
+/* Next label # for each statement for Silicon Graphics IRIS systems.  */
 int sym_lineno = 0;
 
 /* Non-zero if inside of a function, because the stupid MIPS asm can't
@@ -222,11 +229,8 @@ enum processor_type mips_tune;
 /* which instruction set architecture to use.  */
 int mips_isa;
 
-#ifdef MIPS_ABI_DEFAULT
-/* Which ABI to use.  This is defined to a constant in mips.h if the target
-   doesn't support multiple ABIs.  */
+/* which abi to use.  */
 int mips_abi;
-#endif
 
 /* Strings to hold which cpu and instruction set architecture to use.  */
 const char *mips_cpu_string;   /* for -mcpu=<xxx> */
@@ -246,7 +250,7 @@ const char *mips_no_mips16_string;
 
 /* This is only used to determine if an type size setting option was
    explicitly specified (-mlong64, -mint64, -mlong32).  The specs
-   set this option if such an option is used. */
+   set this option if such an option is used.  */
 const char *mips_explicit_type_size_string;
 
 /* Whether we are generating mips16 hard float code.  In mips16 mode
@@ -260,6 +264,8 @@ int mips16_hard_float;
    avoid using up another bit in target_flags.  */
 const char *mips_entry_string;
 
+const char *mips_cache_flush_func = CACHE_FLUSH_FUNC;
+
 /* Whether we should entry and exit pseudo-ops in mips16 mode.  */
 int mips_entry;
 
@@ -343,7 +349,7 @@ char mips_reg_names[][8] =
 /* Mips software names for the registers, used to overwrite the
    mips_reg_names array.  */
 
-char mips_sw_reg_names[][8] =
+static const char mips_sw_reg_names[][8] =
 {
   "$zero","$at",  "$v0",  "$v1",  "$a0",  "$a1",  "$a2",  "$a3",
   "$t0",  "$t1",  "$t2",  "$t3",  "$t4",  "$t5",  "$t6",  "$t7",
@@ -358,7 +364,7 @@ char mips_sw_reg_names[][8] =
 };
 
 /* Map hard register number to register class */
-enum reg_class mips_regno_to_class[] =
+const enum reg_class mips_regno_to_class[] =
 {
   GR_REGS,     GR_REGS,        M16_NA_REGS,    M16_NA_REGS,
   M16_REGS,    M16_REGS,       M16_REGS,       M16_REGS,
@@ -451,6 +457,20 @@ enum reg_class mips_char_to_class[256] =
 };
 \f
 /* Initialize the GCC target structure.  */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER mips_assemble_integer
+
+#if TARGET_IRIX5 && !TARGET_IRIX6
+#undef TARGET_ASM_UNALIGNED_HI_OP
+#define TARGET_ASM_UNALIGNED_HI_OP "\t.align 0\n\t.half\t"
+#undef TARGET_ASM_UNALIGNED_SI_OP
+#define TARGET_ASM_UNALIGNED_SI_OP "\t.align 0\n\t.word\t"
+#endif
+
 #undef TARGET_ASM_FUNCTION_PROLOGUE
 #define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
 #undef TARGET_ASM_FUNCTION_EPILOGUE
@@ -507,7 +527,7 @@ arith32_operand (op, mode)
   return register_operand (op, mode);
 }
 
-/* Return truth value of whether OP is a integer which fits in 16 bits  */
+/* Return truth value of whether OP is an integer which fits in 16 bits.  */
 
 int
 small_int (op, mode)
@@ -580,7 +600,7 @@ reg_or_0_operand (op, mode)
 }
 
 /* Return truth value of whether OP is a register or the constant 0,
-   even in mips16 mode. */
+   even in mips16 mode.  */
 
 int
 true_reg_or_0_operand (op, mode)
@@ -795,7 +815,7 @@ simple_memory_operand (op, mode)
        if (GET_CODE (op) != SYMBOL_REF)
          return 0;
 
-       /* let's be paranoid.... */
+       /* let's be paranoid....  */
        if (! SMALL_INT (offset))
          return 0;
       }
@@ -900,7 +920,7 @@ double_memory_operand (op, mode)
            return 1;
 
          /* Similarly, we accept a case where the memory address is
-             itself on the stack, and will be reloaded. */
+             itself on the stack, and will be reloaded.  */
          if (GET_CODE (addr) == MEM)
            {
              rtx maddr;
@@ -1292,7 +1312,7 @@ mips_legitimate_address_p (mode, xinsn, strict)
     }
 
   /* Check for constant before stripping off SUBREG, so that we don't
-     accept (subreg (const_int)) which will fail to reload. */
+     accept (subreg (const_int)) which will fail to reload.  */
   if (CONSTANT_ADDRESS_P (xinsn)
       && ! (mips_split_addresses && mips_check_split (xinsn, mode))
       && (! TARGET_MIPS16 || mips16_constant (xinsn, mode, 1, 0)))
@@ -1383,7 +1403,7 @@ mips_legitimate_address_p (mode, xinsn, strict)
                 (set (blah:DI) (plus x y)).  */
              && (!TARGET_64BIT
                  || (code1 == CONST_INT
-                     && trunc_int_for_mode (INTVAL (xplus1), 
+                     && trunc_int_for_mode (INTVAL (xplus1),
                                             SImode) == INTVAL (xplus1)))
              && !TARGET_MIPS16)
            return 1;
@@ -2235,7 +2255,7 @@ mips_move_1word (operands, insn, unsignedp)
 
   if (ret == 0)
     {
-      abort_with_insn (insn, "Bad move");
+      abort_with_insn (insn, "bad move");
       return 0;
     }
 
@@ -2323,7 +2343,7 @@ mips_move_2words (operands, insn)
                  if (TARGET_FLOAT64)
                    {
                      if (!TARGET_64BIT)
-                       abort_with_insn (insn, "Bad move");
+                       abort_with_insn (insn, "bad move");
 
 #ifdef TARGET_FP_CALL_32
                      if (FP_CALL_GP_REG_P (regno1))
@@ -2343,7 +2363,7 @@ mips_move_2words (operands, insn)
              if (TARGET_FLOAT64)
                {
                  if (!TARGET_64BIT)
-                   abort_with_insn (insn, "Bad move");
+                   abort_with_insn (insn, "bad move");
 
 #ifdef TARGET_FP_CALL_32
                  if (FP_CALL_GP_REG_P (regno0))
@@ -2688,7 +2708,7 @@ mips_move_2words (operands, insn)
 
   if (ret == 0)
     {
-      abort_with_insn (insn, "Bad move");
+      abort_with_insn (insn, "bad move");
       return 0;
     }
 
@@ -2727,7 +2747,7 @@ mips_address_cost (addr)
          return 2;
       }
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case SYMBOL_REF:
       return SYMBOL_REF_FLAG (addr) ? 1 : 2;
@@ -3480,7 +3500,7 @@ expand_block_move (operands)
    The block move type can be one of the following:
        BLOCK_MOVE_NORMAL       Do all of the block move.
        BLOCK_MOVE_NOT_LAST     Do all but the last store.
-       BLOCK_MOVE_LAST         Do just the last store. */
+       BLOCK_MOVE_LAST         Do just the last store.  */
 
 const char *
 output_block_move (insn, operands, num_regs, move_type)
@@ -3536,7 +3556,9 @@ output_block_move (insn, operands, num_regs, move_type)
      constant addresses into registers when generating N32/N64 code, just
      in case we might emit an unaligned load instruction.  */
   if (num_regs > 2 && (bytes > 2 * align || move_type != BLOCK_MOVE_NORMAL
-                      || mips_abi == ABI_N32 || mips_abi == ABI_64))
+                      || mips_abi == ABI_MEABI
+                      || mips_abi == ABI_N32
+                      || mips_abi == ABI_64))
     {
       if (CONSTANT_P (src_reg))
        {
@@ -3614,7 +3636,7 @@ output_block_move (insn, operands, num_regs, move_type)
 
   else if (num_regs < 1)
     abort_with_insn (insn,
-                    "Cannot do block move, not enough scratch registers");
+                    "cannot do block move, not enough scratch registers");
 
   while (bytes > 0)
     {
@@ -3850,11 +3872,12 @@ init_cumulative_args (cum, fntype, libname)
     }
 
   *cum = zero_cum;
+  cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
 
   /* Determine if this function has variable arguments.  This is
      indicated by the last argument being 'void_type_mode' if there
      are no variable arguments.  The standard MIPS calling sequence
-     passes all arguments in the general purpose registers in this case. */
+     passes all arguments in the general purpose registers in this case.  */
 
   for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
        param != 0; param = next_param)
@@ -3994,6 +4017,11 @@ function_arg (cum, mode, type, named)
          arg_words = &cum->fp_arg_words;
          regbase = FP_ARG_FIRST;
        }
+      /* The MIPS eabi says only structures containing doubles get passed in a
+         fp register, so force a structure containing a float to be passed in
+         the integer registers.  */
+      else if (mips_abi == ABI_MEABI && struct_p)
+       regbase = GP_ARG_FIRST;
       else
        regbase = (TARGET_SOFT_FLOAT || ! named ? GP_ARG_FIRST : FP_ARG_FIRST);
       break;
@@ -4063,11 +4091,30 @@ function_arg (cum, mode, type, named)
       if (regbase == -1)
        abort ();
 
-      if (! type || TREE_CODE (type) != RECORD_TYPE || mips_abi == ABI_32
-         || mips_abi == ABI_EABI || mips_abi == ABI_O64 || ! named
+      if (! type || TREE_CODE (type) != RECORD_TYPE
+         || mips_abi == ABI_32  || mips_abi == ABI_EABI
+         || mips_abi == ABI_O64 || mips_abi == ABI_MEABI
+         || ! named
          || ! TYPE_SIZE_UNIT (type)
          || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
-       ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
+       {
+
+         unsigned int arg_reg = (regbase + *arg_words + bias);
+         ret = gen_rtx_REG (mode, arg_reg);
+         if (mips_abi == ABI_MEABI
+             && regbase == FP_ARG_FIRST
+             && ! cum->prototype)
+           {
+              /* To make K&R varargs work we need to pass floating
+                 point arguments in both integer and FP registers.  */
+              ret = gen_rtx_PARALLEL (mode,
+                                     gen_rtvec (2,
+                                                gen_rtx_EXPR_LIST (VOIDmode,
+                                                                   gen_rtx_REG (mode,
+                                                                                arg_reg + GP_ARG_FIRST - FP_ARG_FIRST),
+                                                                   const0_rtx),                                                gen_rtx_EXPR_LIST (VOIDmode, ret, const0_rtx)));
+            }
+       }
       else
        {
          /* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the
@@ -4124,6 +4171,7 @@ function_arg (cum, mode, type, named)
                  if (field
                      && int_bit_position (field) == bitpos
                      && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+                     && !TARGET_SOFT_FLOAT
                      && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
                    reg = gen_rtx_REG (DFmode,
                                       regno + FP_ARG_FIRST - GP_ARG_FIRST);
@@ -4164,7 +4212,9 @@ function_arg (cum, mode, type, named)
         calling convention for now.  */
 
       if (struct_p && int_size_in_bytes (type) < UNITS_PER_WORD
-         && ! TARGET_64BIT && mips_abi != ABI_EABI)
+         && ! TARGET_64BIT
+         && mips_abi != ABI_EABI
+         && mips_abi != ABI_MEABI)
        {
          rtx amount = GEN_INT (BITS_PER_WORD
                                - int_size_in_bytes (type) * BITS_PER_UNIT);
@@ -4256,7 +4306,7 @@ function_arg_partial_nregs (cum, mode, type, named)
    Note that the GPR save area is not constant size, due to optimization
      in the prologue.  Hence, we can't use a design with two pointers
      and two offsets, although we could have designed this with two pointers
-     and three offsets. */
+     and three offsets.  */
 
 
 tree
@@ -4319,7 +4369,7 @@ mips_va_start (stdarg_p, valist, nextarg)
   if (mips_abi == ABI_EABI)
     {
       int gpr_save_area_size;
-      /* Note UNITS_PER_WORD is 4 bytes or 8, depending on TARGET_64BIT. */
+      /* Note UNITS_PER_WORD is 4 bytes or 8, depending on TARGET_64BIT.  */
       if (int_arg_words < 8 )
        /* Adjust for the prologue's economy measure */
        gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
@@ -4355,7 +4405,7 @@ mips_va_start (stdarg_p, valist, nextarg)
          /* Emit code setting a pointer into the overflow (shared-stack) area.
             If there were more than 8 non-float formals, or more than 8
             float formals, then this pointer isn't to the base of the area.
-            In that case, it must point to where the first vararg is. */
+            In that case, it must point to where the first vararg is.  */
          size_excess = 0;
          if (float_formals > floats_passed_in_regs)
            size_excess += (float_formals-floats_passed_in_regs) * 8;
@@ -4369,7 +4419,7 @@ mips_va_start (stdarg_p, valist, nextarg)
             take into account the exact sequence of floats and non-floats
             which make up the excess.  That calculation should be rolled
             into the code which sets the current_function_args_info struct.
-            The above then reduces to a fetch from that struct. */
+            The above then reduces to a fetch from that struct.  */
 
 
          t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
@@ -4379,7 +4429,7 @@ mips_va_start (stdarg_p, valist, nextarg)
          t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
          expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-         /* Emit code setting a ptr to the base of the overflow area. */
+         /* Emit code setting a ptr to the base of the overflow area.  */
          t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
          t = build (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
          expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -4389,7 +4439,7 @@ mips_va_start (stdarg_p, valist, nextarg)
             If mips4, this is gpr_save_area_size below the overflow area.
             If mips2, also round down to an 8-byte boundary, since the FPR
             save area is 8-byte aligned, and GPR is 4-byte-aligned.
-            Therefore there can be a 4-byte gap between the save areas. */
+            Therefore there can be a 4-byte gap between the save areas.  */
          gprv = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
          fpr_save_offset = gpr_save_area_size;
          if (!TARGET_64BIT)
@@ -4431,7 +4481,7 @@ mips_va_start (stdarg_p, valist, nextarg)
          /* TARGET_SOFT_FLOAT or TARGET_SINGLE_FLOAT */
 
          /* Everything is in the GPR save area, or in the overflow
-            area which is contiguous with it. */
+            area which is contiguous with it.  */
 
          int offset = -gpr_save_area_size;
          if (gpr_save_area_size == 0)
@@ -4454,6 +4504,8 @@ mips_va_start (stdarg_p, valist, nextarg)
             and both iris5.h and iris6.h define _MIPS_SIM.  */
          if (mips_abi == ABI_N32 || mips_abi == ABI_64)
            ofs = (int_arg_words >= 8 ? -UNITS_PER_WORD : 0);
+         else if (mips_abi == ABI_MEABI)
+           ofs = (int_arg_words >= 8 ? -UNITS_PER_WORD : 0);
          else
            ofs = -UNITS_PER_WORD;
        }
@@ -4496,7 +4548,7 @@ mips_va_arg (valist, type)
       if (TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT)
        {
          /* Case of all args in a merged stack. No need to check bounds,
-            just advance valist along the stack. */
+            just advance valist along the stack.  */
 
          tree gpr = valist;
          if (! indirect
@@ -4534,7 +4586,7 @@ mips_va_arg (valist, type)
          return addr_rtx;
        }
 
-      /* Not a simple merged stack.  Need ptrs and indexes left by va_start. */
+      /* Not a simple merged stack.  Need ptrs and indexes left by va_start.  */
 
       f_ovfl  = TYPE_FIELDS (va_list_type_node);
       f_gtop = TREE_CHAIN (f_ovfl);
@@ -4554,11 +4606,11 @@ mips_va_arg (valist, type)
       if (TREE_CODE (type) == REAL_TYPE)
         {
 
-         /* Emit code to branch if foff == 0. */
+         /* Emit code to branch if foff == 0.  */
           r = expand_expr (foff, NULL_RTX, TYPE_MODE (TREE_TYPE (foff)),
                EXPAND_NORMAL);
-          emit_cmp_and_jump_insns (r, const0_rtx, EQ,
-               const1_rtx, GET_MODE (r), 1, 1, lab_false);
+          emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r),
+                                  1, lab_false);
 
           /* Emit code for addr_rtx = ftop - foff */
           t = build (MINUS_EXPR, TREE_TYPE (ftop), ftop, foff );
@@ -4582,7 +4634,7 @@ mips_va_arg (valist, type)
              /* For mips2, the overflow area contains mixed size items.
                 If a 4-byte int is followed by an 8-byte float, then
                 natural alignment causes a 4 byte gap.
-                So, dynamically adjust ovfl up to a multiple of 8. */
+                So, dynamically adjust ovfl up to a multiple of 8.  */
              t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), ovfl,
                        build_int_2 (7, 0));
              t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, t);
@@ -4591,7 +4643,7 @@ mips_va_arg (valist, type)
            }
 
           /* Emit code for addr_rtx = the ovfl pointer into overflow area.
-            Regardless of mips2, postincrement the ovfl pointer by 8. */
+            Regardless of mips2, postincrement the ovfl pointer by 8.  */
           t = build (POSTINCREMENT_EXPR, TREE_TYPE(ovfl), ovfl,
                size_int (8));
           r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
@@ -4614,33 +4666,33 @@ mips_va_arg (valist, type)
              /* In mips2, int takes 32 bits of the GPR save area, but
                 longlong takes an aligned 64 bits.  So, emit code
                 to zero the low order bits of goff, thus aligning
-                the later calculation of (gtop-goff) upwards. */
+                the later calculation of (gtop-goff) upwards.  */
               t = build (BIT_AND_EXPR, TREE_TYPE (goff), goff,
                        build_int_2 (-8, -1));
               t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
               expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
            }
 
-         /* Emit code to branch if goff == 0. */
+         /* Emit code to branch if goff == 0.  */
           r = expand_expr (goff, NULL_RTX, TYPE_MODE (TREE_TYPE (goff)),
                EXPAND_NORMAL);
-          emit_cmp_and_jump_insns (r, const0_rtx, EQ,
-               const1_rtx, GET_MODE (r), 1, 1, lab_false);
+          emit_cmp_and_jump_insns (r, const0_rtx, EQ, const1_rtx, GET_MODE (r),
+                                  1, lab_false);
 
-          /* Emit code for addr_rtx = gtop - goff. */
+          /* Emit code for addr_rtx = gtop - goff.  */
           t = build (MINUS_EXPR, TREE_TYPE (gtop), gtop, goff);
           r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
           if (r != addr_rtx)
            emit_move_insn (addr_rtx, r);
 
-         /* Note that mips2 int is 32 bit, but mips2 longlong is 64. */
+         /* Note that mips2 int is 32 bit, but mips2 longlong is 64.  */
          if (! TARGET_64BIT && TYPE_PRECISION (type) == 64)
            step_size = 8;
          else
            step_size = UNITS_PER_WORD;
 
           /* Emit code for goff = goff - step_size.
-            Advances the offset up GPR save area over the item. */
+            Advances the offset up GPR save area over the item.  */
           t = build (MINUS_EXPR, TREE_TYPE (goff), goff,
                build_int_2 (step_size, 0));
           t = build (MODIFY_EXPR, TREE_TYPE (goff), goff, t);
@@ -4677,7 +4729,7 @@ mips_va_arg (valist, type)
     }
   else
     {
-      /* Not EABI. */
+      /* Not EABI.  */
       int align;
 
       /* ??? The original va-mips.h did always align, despite the fact
@@ -4735,7 +4787,7 @@ override_options ()
   /* If both single-float and soft-float are set, then clear the one that
      was set by TARGET_DEFAULT, leaving the one that was set by the
      user.  We assume here that the specs prevent both being set by the
-     user. */
+     user.  */
 #ifdef TARGET_DEFAULT
   if (TARGET_SINGLE_FLOAT && TARGET_SOFT_FLOAT)
     target_flags &= ~((TARGET_DEFAULT) & (MASK_SOFT_FLOAT | MASK_SINGLE_FLOAT));
@@ -4764,7 +4816,10 @@ override_options ()
              mips_isa = MIPS_ISA_DEFAULT;
            }
        }
-      else if (mips_isa < 1 || mips_isa > 4)
+      else if (mips_isa < 1
+              || (mips_isa > 4
+                  && mips_isa != 32
+                  && mips_isa != 64))
        {
          error ("-mips%d not supported", mips_isa);
          mips_isa = 1;
@@ -4778,7 +4833,7 @@ override_options ()
     }
 
 #ifdef MIPS_ABI_DEFAULT
-  /* Get the ABI to use. */
+  /* Get the ABI to use.  */
   if (mips_abi_string == (char *) 0)
     mips_abi = MIPS_ABI_DEFAULT;
   else if (! strcmp (mips_abi_string, "32"))
@@ -4791,19 +4846,29 @@ override_options ()
     mips_abi = ABI_64;
   else if (! strcmp (mips_abi_string, "eabi"))
     mips_abi = ABI_EABI;
+  else if (! strcmp (mips_abi_string, "meabi"))
+    mips_abi = ABI_MEABI;
   else
     error ("bad value (%s) for -mabi= switch", mips_abi_string);
 
   /* A specified ISA defaults the ABI if it was not specified.  */
   if (mips_abi_string == 0 && mips_isa_string
-      && mips_abi != ABI_EABI && mips_abi != ABI_O64)
+      && mips_abi != ABI_EABI
+      && mips_abi != ABI_O64
+      && mips_abi != ABI_MEABI)
     {
-      if (! ISA_HAS_64BIT_REGS)
-       mips_abi = ABI_32;
+      if (mips_isa == 64)
+       mips_abi = ABI_O64;
       else
-       mips_abi = ABI_64;
+       {
+         if (! ISA_HAS_64BIT_REGS)
+           mips_abi = ABI_32;
+         else
+           mips_abi = ABI_64;
+       }
     }
 
+#ifdef MIPS_CPU_STRING_DEFAULT
   /* A specified ABI defaults the ISA if it was not specified.  */
   else if (mips_isa_string == 0 && mips_abi_string
           && mips_abi != ABI_EABI && mips_abi != ABI_O64)
@@ -4815,13 +4880,13 @@ override_options ()
       else
        mips_isa = 4;
     }
+#endif
 
   /* If both ABI and ISA were specified, check for conflicts.  */
   else if (mips_isa_string && mips_abi_string)
     {
-      if ((! ISA_HAS_64BIT_REGS && (mips_abi == ABI_N32 || mips_abi == ABI_64
+      if (! ISA_HAS_64BIT_REGS && (mips_abi == ABI_N32 || mips_abi == ABI_64
                             || mips_abi == ABI_O64))
-         || (ISA_HAS_64BIT_REGS && mips_abi == ABI_32))
        error ("-mabi=%s does not support -mips%d", mips_abi_string, mips_isa);
     }
 
@@ -4837,13 +4902,9 @@ override_options ()
          || mips_abi == ABI_64))
     target_flags |= MASK_LONG64;
 
-  /* ??? This doesn't work yet, so don't let people try to use it.  */
-  if (mips_abi == ABI_32)
-    error ("The -mabi=32 support does not work yet.");
-
 #else
   if (mips_abi_string)
-    error ("This target does not support the -mabi switch.");
+    error ("this target does not support the -mabi switch");
 #endif
 
 #ifdef MIPS_CPU_STRING_DEFAULT
@@ -4893,6 +4954,14 @@ override_options ()
          mips_arch_string = "8000";
          mips_arch = PROCESSOR_R8000;
          break;
+       case 32:
+          mips_arch_string = "4kc";
+          mips_arch = PROCESSOR_R4KC;
+          break;
+        case 64:
+          mips_arch_string = "5kc";
+          mips_arch = PROCESSOR_R5KC;
+          break;
        }
     }
   else
@@ -4929,6 +4998,14 @@ override_options ()
          mips_tune_string = "8000";
          mips_tune = PROCESSOR_R8000;
          break;
+       case 32:
+         mips_tune_string = "4kc";
+         mips_tune = PROCESSOR_R4KC;
+         break;
+       case 64:
+         mips_tune_string = "5kc";
+         mips_tune = PROCESSOR_R5KC;
+         break;
        }
 
     }
@@ -4942,16 +5019,14 @@ override_options ()
        }
     }
 
-   /* Handle processor configuration based on architecture.  */
-   if (TARGET_MIPS4100 || TARGET_MIPS3900)
-     target_flags |= MASK_SOFT_FLOAT;
-
-
   if ((mips_arch == PROCESSOR_R3000 && (mips_isa != 1))
+      || (mips_arch == PROCESSOR_R4KC && mips_isa != 32)
+      || ((mips_arch == PROCESSOR_R5KC
+          || mips_arch == PROCESSOR_R20KC) && mips_isa != 64)
       || (mips_arch == PROCESSOR_R6000 && mips_isa != 1 && mips_isa != 2)
       || ((mips_arch == PROCESSOR_R4000
-           || mips_arch == PROCESSOR_R4100
-           || mips_arch == PROCESSOR_R4300
+          || mips_arch == PROCESSOR_R4100
+          || mips_arch == PROCESSOR_R4300
           || mips_arch == PROCESSOR_R4600
           || mips_arch == PROCESSOR_R4650)
          && mips_isa != 1 && mips_isa != 2 && mips_isa != 3))
@@ -5059,7 +5134,7 @@ override_options ()
   if (mips_entry_string != NULL)
     {
       if (*mips_entry_string != '\0')
-       error ("Invalid option `entry%s'", mips_entry_string);
+       error ("invalid option `entry%s'", mips_entry_string);
 
       if (! TARGET_MIPS16)
        warning ("-mentry is only meaningful with -mips-16");
@@ -5159,7 +5234,14 @@ override_options ()
            temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
 
          else if (FP_REG_P (regno))
-           temp = ((TARGET_FLOAT64 || ((regno & 1) == 0))
+           temp = ((TARGET_FLOAT64 || ((regno & 1) == 0)
+                     /* I think this change is OK regardless of abi, but
+                        I'm being cautions untill I can test this more.
+                        HARD_REGNO_MODE_OK is about whether or not you
+                        can move to and from a register without changing
+                        the value, not about whether math works on the
+                        register.  */
+                     || (mips_abi == ABI_MEABI && size <= 4))
                    && (class == MODE_FLOAT
                        || class == MODE_COMPLEX_FLOAT
                        || (TARGET_DEBUG_H_MODE && class == MODE_INT))
@@ -5257,7 +5339,7 @@ mips_debugger_offset (addr, offset)
   /* sdbout_parms does not want this to crash for unrecognized cases.  */
 #if 0
   else if (reg != arg_pointer_rtx)
-    abort_with_insn (addr, "mips_debugger_offset called with non stack/frame/arg pointer.");
+    abort_with_insn (addr, "mips_debugger_offset called with non stack/frame/arg pointer");
 #endif
 
   return offset;
@@ -5449,7 +5531,7 @@ print_operand (file, op, letter)
        break;
 
        default:
-         error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
+         error ("PRINT_OPERAND: unknown punctuation '%c'", letter);
          break;
        }
 
@@ -5641,7 +5723,7 @@ print_operand_address (file, addr)
       {
       case REG:
        if (! TARGET_MIPS16 && REGNO (addr) == ARG_POINTER_REGNUM)
-         abort_with_insn (addr, "Arg pointer not eliminated.");
+         abort_with_insn (addr, "arg pointer not eliminated");
 
        fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
        break;
@@ -5652,11 +5734,11 @@ print_operand_address (file, addr)
          register rtx arg1 = XEXP (addr, 1);
 
          if (! mips_split_addresses)
-           abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, Spurious LO_SUM.");
+           abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, Spurious LO_SUM");
 
          if (GET_CODE (arg0) != REG)
            abort_with_insn (addr,
-                            "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
+                            "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG");
 
          fprintf (file, "%%lo(");
          print_operand_address (file, arg1);
@@ -5693,7 +5775,7 @@ print_operand_address (file, addr)
            abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2");
 
          if (REGNO (reg) == ARG_POINTER_REGNUM)
-           abort_with_insn (addr, "Arg pointer not eliminated.");
+           abort_with_insn (addr, "arg pointer not eliminated");
 
          if (TARGET_MIPS16
              && GET_CODE (offset) == CONST
@@ -5721,7 +5803,29 @@ print_operand_address (file, addr)
        break;
     }
 }
+\f
+/* Target hook for assembling integer objects.  It appears that the Irix
+   6 assembler can't handle 64-bit decimal integers, so avoid printing
+   such an integer here.  */
 
+static bool
+mips_assemble_integer (x, size, aligned_p)
+     rtx x;
+     unsigned int size;
+     int aligned_p;
+{
+  if ((TARGET_64BIT || TARGET_GAS) && size == 8 && aligned_p)
+    {
+      fputs ("\t.dword\t", asm_out_file);
+      if (HOST_BITS_PER_WIDE_INT < 64 || GET_CODE (x) != CONST_INT)
+       output_addr_const (asm_out_file, x);
+      else
+       print_operand (asm_out_file, x, 'X');
+      fputc ('\n', asm_out_file);
+      return true;
+    }
+  return default_assemble_integer (x, size, aligned_p);
+}
 \f
 /* If optimizing for the global pointer, keep track of all of the externs, so
    that at the end of the file, we can emit the appropriate .extern
@@ -5781,7 +5885,7 @@ mips_output_external (file, decl, name)
 #ifdef ASM_OUTPUT_UNDEF_FUNCTION
 int
 mips_output_external_libcall (file, name)
-     FILE *file;
+     FILE *file ATTRIBUTE_UNUSED;
      const char *name;
 {
   register struct extern_list *p;
@@ -5865,7 +5969,6 @@ mips_output_lineno (stream, line)
               LOCAL_LABEL_PREFIX, sym_lineno, ASM_STABN_OP, N_SLINE, line,
               LOCAL_LABEL_PREFIX, sym_lineno);
     }
-
   else
     {
       fprintf (stream, "\n\t%s.loc\t%d %d\n",
@@ -6030,6 +6133,41 @@ mips_asm_file_start (stream)
   if (TARGET_MIPS_AS && optimize && flag_delayed_branch)
     fprintf (stream, "\t.set\tnobopt\n");
 
+  if (TARGET_GAS)
+    {
+#if defined(OBJECT_FORMAT_ELF)
+      /* Generate a special section to describe the ABI switches used to
+        produce the resultant binary.  This used to be done by the assembler
+        setting bits in the ELF header's flags field, but we have run out of
+        bits.  GDB needs this information in order to be able to correctly
+        debug these binaries. See the function mips_gdbarch_init() in
+        gdb/mips-tdep.c.  */
+      const char * abi_string = NULL;
+
+      switch (mips_abi)
+       {
+       case ABI_32:   abi_string = "abi32"; break;
+       case ABI_N32:  abi_string = "abiN32"; break;
+       case ABI_64:   abi_string = "abi64"; break;
+       case ABI_O64:  abi_string = "abiO64"; break;
+       case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
+       case ABI_MEABI:abi_string = TARGET_64BIT ? "meabi64" : "meabi32"; break;
+       default:
+         abort ();
+       }
+      /* Note - we use fprintf directly rather than called named_section()
+        because in this way we can avoid creating an allocated section.  We
+        do not want this section to take up any space in the running
+        executable.  */
+      fprintf (stream, "\t.section .mdebug.%s\n", abi_string);
+
+      /* Restore the default section.  */
+      fprintf (stream, "\t.previous\n");
+#endif
+    }
+
+
+
   /* Generate the pseudo ops that System V.4 wants.  */
 #ifndef ABICALLS_ASM_OP
 #define ABICALLS_ASM_OP "\t.abicalls"
@@ -6114,7 +6252,6 @@ copy_file_data (to, from)
 {
   char buffer[8192];
   size_t len;
-
   rewind (from);
   if (ferror (from))
     fatal_io_error ("can't rewind temp file");
@@ -6152,43 +6289,6 @@ mips_declare_object (stream, name, init_string, final_string, size)
     }
 }
 \f
-/* Output a double precision value to the assembler.  If both the
-   host and target are IEEE, emit the values in hex.  */
-
-void
-mips_output_double (stream, value)
-     FILE *stream;
-     REAL_VALUE_TYPE value;
-{
-#ifdef REAL_VALUE_TO_TARGET_DOUBLE
-  long value_long[2];
-  REAL_VALUE_TO_TARGET_DOUBLE (value, value_long);
-
-  fprintf (stream, "\t.word\t0x%08lx\t\t# %.20g\n\t.word\t0x%08lx\n",
-          value_long[0], value, value_long[1]);
-#else
-  fprintf (stream, "\t.double\t%.20g\n", value);
-#endif
-}
-
-/* Output a single precision value to the assembler.  If both the
-   host and target are IEEE, emit the values in hex.  */
-
-void
-mips_output_float (stream, value)
-     FILE *stream;
-     REAL_VALUE_TYPE value;
-{
-#ifdef REAL_VALUE_TO_TARGET_SINGLE
-  long value_long;
-  REAL_VALUE_TO_TARGET_SINGLE (value, value_long);
-
-  fprintf (stream, "\t.word\t0x%08lx\t\t# %.12g (float)\n", value_long, value);
-#else
-  fprintf (stream, "\t.float\t%.12g\n", value);
-#endif
-}
-\f
 /* Return the bytes needed to compute the frame pointer from the current
    stack pointer.
 
@@ -6365,7 +6465,7 @@ compute_frame_size (size)
      call to mcount.  */
   if (total_size == extra_size
       && (mips_abi == ABI_32 || mips_abi == ABI_O64 || mips_abi == ABI_EABI)
-      && ! profile_flag)
+      && ! current_function_profile)
     total_size = extra_size = 0;
   else if (TARGET_ABICALLS)
     {
@@ -6497,8 +6597,27 @@ mips_annotate_frame_insn (insn, dwarf_pattern)
                                      REG_NOTES (insn));
 }
 
+/* Return a frame-related rtx that stores register REGNO at (SP + OFFSET).
+   The expression should only be used to store single registers.  */
+
+static rtx
+mips_frame_set (mode, regno, offset)
+     enum machine_mode mode;
+     int regno;
+     int offset;
+{
+  rtx address = plus_constant (stack_pointer_rtx, offset);
+  rtx set = gen_rtx_SET (mode,
+                        gen_rtx_MEM (mode, address),
+                        gen_rtx_REG (mode, regno));
+  RTX_FRAME_RELATED_P (set) = 1;
+  return set;
+}
+
+
 /* Emit a move instruction that stores REG in MEM.  Make the instruction
-   frame related and note that it stores REG at (SP + OFFSET).  */
+   frame related and note that it stores REG at (SP + OFFSET).  This
+   function may be asked to store an FPR pair.  */
 
 static void
 mips_emit_frame_related_store (mem, reg, offset)
@@ -6506,11 +6625,24 @@ mips_emit_frame_related_store (mem, reg, offset)
      rtx reg;
      HOST_WIDE_INT offset;
 {
-  rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
-  rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
+  rtx dwarf_expr;
+
+  if (GET_MODE (reg) == DFmode && ! TARGET_FLOAT64)
+    {
+      /* Two registers are being stored, so the frame-related expression
+        must be a PARALLEL rtx with one SET for each register.  The
+        higher numbered register is stored in the lower address on
+        big-endian targets.  */
+      int regno1 = TARGET_BIG_ENDIAN ? REGNO (reg) + 1 : REGNO (reg);
+      int regno2 = TARGET_BIG_ENDIAN ? REGNO (reg) : REGNO (reg) + 1;
+      rtx set1 = mips_frame_set (SFmode, regno1, offset);
+      rtx set2 = mips_frame_set (SFmode, regno2, offset + UNITS_PER_FPREG);
+      dwarf_expr = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set1, set2));
+    }
+  else
+    dwarf_expr = mips_frame_set (GET_MODE (reg), REGNO (reg), offset);
 
-  mips_annotate_frame_insn (emit_move_insn (mem, reg),
-                           gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
+  mips_annotate_frame_insn (emit_move_insn (mem, reg), dwarf_expr);
 }
 
 static void
@@ -6522,6 +6654,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
 {
   long mask = current_frame_info.mask;
   long fmask = current_frame_info.fmask;
+  long real_mask = mask;
   int regno;
   rtx base_reg_rtx;
   HOST_WIDE_INT base_offset;
@@ -6534,6 +6667,12 @@ save_restore_insns (store_p, large_reg, large_offset, file)
       && ! BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST))
     abort ();
 
+  /* Do not restore GP under certain conditions.  */
+  if (! store_p
+      && TARGET_ABICALLS
+      && (mips_abi == ABI_32 || mips_abi == ABI_O64))
+    mask &= ~(1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST));
+
   if (mask == 0 && fmask == 0)
     return;
 
@@ -6558,7 +6697,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
 
       if (gp_offset < 0 || end_offset < 0)
        internal_error
-         ("gp_offset (%ld) or end_offset (%ld) is less than zero.",
+         ("gp_offset (%ld) or end_offset (%ld) is less than zero",
           (long) gp_offset, (long) end_offset);
 
       /* If we see a large frame in mips16 mode, we save the registers
@@ -6648,9 +6787,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
 
                if (store_p)
                  mips_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
-               else if (!TARGET_ABICALLS
-                        || (mips_abi != ABI_32 && mips_abi != ABI_O64)
-                        || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
+               else
                  {
                    emit_move_insn (reg_rtx, mem_rtx);
                    if (TARGET_MIPS16
@@ -6662,50 +6799,50 @@ save_restore_insns (store_p, large_reg, large_offset, file)
              }
            else
              {
-               if (store_p || !TARGET_ABICALLS
-                   || (mips_abi != ABI_32 && mips_abi != ABI_O64)
-                   || regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
+               int r = regno;
+
+               /* The mips16 does not have an instruction to
+                  load $31, so we load $7 instead, and work
+                  things out in the caller.  */
+               if (TARGET_MIPS16 && ! store_p && r == GP_REG_FIRST + 31)
+                 r = GP_REG_FIRST + 7;
+               /* The mips16 sometimes needs to save $18.  */
+               if (TARGET_MIPS16
+                   && regno != GP_REG_FIRST + 31
+                   && ! M16_REG_P (regno))
                  {
-                   int r = regno;
-
-                   /* The mips16 does not have an instruction to
-                       load $31, so we load $7 instead, and work
-                       things out in the caller.  */
-                   if (TARGET_MIPS16 && ! store_p && r == GP_REG_FIRST + 31)
-                     r = GP_REG_FIRST + 7;
-                     /* The mips16 sometimes needs to save $18.  */
-                   if (TARGET_MIPS16
-                       && regno != GP_REG_FIRST + 31
-                       && ! M16_REG_P (regno))
+                   if (! store_p)
+                     r = GP_REG_FIRST + 6;
+                   else
                      {
-                       if (! store_p)
-                         r = GP_REG_FIRST + 6;
-                       else
-                         {
-                           r = GP_REG_FIRST + 3;
-                           fprintf (file, "\tmove\t%s,%s\n",
-                                    reg_names[r], reg_names[regno]);
-                         }
+                       r = GP_REG_FIRST + 3;
+                       fprintf (file, "\tmove\t%s,%s\n",
+                                reg_names[r], reg_names[regno]);
                      }
-                   fprintf (file, "\t%s\t%s,",
-                            (TARGET_64BIT
-                             ? (store_p) ? "sd" : "ld"
-                             : (store_p) ? "sw" : "lw"),
-                            reg_names[r]);
-                   fprintf (file, HOST_WIDE_INT_PRINT_DEC,
-                            gp_offset - base_offset);
-                   fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
-                   if (! store_p
-                       && TARGET_MIPS16
-                       && regno != GP_REG_FIRST + 31
-                       && ! M16_REG_P (regno))
-                     fprintf (file, "\tmove\t%s,%s\n",
-                              reg_names[regno], reg_names[r]);
                  }
-
+               fprintf (file, "\t%s\t%s,",
+                        (TARGET_64BIT
+                         ? (store_p) ? "sd" : "ld"
+                         : (store_p) ? "sw" : "lw"),
+                        reg_names[r]);
+               fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+                        gp_offset - base_offset);
+               fprintf (file, "(%s)\n", reg_names[REGNO(base_reg_rtx)]);
+               if (! store_p
+                   && TARGET_MIPS16
+                   && regno != GP_REG_FIRST + 31
+                   && ! M16_REG_P (regno))
+                 fprintf (file, "\tmove\t%s,%s\n",
+                          reg_names[regno], reg_names[r]);
              }
            gp_offset -= GET_MODE_SIZE (gpr_mode);
          }
+        /* If the restore is being supressed, still take into account
+          the offset at which it is stored.  */
+       else if (BITSET_P (real_mask, regno - GP_REG_FIRST))
+         {
+           gp_offset -= GET_MODE_SIZE (gpr_mode);
+         }
     }
   else
     base_reg_rtx = 0, base_offset  = 0;
@@ -6722,7 +6859,7 @@ save_restore_insns (store_p, large_reg, large_offset, file)
 
       if (fp_offset < 0 || end_offset < 0)
        internal_error
-         ("fp_offset (%ld) or end_offset (%ld) is less than zero.",
+         ("fp_offset (%ld) or end_offset (%ld) is less than zero",
           (long) fp_offset, (long) end_offset);
 
       else if (fp_offset < 32768)
@@ -6813,7 +6950,7 @@ mips_output_function_prologue (file, size)
 #ifndef FUNCTION_NAME_ALREADY_DECLARED
   const char *fnname;
 #endif
-  long tsize = current_frame_info.total_size;
+  HOST_WIDE_INT tsize = current_frame_info.total_size;
 
   ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl));
 
@@ -6857,9 +6994,9 @@ mips_output_function_prologue (file, size)
               (reg_names[(frame_pointer_needed)
                          ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
               ((frame_pointer_needed && TARGET_MIPS16)
-               ? (tsize - current_function_outgoing_args_size)
-               : tsize),
-              reg_names[31 + GP_REG_FIRST],
+               ? ((long) tsize - current_function_outgoing_args_size)
+               : (long) tsize),
+              reg_names[GP_REG_FIRST + 31],
               current_frame_info.var_size,
               current_frame_info.num_gp,
               current_frame_info.num_fp,
@@ -6875,7 +7012,7 @@ mips_output_function_prologue (file, size)
 
       /* Require:
         OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg.
-        HIGHEST_GP_SAVED == *FRAMEREG + FRAMESIZE + GPOFFSET => can find saved regs. */
+        HIGHEST_GP_SAVED == *FRAMEREG + FRAMESIZE + GPOFFSET => can find saved regs.  */
     }
 
   if (mips_entry && ! mips_can_use_return_insn ())
@@ -6936,11 +7073,10 @@ mips_output_function_prologue (file, size)
              || GET_CODE (offset) != CONST_INT)
            continue;
          if (REGNO (base) == (unsigned) STACK_POINTER_REGNUM
-             && (unsigned HOST_WIDE_INT) INTVAL (offset)
-             == tsize + (REGNO (src) - 4) * UNITS_PER_WORD)
+             && INTVAL (offset) == tsize + (REGNO (src) - 4) * UNITS_PER_WORD)
            ;
          else if (REGNO (base) == (unsigned) HARD_FRAME_POINTER_REGNUM
-                  && ((unsigned HOST_WIDE_INT) INTVAL (offset)
+                  && (INTVAL (offset)
                       == (tsize
                           + (REGNO (src) - 4) * UNITS_PER_WORD
                           - current_function_outgoing_args_size)))
@@ -7004,7 +7140,7 @@ mips_output_function_prologue (file, size)
        {
          fprintf (file, "\t%s\t%s,%s,%ld\n",
                   (Pmode == DImode ? "dsubu" : "subu"),
-                  sp_str, sp_str, tsize);
+                  sp_str, sp_str, (long) tsize);
          fprintf (file, "\t.cprestore %ld\n", current_frame_info.args_size);
        }
 
@@ -7053,7 +7189,7 @@ mips_expand_prologue ()
      the varargs special argument, and treat it as part of the
      variable arguments.
 
-     This is only needed if store_args_on_stack is true. */
+     This is only needed if store_args_on_stack is true.  */
 
   INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0);
   regno = GP_ARG_FIRST;
@@ -7129,7 +7265,7 @@ mips_expand_prologue ()
          pattern = RTVEC_ELT (adjust, i);
          if (GET_CODE (pattern) != SET
              || GET_CODE (SET_SRC (pattern)) != ASHIFT)
-           abort_with_insn (pattern, "Insn is not a shift");
+           abort_with_insn (pattern, "insn is not a shift");
          PUT_CODE (SET_SRC (pattern), ASHIFTRT);
 
          insn = emit_insn (pattern);
@@ -7156,7 +7292,7 @@ mips_expand_prologue ()
       int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD;
       rtx ptr = stack_pointer_rtx;
 
-      /* If we are doing svr4-abi, sp has already been decremented by tsize. */
+      /* If we are doing svr4-abi, sp has already been decremented by tsize.  */
       if (TARGET_ABICALLS)
        offset += tsize;
 
@@ -7369,12 +7505,12 @@ mips_expand_prologue ()
   /* If we are profiling, make sure no instructions are scheduled before
      the call to mcount.  */
 
-  if (profile_flag || profile_block_flag)
+  if (current_function_profile)
     emit_insn (gen_blockage ());
 }
 \f
 /* Do any necessary cleanup after a function to restore stack, frame,
-   and regs. */
+   and regs.  */
 
 #define RA_MASK BITMASK_HIGH   /* 1 << 31 */
 #define PIC_OFFSET_TABLE_MASK (1 << (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
@@ -7603,7 +7739,7 @@ mips_can_use_return_insn ()
   if (! reload_completed)
     return 0;
 
-  if (regs_ever_live[31] || profile_flag)
+  if (regs_ever_live[31] || current_function_profile)
     return 0;
 
   /* In mips16 mode, a function which returns a floating point value
@@ -7909,11 +8045,12 @@ function_arg_pass_by_reference (cum, mode, type, named)
      to prevent it, or add code to function.c to properly handle the case.  */
   /* ??? cum can be NULL when called from mips_va_arg.  The problem handled
      here hopefully is not relevant to mips_va_arg.  */
-  if (cum && MUST_PASS_IN_STACK (mode, type))
+  if (cum && MUST_PASS_IN_STACK (mode, type)
+      && mips_abi != ABI_MEABI)
      {
        /* Don't pass the actual CUM to FUNCTION_ARG, because we would
          get double copies of any offsets generated for small structs
-         passed in registers. */
+         passed in registers.  */
        CUMULATIVE_ARGS temp;
        temp = *cum;
        if (FUNCTION_ARG (temp, mode, type, named) != 0)
@@ -8666,7 +8803,7 @@ build_mips16_call_stub (retval, fnmem, arg_size, fp_code)
 
       /* We build the stub code by hand.  That's the only way we can
         do it, since we can't generate 32 bit code during a 16 bit
-        compilation. */
+        compilation.  */
 
       /* We don't want the assembler to insert any nops here.  */
       fprintf (asm_out_file, "\t.set\tnoreorder\n");
@@ -9334,7 +9471,7 @@ machine_dependent_reorg (first)
        {
          /* If we haven't had a barrier within 0x8000 bytes of a
              constant reference or we are at the end of the function,
-             emit a barrier now. */
+             emit a barrier now.  */
 
          rtx label, jump, barrier;
 
@@ -9416,7 +9553,7 @@ mips_adjust_insn_length (insn, length)
    LENGTH is the length (in bytes) of the sequence we are to generate.
    That tells us whether to generate a simple conditional branch, or a
    reversed conditional branch around a `jr' instruction.  */
-char *
+const char *
 mips_output_conditional_branch (insn,
                                operands,
                                two_operands_p,
@@ -9444,9 +9581,9 @@ mips_output_conditional_branch (insn,
      operand.  */
   const char *op2 = (two_operands_p ? ",%z3" : ",%.");
   /* The operand-printing string for the comparison.  */
-  const char *comp = (float_p ? "%F0" : "%C0");
+  const char *const comp = (float_p ? "%F0" : "%C0");
   /* The operand-printing string for the inverted comparison.  */
-  const char *inverted_comp = (float_p ? "%W0" : "%N0");
+  const char *const inverted_comp = (float_p ? "%W0" : "%N0");
 
   /* The MIPS processors (for levels of the ISA at least two), have
      "likely" variants of each branch instruction.  These instructions
@@ -9479,7 +9616,7 @@ mips_output_conditional_branch (insn,
          break;
 
        case LTU:
-         /* A condition which will always be false. */
+         /* A condition which will always be false.  */
          code = NE;
          op1 = "%.";
          break;
@@ -9534,46 +9671,44 @@ mips_output_conditional_branch (insn,
                .set reorder
             l:
 
-          Because we have to jump four bytes *past* the following
-          instruction if this branch was annulled, we can't just use
-          a label, as in the picture above; there's no way to put the
-          label after the next instruction, as the assembler does not
-          accept `.L+4' as the target of a branch.  (We can't just
-          wait until the next instruction is output; it might be a
-          macro and take up more than four bytes.  Once again, we see
-          why we want to eliminate macros.)
-
-          If the branch is annulled, we jump four more bytes that we
-          would otherwise; that way we skip the annulled instruction
-          in the delay slot.  */
-
-       const char *target
-         = ((mips_branch_likely || length == 16) ? ".+16" : ".+12");
-       char *c;
+       */
 
-       strcpy (buffer, "%(%<");
-       c = strchr (buffer, '\0');
-       /* Generate the reversed comparision.  This takes four
+        rtx orig_target;
+       rtx target = gen_label_rtx ();
+
+        output_asm_insn ("%(%<", 0);
+        orig_target = operands[1];
+        operands[1] = target;
+       /* Generate the reversed comparison.  This takes four
           bytes.  */
        if (float_p)
-         sprintf (c, "%%*b%s\t%%Z2%s",
-                  inverted_p ? comp : inverted_comp,
-                  target);
+         sprintf (buffer, "%%*b%s\t%%Z2%%1",
+                  inverted_p ? comp : inverted_comp);
        else
-         sprintf (c, "%%*b%s%s\t%s%s,%s",
+         sprintf (buffer, "%%*b%s%s\t%s%s,%%1",
                   inverted_p ? comp : inverted_comp,
                   need_z_p ? "z" : "",
                   op1,
-                  op2,
-                  target);
-       strcat (c, "\n\tnop\n\tj\t%1");
-       if (length == 16)
-         /* The delay slot was unfilled.  Since we're inside
-            .noreorder, the assembler will not fill in the NOP for
-            us, so we must do it ourselves.  */
-         strcat (buffer, "\n\tnop");
-       strcat (buffer, "%>%)");
-       return buffer;
+                  op2);
+        output_asm_insn (buffer, operands);
+        operands[1] = orig_target;
+
+       output_asm_insn ("nop\n\tj\t%1", operands);
+
+        if (length == 16)
+         output_asm_insn ("nop", 0);
+        else
+          {
+            /* Output delay slot instruction.  */
+            rtx insn = final_sequence;
+            final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
+                             optimize, 0, 1);
+            INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
+          }
+       output_asm_insn ("%>%)", 0);
+        ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
+                                   CODE_LABEL_NUMBER (target));
+        return "";
       }
 
     /* We do not currently use this code.  It handles jumps to
@@ -9624,7 +9759,7 @@ mips_output_conditional_branch (insn,
           anything.  */
 
        /* The target of the reversed branch.  */
-       const char *target
+       const char *const target
          = ((mips_branch_likely || length == 20) ? ".+20" : ".+16");
        const char *at_register = mips_reg_names[ASSEMBLER_SCRATCH_REGNUM];
        const char *gp_register = mips_reg_names[PIC_OFFSET_TABLE_REGNUM];
@@ -9713,6 +9848,8 @@ mips_parse_cpu (cpu_string)
     case '2':
       if (!strcmp (p, "2000") || !strcmp (p, "2k") || !strcmp (p, "2K"))
        cpu = PROCESSOR_R3000;
+      else if (!strcmp (p, "20kc") || !strcmp (p, "20Kc") )
+        cpu = PROCESSOR_R20KC;
       break;
 
     case '3':
@@ -9741,11 +9878,20 @@ mips_parse_cpu (cpu_string)
        cpu = PROCESSOR_R4600;
       else if (!strcmp (p, "4650"))
        cpu = PROCESSOR_R4650;
+      /* The 4kc and 4kp processor cores are the same for
+        scheduling purposes; they both implement the MIPS32
+        ISA and only differ in their memory management
+        methods.  */
+      else if (!strcmp (p, "4kc") || !strcmp (p, "4Kc")
+               || !strcmp (p, "4kp") || !strcmp (p, "4Kp") )
+       cpu = PROCESSOR_R4KC;
       break;
 
     case '5':
       if (!strcmp (p, "5000") || !strcmp (p, "5k") || !strcmp (p, "5K"))
        cpu = PROCESSOR_R5000;
+      else if (!strcmp (p, "5kc") || !strcmp (p, "5Kc") )
+          cpu = PROCESSOR_R5KC;
       break;
 
     case '6':
@@ -9800,7 +9946,7 @@ mips_unique_section (decl, reloc)
   int len, size, sec;
   const char *name, *prefix;
   char *string;
-  static const char *prefixes[4][2] = {
+  static const char *const prefixes[4][2] = {
     { ".text.", ".gnu.linkonce.t." },
     { ".rodata.", ".gnu.linkonce.r." },
     { ".data.", ".gnu.linkonce.d." },
@@ -9863,6 +10009,17 @@ mips_unique_section (decl, reloc)
   DECL_SECTION_NAME (decl) = build_string (len, string);
 }
 
+unsigned int
+mips_hard_regno_nregs (regno, mode)
+    int regno;
+    enum machine_mode mode;
+{
+  if (! FP_REG_P (regno))
+    return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+  else
+    return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
+}
+
 \f
 #ifdef TARGET_IRIX6
 /* Output assembly to switch to section NAME with attribute FLAGS.  */
@@ -9886,7 +10043,6 @@ iris6_asm_named_section_1 (name, flags, align)
     sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
   if (strcmp (name, ".debug_frame") == 0)
     sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
-
   if (flags & SECTION_DEBUG)
     sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
   else if (flags & SECTION_BSS)
@@ -9979,7 +10135,7 @@ iris6_asm_output_align (file, log)
    but takes it from the first .section directive seen.  Play yet more
    file switching games so that we can emit a .section directive at the
    beginning of the file with the proper alignment attached.  */
-   
+
 void
 iris6_asm_file_start (stream)
      FILE *stream;