* hppa-hpux-tdep.c: Update copyright notice and year.
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index fafac66be9dd1e745ddde40c776607ff8dbf2f95..1fc83867a4ce5e0aa928e4713beca8ad4b7e1c91 100644 (file)
 #include "symcat.h"
 #include "sim-regno.h"
 #include "dis-asm.h"
+#include "frame-unwind.h"
+#include "frame-base.h"
+#include "trad-frame.h"
+#include "infcall.h"
+#include "floatformat.h"
+
+static const struct objfile_data *mips_pdr_data;
 
-static void set_reg_offset (CORE_ADDR *saved_regs, int regnum, CORE_ADDR off);
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
 
-/* A useful bit in the CP0 status register (PS_REGNUM).  */
+/* A useful bit in the CP0 status register (MIPS_PS_REGNUM).  */
 /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
 #define ST0_FR (1 << 26)
 
@@ -80,12 +86,6 @@ static const char *mips_abi_strings[] = {
   NULL
 };
 
-struct frame_extra_info
-  {
-    mips_extra_func_info_t proc_desc;
-    int num_args;
-  };
-
 /* Various MIPS ISA options (related to stack analysis) can be
    overridden dynamically.  Establish an enum/array for managing
    them. */
@@ -102,15 +102,14 @@ static const char *size_enums[] = {
 };
 
 /* Some MIPS boards don't support floating point while others only
-   support single-precision floating-point operations.  See also
-   FP_REGISTER_DOUBLE. */
+   support single-precision floating-point operations.  */
 
 enum mips_fpu_type
-  {
-    MIPS_FPU_DOUBLE,           /* Full double precision floating point.  */
-    MIPS_FPU_SINGLE,           /* Single precision floating point (R4650).  */
-    MIPS_FPU_NONE              /* No floating point.  */
-  };
+{
+  MIPS_FPU_DOUBLE,             /* Full double precision floating point.  */
+  MIPS_FPU_SINGLE,             /* Single precision floating point (R4650).  */
+  MIPS_FPU_NONE                        /* No floating point.  */
+};
 
 #ifndef MIPS_DEFAULT_FPU_TYPE
 #define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE
@@ -122,30 +121,53 @@ static int mips_debug = 0;
 
 /* MIPS specific per-architecture information */
 struct gdbarch_tdep
-  {
-    /* from the elf header */
-    int elf_flags;
-
-    /* mips options */
-    enum mips_abi mips_abi;
-    enum mips_abi found_abi;
-    enum mips_fpu_type mips_fpu_type;
-    int mips_last_arg_regnum;
-    int mips_last_fp_arg_regnum;
-    int mips_default_saved_regsize;
-    int mips_fp_register_double;
-    int mips_default_stack_argsize;
-    int default_mask_address_p;
-    /* Is the target using 64-bit raw integer registers but only
-       storing a left-aligned 32-bit value in each?  */
-    int mips64_transfers_32bit_regs_p;
-    /* Indexes for various registers.  IRIX and embedded have
-       different values.  This contains the "public" fields.  Don't
-       add any that do not need to be public.  */
-    const struct mips_regnum *regnum;
-    /* Register names table for the current register set.  */
-    const char **mips_processor_reg_names;
-  };
+{
+  /* from the elf header */
+  int elf_flags;
+
+  /* mips options */
+  enum mips_abi mips_abi;
+  enum mips_abi found_abi;
+  enum mips_fpu_type mips_fpu_type;
+  int mips_last_arg_regnum;
+  int mips_last_fp_arg_regnum;
+  int default_mask_address_p;
+  /* Is the target using 64-bit raw integer registers but only
+     storing a left-aligned 32-bit value in each?  */
+  int mips64_transfers_32bit_regs_p;
+  /* Indexes for various registers.  IRIX and embedded have
+     different values.  This contains the "public" fields.  Don't
+     add any that do not need to be public.  */
+  const struct mips_regnum *regnum;
+  /* Register names table for the current register set.  */
+  const char **mips_processor_reg_names;
+};
+
+static int
+n32n64_floatformat_always_valid (const struct floatformat *fmt,
+                                 const char *from)
+{
+  return 1;
+}
+
+/* FIXME: brobecker/2004-08-08: Long Double values are 128 bit long.
+   They are implemented as a pair of 64bit doubles where the high
+   part holds the result of the operation rounded to double, and
+   the low double holds the difference between the exact result and
+   the rounded result.  So "high" + "low" contains the result with
+   added precision.  Unfortunately, the floatformat structure used
+   by GDB is not powerful enough to describe this format.  As a temporary
+   measure, we define a 128bit floatformat that only uses the high part.
+   We lose a bit of precision but that's probably the best we can do
+   for now with the current infrastructure.  */
+
+static const struct floatformat floatformat_n32n64_long_double_big =
+{
+  floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
+  floatformat_intbit_no,
+  "floatformat_ieee_double_big",
+  n32n64_floatformat_always_valid
+};
 
 const struct mips_regnum *
 mips_regnum (struct gdbarch *gdbarch)
@@ -177,12 +199,6 @@ is_mips16_addr (CORE_ADDR addr)
   return ((addr) & 1);
 }
 
-static CORE_ADDR
-make_mips16_addr (CORE_ADDR addr)
-{
-  return ((addr) | 1);
-}
-
 static CORE_ADDR
 unmake_mips16_addr (CORE_ADDR addr)
 {
@@ -194,9 +210,9 @@ unmake_mips16_addr (CORE_ADDR addr)
 static LONGEST
 read_signed_register (int regnum)
 {
-  void *buf = alloca (register_size (current_gdbarch, regnum));
-  deprecated_read_register_gen (regnum, buf);
-  return (extract_signed_integer (buf, register_size (current_gdbarch, regnum)));
+  LONGEST val;
+  regcache_cooked_read_signed (current_regcache, regnum, &val);
+  return val;
 }
 
 static LONGEST
@@ -227,7 +243,7 @@ mips_abi (struct gdbarch *gdbarch)
 }
 
 int
-mips_regsize (struct gdbarch *gdbarch)
+mips_isa_regsize (struct gdbarch *gdbarch)
 {
   return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
          / gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
@@ -235,16 +251,30 @@ mips_regsize (struct gdbarch *gdbarch)
 
 /* Return the currently configured (or set) saved register size. */
 
-static const char *mips_saved_regsize_string = size_auto;
+static const char *mips_abi_regsize_string = size_auto;
 
-static unsigned int
-mips_saved_regsize (struct gdbarch_tdep *tdep)
+unsigned int
+mips_abi_regsize (struct gdbarch *gdbarch)
 {
-  if (mips_saved_regsize_string == size_auto)
-    return tdep->mips_default_saved_regsize;
-  else if (mips_saved_regsize_string == size_64)
+  if (mips_abi_regsize_string == size_auto)
+    switch (mips_abi (gdbarch))
+      {
+      case MIPS_ABI_EABI32:
+      case MIPS_ABI_O32:
+       return 4;
+      case MIPS_ABI_N32:
+      case MIPS_ABI_N64:
+      case MIPS_ABI_O64:
+      case MIPS_ABI_EABI64:
+       return 8;
+      case MIPS_ABI_UNKNOWN:
+      case MIPS_ABI_LAST:
+      default:
+       internal_error (__FILE__, __LINE__, "bad switch");
+      }
+  else if (mips_abi_regsize_string == size_64)
     return 8;
-  else /* if (mips_saved_regsize_string == size_32) */
+  else                         /* if (mips_abi_regsize_string == size_32) */
     return 4;
 }
 
@@ -259,14 +289,14 @@ mips_saved_regsize (struct gdbarch_tdep *tdep)
    MSYMBOL_IS_SPECIAL   tests the "special" bit in a minimal symbol  */
 
 static void
-mips_elf_make_msymbol_special (asymbol *sym, struct minimal_symbol *msym)
-{
-  if (((elf_symbol_type *)(sym))->internal_elf_sym.st_other == STO_MIPS16) 
-    { 
-      MSYMBOL_INFO (msym) = (char *) 
-       (((long) MSYMBOL_INFO (msym)) | 0x80000000); 
-      SYMBOL_VALUE_ADDRESS (msym) |= 1; 
-    } 
+mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
+{
+  if (((elf_symbol_type *) (sym))->internal_elf_sym.st_other == STO_MIPS16)
+    {
+      MSYMBOL_INFO (msym) = (char *)
+       (((long) MSYMBOL_INFO (msym)) | 0x80000000);
+      SYMBOL_VALUE_ADDRESS (msym) |= 1;
+    }
 }
 
 static int
@@ -282,10 +312,9 @@ msymbol_is_special (struct minimal_symbol *msym)
 
 static void
 mips_xfer_register (struct regcache *regcache, int reg_num, int length,
-                   enum bfd_endian endian, bfd_byte *in, const bfd_byte *out,
-                   int buf_offset)
+                   enum bfd_endian endian, bfd_byte * in,
+                   const bfd_byte * out, int buf_offset)
 {
-  bfd_byte reg[MAX_REGISTER_SIZE];
   int reg_offset = 0;
   gdb_assert (reg_num >= NUM_REGS);
   /* Need to transfer the left or right part of the register, based on
@@ -298,7 +327,7 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length,
     case BFD_ENDIAN_LITTLE:
       reg_offset = 0;
       break;
-    case BFD_ENDIAN_UNKNOWN: /* Indicates no alignment.  */
+    case BFD_ENDIAN_UNKNOWN:   /* Indicates no alignment.  */
       reg_offset = 0;
       break;
     default:
@@ -316,9 +345,11 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length,
        fprintf_unfiltered (gdb_stdlog, "%02x", out[buf_offset + i]);
     }
   if (in != NULL)
-    regcache_cooked_read_part (regcache, reg_num, reg_offset, length, in + buf_offset);
+    regcache_cooked_read_part (regcache, reg_num, reg_offset, length,
+                              in + buf_offset);
   if (out != NULL)
-    regcache_cooked_write_part (regcache, reg_num, reg_offset, length, out + buf_offset);
+    regcache_cooked_write_part (regcache, reg_num, reg_offset, length,
+                               out + buf_offset);
   if (mips_debug && in != NULL)
     {
       int i;
@@ -339,7 +370,8 @@ mips2_fp_compat (void)
 {
   /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
      meaningful.  */
-  if (register_size (current_gdbarch, mips_regnum (current_gdbarch)->fp0) == 4)
+  if (register_size (current_gdbarch, mips_regnum (current_gdbarch)->fp0) ==
+      4)
     return 0;
 
 #if 0
@@ -348,53 +380,38 @@ mips2_fp_compat (void)
   /* Otherwise check the FR bit in the status register - it controls
      the FP compatiblity mode.  If it is clear we are in compatibility
      mode.  */
-  if ((read_register (PS_REGNUM) & ST0_FR) == 0)
+  if ((read_register (MIPS_PS_REGNUM) & ST0_FR) == 0)
     return 1;
 #endif
 
   return 0;
 }
 
-/* Indicate that the ABI makes use of double-precision registers
-   provided by the FPU (rather than combining pairs of registers to
-   form double-precision values).  See also MIPS_FPU_TYPE.  */
-#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
-
 /* The amount of space reserved on the stack for registers. This is
-   different to MIPS_SAVED_REGSIZE as it determines the alignment of
+   different to MIPS_ABI_REGSIZE as it determines the alignment of
    data allocated after the registers have run out. */
 
 static const char *mips_stack_argsize_string = size_auto;
 
 static unsigned int
-mips_stack_argsize (struct gdbarch_tdep *tdep)
+mips_stack_argsize (struct gdbarch *gdbarch)
 {
   if (mips_stack_argsize_string == size_auto)
-    return tdep->mips_default_stack_argsize;
+    return mips_abi_regsize (gdbarch);
   else if (mips_stack_argsize_string == size_64)
     return 8;
-  else /* if (mips_stack_argsize_string == size_32) */
+  else                         /* if (mips_stack_argsize_string == size_32) */
     return 4;
 }
 
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
-static mips_extra_func_info_t heuristic_proc_desc (CORE_ADDR, CORE_ADDR,
-                                                  struct frame_info *, int);
-
 static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
 static CORE_ADDR read_next_frame_reg (struct frame_info *, int);
 
 static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
-static mips_extra_func_info_t find_proc_desc (CORE_ADDR pc,
-                                             struct frame_info *next_frame,
-                                             int cur_frame);
-
-static CORE_ADDR after_prologue (CORE_ADDR pc,
-                                mips_extra_func_info_t proc_desc);
-
 static struct type *mips_float_register_type (void);
 static struct type *mips_double_register_type (void);
 
@@ -407,54 +424,55 @@ static struct cmd_list_element *showmipscmdlist = NULL;
    mips_register_name().  Processor specific registers 32 and above
    are listed in the followign tables.  */
 
-enum { NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+enum
+{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
 
 /* Generic MIPS.  */
 
 static const char *mips_generic_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
-  "sr",        "lo",   "hi",   "bad",  "cause","pc",
-  "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-  "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-  "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-  "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-  "fsr",  "fir",  ""/*"fp"*/,  "",
-  "",  "",     "",     "",     "",     "",     "",     "",
-  "",  "",     "",     "",     "",     "",     "",     "",
+  "sr", "lo", "hi", "bad", "cause", "pc",
+  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+  "fsr", "fir", "" /*"fp" */ , "",
+  "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "",
 };
 
 /* Names of IDT R3041 registers.  */
 
 static const char *mips_r3041_reg_names[] = {
-  "sr",        "lo",   "hi",   "bad",  "cause","pc",
-  "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-  "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-  "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-  "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-  "fsr",  "fir",  "",/*"fp"*/  "",
-  "",  "",     "bus",  "ccfg", "",     "",     "",     "",
-  "",  "",     "port", "cmp",  "",     "",     "epc",  "prid",
+  "sr", "lo", "hi", "bad", "cause", "pc",
+  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+  "fsr", "fir", "", /*"fp" */ "",
+  "", "", "bus", "ccfg", "", "", "", "",
+  "", "", "port", "cmp", "", "", "epc", "prid",
 };
 
 /* Names of tx39 registers.  */
 
 static const char *mips_tx39_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
-  "sr",        "lo",   "hi",   "bad",  "cause","pc",
-  "",   "",    "",     "",     "",     "",     "",     "",
-  "",   "",    "",     "",     "",     "",     "",     "",
-  "",          "",     "",     "",     "",     "",     "",     "",
-  "",          "",     "",     "",     "",     "",     "",     "",
-  "",          "",     "",     "",
-  "",  "",     "",     "",     "",     "",     "",     "",
-  "",  "", "config", "cache", "debug", "depc", "epc",  ""
+  "sr", "lo", "hi", "bad", "cause", "pc",
+  "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "",
+  "", "", "", "",
+  "", "", "", "", "", "", "", "",
+  "", "", "config", "cache", "debug", "depc", "epc", ""
 };
 
 /* Names of IRIX registers.  */
 static const char *mips_irix_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
-  "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-  "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-  "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-  "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-  "pc",        "cause", "bad", "hi",   "lo",   "fsr",  "fir"
+  "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+  "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+  "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+  "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+  "pc", "cause", "bad", "hi", "lo", "fsr", "fir"
 };
 
 
@@ -465,18 +483,18 @@ mips_register_name (int regno)
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   /* GPR names for all ABIs other than n32/n64.  */
   static char *mips_gpr_names[] = {
-    "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
-    "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
-    "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
-    "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra",
+    "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+    "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
+    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+    "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
   };
 
   /* GPR names for n32 and n64 ABIs.  */
   static char *mips_n32_n64_gpr_names[] = {
-    "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3", 
-    "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3", 
-    "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7", 
-    "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
+    "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
+    "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
+    "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+    "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
   };
 
   enum mips_abi abi = mips_abi (current_gdbarch);
@@ -525,8 +543,7 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   /* FIXME: cagney/2003-04-13: Can't yet use gdbarch_num_regs
      (gdbarch), as not all architectures are multi-arch.  */
   raw_p = rawnum < NUM_REGS;
-  if (REGISTER_NAME (regnum) == NULL
-      || REGISTER_NAME (regnum)[0] == '\0')
+  if (REGISTER_NAME (regnum) == NULL || REGISTER_NAME (regnum)[0] == '\0')
     return 0;
   if (reggroup == float_reggroup)
     return float_p && pseudo;
@@ -542,7 +559,7 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   /* Restore the same pseudo register.  */
   if (reggroup == restore_reggroup)
     return raw_p && pseudo;
-  return 0;   
+  return 0;
 }
 
 /* Map the symbol table registers which live in the range [1 *
@@ -557,7 +574,8 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
   if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
     regcache_raw_read (regcache, rawnum, buf);
-  else if (register_size (gdbarch, rawnum) > register_size (gdbarch, cookednum))
+  else if (register_size (gdbarch, rawnum) >
+          register_size (gdbarch, cookednum))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
          || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
@@ -570,14 +588,16 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 }
 
 static void
-mips_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
-                           int cookednum, const void *buf)
+mips_pseudo_register_write (struct gdbarch *gdbarch,
+                           struct regcache *regcache, int cookednum,
+                           const void *buf)
 {
   int rawnum = cookednum % NUM_REGS;
   gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
   if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
     regcache_raw_write (regcache, rawnum, buf);
-  else if (register_size (gdbarch, rawnum) > register_size (gdbarch, cookednum))
+  else if (register_size (gdbarch, rawnum) >
+          register_size (gdbarch, cookednum))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
          || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
@@ -590,8 +610,7 @@ mips_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 }
 
 /* Table to translate MIPS16 register field to actual register number.  */
-static int mips16_to_32_reg[8] =
-{16, 17, 2, 3, 4, 5, 6, 7};
+static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
 
 /* Heuristic_proc_start may hunt through the text section for a long
    time across a 2400 baud serial line.  Allows the user to limit this
@@ -599,30 +618,6 @@ static int mips16_to_32_reg[8] =
 
 static unsigned int heuristic_fence_post = 0;
 
-#define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)  /* least address */
-#define PROC_HIGH_ADDR(proc) ((proc)->high_addr)       /* upper address bound */
-#define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
-#define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
-#define PROC_FRAME_ADJUST(proc)  ((proc)->frame_adjust)
-#define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
-#define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
-#define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
-#define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
-#define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
-/* FIXME drow/2002-06-10: If a pointer on the host is bigger than a long,
-   this will corrupt pdr.iline.  Fortunately we don't use it.  */
-#define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
-#define _PROC_MAGIC_ 0x0F0F0F0F
-#define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
-#define SET_PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym = _PROC_MAGIC_)
-
-struct linked_proc_info
-  {
-    struct mips_extra_func_info info;
-    struct linked_proc_info *next;
-  }
- *linked_proc_desc_table = NULL;
-
 /* Number of bytes of storage in the actual machine representation for
    register N.  NOTE: This defines the pseudo register type so need to
    rebuild the architecture vector.  */
@@ -652,9 +647,9 @@ mips_convert_register_p (int regnum, struct type *type)
 {
   return (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && register_size (current_gdbarch, regnum) == 4
-         && (regnum) >= mips_regnum (current_gdbarch)->fp0 && (regnum) < mips_regnum (current_gdbarch)->fp0 + 32
-         && TYPE_CODE(type) == TYPE_CODE_FLT
-         && TYPE_LENGTH(type) == 8);
+         && (regnum % NUM_REGS) >= mips_regnum (current_gdbarch)->fp0
+         && (regnum % NUM_REGS) < mips_regnum (current_gdbarch)->fp0 + 32
+         && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
 }
 
 static void
@@ -684,16 +679,16 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
       && (regnum % NUM_REGS) < mips_regnum (current_gdbarch)->fp0 + 32)
     {
       /* The floating-point registers raw, or cooked, always match
-         mips_regsize(), and also map 1:1, byte for byte.  */
+         mips_isa_regsize(), and also map 1:1, byte for byte.  */
       switch (gdbarch_byte_order (gdbarch))
        {
        case BFD_ENDIAN_BIG:
-         if (mips_regsize (gdbarch) == 4)
+         if (mips_isa_regsize (gdbarch) == 4)
            return builtin_type_ieee_single_big;
          else
            return builtin_type_ieee_double_big;
        case BFD_ENDIAN_LITTLE:
-         if (mips_regsize (gdbarch) == 4)
+         if (mips_isa_regsize (gdbarch) == 4)
            return builtin_type_ieee_single_little;
          else
            return builtin_type_ieee_double_little;
@@ -702,23 +697,38 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
          internal_error (__FILE__, __LINE__, "bad switch");
        }
     }
-  else if (regnum >= (NUM_REGS + mips_regnum (current_gdbarch)->fp_control_status)
-          && regnum <= NUM_REGS + LAST_EMBED_REGNUM)
-    /* The pseudo/cooked view of the embedded registers is always
-       32-bit.  The raw view is handled below.  */
-    return builtin_type_int32;
-  else if (regnum >= NUM_REGS && mips_regsize (gdbarch)
-          && gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
-    /* The target, while using a 64-bit register buffer, is only
-       transfering 32-bits of each integer register.  Reflect this in
-       the cooked/pseudo register value.  */
-    return builtin_type_int32;
-  else if (mips_regsize (gdbarch) == 8)
-    /* 64-bit ISA.  */
-    return builtin_type_int64;
+  else if (regnum < NUM_REGS)
+    {
+      /* The raw or ISA registers.  These are all sized according to
+        the ISA regsize.  */
+      if (mips_isa_regsize (gdbarch) == 4)
+       return builtin_type_int32;
+      else
+       return builtin_type_int64;
+    }
   else
-    /* 32-bit ISA.  */
-    return builtin_type_int32;
+    {
+      /* The cooked or ABI registers.  These are sized according to
+        the ABI (with a few complications).  */
+      if (regnum >= (NUM_REGS
+                    + mips_regnum (current_gdbarch)->fp_control_status)
+         && regnum <= NUM_REGS + MIPS_LAST_EMBED_REGNUM)
+       /* The pseudo/cooked view of the embedded registers is always
+          32-bit.  The raw view is handled below.  */
+       return builtin_type_int32;
+      else if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
+       /* The target, while possibly using a 64-bit register buffer,
+          is only transfering 32-bits of each integer register.
+          Reflect this in the cooked/pseudo (ABI) register value.  */
+       return builtin_type_int32;
+      else if (mips_abi_regsize (gdbarch) == 4)
+       /* The ABI is restricted to 32-bit registers (the ISA could be
+          32- or 64-bit).  */
+       return builtin_type_int32;
+      else
+       /* 64-bit ABI.  */
+       return builtin_type_int64;
+    }
 }
 
 /* TARGET_READ_SP -- Remove useless bits from the stack pointer.  */
@@ -726,7 +736,7 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
 static CORE_ADDR
 mips_read_sp (void)
 {
-  return read_signed_register (SP_REGNUM);
+  return read_signed_register (MIPS_SP_REGNUM);
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
@@ -745,8 +755,7 @@ mips_mask_address_p (struct gdbarch_tdep *tdep)
     case AUTO_BOOLEAN_AUTO:
       return tdep->default_mask_address_p;
     default:
-      internal_error (__FILE__, __LINE__,
-                     "mips_mask_address_p: bad switch");
+      internal_error (__FILE__, __LINE__, "mips_mask_address_p: bad switch");
       return -1;
     }
 }
@@ -764,46 +773,20 @@ show_mask_address (char *cmd, int from_tty, struct cmd_list_element *c)
       printf_filtered ("The 32 bit mips address mask is disabled\n");
       break;
     case AUTO_BOOLEAN_AUTO:
-      printf_filtered ("The 32 bit address mask is set automatically.  Currently %s\n",
-                      mips_mask_address_p (tdep) ? "enabled" : "disabled");
+      printf_filtered
+       ("The 32 bit address mask is set automatically.  Currently %s\n",
+        mips_mask_address_p (tdep) ? "enabled" : "disabled");
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     "show_mask_address: bad switch");
+      internal_error (__FILE__, __LINE__, "show_mask_address: bad switch");
       break;
     }
 }
 
-/* Should call_function allocate stack space for a struct return?  */
-
-static int
-mips_eabi_use_struct_convention (int gcc_p, struct type *type)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  return (TYPE_LENGTH (type) > 2 * mips_saved_regsize (tdep));
-}
-
-/* Should call_function pass struct by reference? 
-   For each architecture, structs are passed either by
-   value or by reference, depending on their size.  */
-
-static int
-mips_eabi_reg_struct_has_addr (int gcc_p, struct type *type)
-{
-  enum type_code typecode = TYPE_CODE (check_typedef (type));
-  int len = TYPE_LENGTH (check_typedef (type));
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-  if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
-    return (len > mips_saved_regsize (tdep));
-
-  return 0;
-}
-
 /* Tell if the program counter value in MEMADDR is in a MIPS16 function.  */
 
-static int
-pc_is_mips16 (bfd_vma memaddr)
+int
+mips_pc_is_mips16 (CORE_ADDR memaddr)
 {
   struct minimal_symbol *sym;
 
@@ -821,137 +804,63 @@ pc_is_mips16 (bfd_vma memaddr)
     return 0;
 }
 
-/* MIPS believes that the PC has a sign extended value.  Perhaphs the
+/* MIPS believes that the PC has a sign extended value.  Perhaps the
    all registers should be sign extended for simplicity? */
 
 static CORE_ADDR
 mips_read_pc (ptid_t ptid)
 {
-  return read_signed_register_pid (PC_REGNUM, ptid);
+  return read_signed_register_pid (mips_regnum (current_gdbarch)->pc, ptid);
 }
 
-/* This returns the PC of the first inst after the prologue.  If we can't
-   find the prologue, then return 0.  */
-
 static CORE_ADDR
-after_prologue (CORE_ADDR pc,
-               mips_extra_func_info_t proc_desc)
+mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  struct symtab_and_line sal;
-  CORE_ADDR func_addr, func_end;
-
-  /* Pass cur_frame == 0 to find_proc_desc.  We should not attempt
-     to read the stack pointer from the current machine state, because
-     the current machine state has nothing to do with the information
-     we need from the proc_desc; and the process may or may not exist
-     right now.  */
-  if (!proc_desc)
-    proc_desc = find_proc_desc (pc, NULL, 0);
-
-  if (proc_desc)
-    {
-      /* If function is frameless, then we need to do it the hard way.  I
-         strongly suspect that frameless always means prologueless... */
-      if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
-         && PROC_FRAME_OFFSET (proc_desc) == 0)
-       return 0;
-    }
-
-  if (!find_pc_partial_function (pc, NULL, &func_addr, &func_end))
-    return 0;                  /* Unknown */
-
-  sal = find_pc_line (func_addr, 0);
-
-  if (sal.end < func_end)
-    return sal.end;
-
-  /* The line after the prologue is after the end of the function.  In this
-     case, tell the caller to find the prologue the hard way.  */
-
-  return 0;
+  return frame_unwind_register_signed (next_frame,
+                                      NUM_REGS + mips_regnum (gdbarch)->pc);
 }
 
-/* Decode a MIPS32 instruction that saves a register in the stack, and
-   set the appropriate bit in the general register mask or float register mask
-   to indicate which register is saved.  This is a helper function
-   for mips_find_saved_regs.  */
+/* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
+   dummy frame.  The frame ID's base needs to match the TOS value
+   saved by save_dummy_frame_tos(), and the PC match the dummy frame's
+   breakpoint.  */
 
-static void
-mips32_decode_reg_save (t_inst inst, unsigned long *gen_mask,
-                       unsigned long *float_mask)
+static struct frame_id
+mips_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  int reg;
-
-  if ((inst & 0xffe00000) == 0xafa00000                /* sw reg,n($sp) */
-      || (inst & 0xffe00000) == 0xafc00000     /* sw reg,n($r30) */
-      || (inst & 0xffe00000) == 0xffa00000)    /* sd reg,n($sp) */
-    {
-      /* It might be possible to use the instruction to
-         find the offset, rather than the code below which
-         is based on things being in a certain order in the
-         frame, but figuring out what the instruction's offset
-         is relative to might be a little tricky.  */
-      reg = (inst & 0x001f0000) >> 16;
-      *gen_mask |= (1 << reg);
-    }
-  else if ((inst & 0xffe00000) == 0xe7a00000   /* swc1 freg,n($sp) */
-          || (inst & 0xffe00000) == 0xe7c00000         /* swc1 freg,n($r30) */
-          || (inst & 0xffe00000) == 0xf7a00000)        /* sdc1 freg,n($sp) */
-
-    {
-      reg = ((inst & 0x001f0000) >> 16);
-      *float_mask |= (1 << reg);
-    }
+  return frame_id_build (frame_unwind_register_signed (next_frame, NUM_REGS + MIPS_SP_REGNUM),
+                        frame_pc_unwind (next_frame));
 }
 
-/* Decode a MIPS16 instruction that saves a register in the stack, and
-   set the appropriate bit in the general register or float register mask
-   to indicate which register is saved.  This is a helper function
-   for mips_find_saved_regs.  */
-
 static void
-mips16_decode_reg_save (t_inst inst, unsigned long *gen_mask)
+mips_write_pc (CORE_ADDR pc, ptid_t ptid)
 {
-  if ((inst & 0xf800) == 0xd000)       /* sw reg,n($sp) */
-    {
-      int reg = mips16_to_32_reg[(inst & 0x700) >> 8];
-      *gen_mask |= (1 << reg);
-    }
-  else if ((inst & 0xff00) == 0xf900)  /* sd reg,n($sp) */
-    {
-      int reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
-      *gen_mask |= (1 << reg);
-    }
-  else if ((inst & 0xff00) == 0x6200   /* sw $ra,n($sp) */
-          || (inst & 0xff00) == 0xfa00)        /* sd $ra,n($sp) */
-    *gen_mask |= (1 << RA_REGNUM);
+  write_register_pid (mips_regnum (current_gdbarch)->pc, pc, ptid);
 }
 
-
 /* Fetch and return instruction from the specified location.  If the PC
    is odd, assume it's a MIPS16 instruction; otherwise MIPS32.  */
 
-static t_inst
+static ULONGEST
 mips_fetch_instruction (CORE_ADDR addr)
 {
-  char buf[MIPS_INSTLEN];
+  char buf[MIPS_INSN32_SIZE];
   int instlen;
   int status;
 
-  if (pc_is_mips16 (addr))
+  if (mips_pc_is_mips16 (addr))
     {
-      instlen = MIPS16_INSTLEN;
+      instlen = MIPS_INSN16_SIZE;
       addr = unmake_mips16_addr (addr);
     }
   else
-    instlen = MIPS_INSTLEN;
-  status = read_memory_nobpt (addr, buf, instlen);
+    instlen = MIPS_INSN32_SIZE;
+  status = deprecated_read_memory_nobpt (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
 }
 
-
 /* These the fields of 32 bit mips instructions */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
@@ -969,17 +878,10 @@ mips_fetch_instruction (CORE_ADDR addr)
 #define rtype_shamt(x) ((x >> 6) & 0x1f)
 #define rtype_funct(x) (x & 0x3f)
 
-static CORE_ADDR
-mips32_relative_offset (unsigned long inst)
+static LONGEST
+mips32_relative_offset (ULONGEST inst)
 {
-  long x;
-  x = itype_immediate (inst);
-  if (x & 0x8000)              /* sign bit set */
-    {
-      x |= 0xffff0000;         /* sign extension */
-    }
-  x = x << 2;
-  return x;
+  return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2;
 }
 
 /* Determine whate to set a single step breakpoint while considering
@@ -993,7 +895,7 @@ mips32_next_pc (CORE_ADDR pc)
   if ((inst & 0xe0000000) != 0)        /* Not a special, jump or branch instruction */
     {
       if (itype_op (inst) >> 2 == 5)
-                               /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
+       /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
        {
          op = (itype_op (inst) & 0x03);
          switch (op)
@@ -1011,11 +913,13 @@ mips32_next_pc (CORE_ADDR pc)
            }
        }
       else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
-                               /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+       /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
        {
          int tf = itype_rt (inst) & 0x01;
          int cnum = itype_rt (inst) >> 2;
-         int fcrcs = read_signed_register (mips_regnum (current_gdbarch)->fp_control_status);
+         int fcrcs =
+           read_signed_register (mips_regnum (current_gdbarch)->
+                                 fp_control_status);
          int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
 
          if (((cond >> cnum) & 0x01) == tf)
@@ -1045,7 +949,7 @@ mips32_next_pc (CORE_ADDR pc)
              pc += 4;
            }
 
-         break;        /* end SPECIAL */
+         break;                /* end SPECIAL */
        case 1:         /* REGIMM */
          {
            op = itype_rt (inst);       /* branch condition */
@@ -1075,7 +979,7 @@ mips32_next_pc (CORE_ADDR pc)
                pc += 4;
              }
          }
-         break;        /* end REGIMM */
+         break;                /* end REGIMM */
        case 2:         /* J */
        case 3:         /* JAL */
          {
@@ -1110,7 +1014,7 @@ mips32_next_pc (CORE_ADDR pc)
            pc += 8;
          break;
        case 6:         /* BLEZ, BLEZL */
-         if (read_signed_register (itype_rs (inst) <= 0))
+         if (read_signed_register (itype_rs (inst)) <= 0)
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
@@ -1118,7 +1022,7 @@ mips32_next_pc (CORE_ADDR pc)
        case 7:
        default:
        greater_branch: /* BGTZ, BGTZL */
-         if (read_signed_register (itype_rs (inst) > 0))
+         if (read_signed_register (itype_rs (inst)) > 0)
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
@@ -1167,11 +1071,11 @@ enum mips16_inst_fmts
 /* I am heaping all the fields of the formats into one structure and
    then, only the fields which are involved in instruction extension */
 struct upk_mips16
-  {
-    CORE_ADDR offset;
-    unsigned int regx;         /* Function in i8 type */
-    unsigned int regy;
-  };
+{
+  CORE_ADDR offset;
+  unsigned int regx;           /* Function in i8 type */
+  unsigned int regy;
+};
 
 
 /* The EXT-I, EXT-ri nad EXT-I8 instructions all have the same format
@@ -1211,8 +1115,7 @@ static void
 unpack_mips16 (CORE_ADDR pc,
               unsigned int extension,
               unsigned int inst,
-              enum mips16_inst_fmts insn_format,
-              struct upk_mips16 *upk)
+              enum mips16_inst_fmts insn_format, struct upk_mips16 *upk)
 {
   CORE_ADDR offset;
   int regx;
@@ -1226,7 +1129,7 @@ unpack_mips16 (CORE_ADDR pc,
          {
            value = extended_offset (extension);
            value = value << 11;        /* rom for the original value */
-           value |= inst & 0x7ff;              /* eleven bits from instruction */
+           value |= inst & 0x7ff;      /* eleven bits from instruction */
          }
        else
          {
@@ -1285,8 +1188,7 @@ unpack_mips16 (CORE_ADDR pc,
        break;
       }
     default:
-      internal_error (__FILE__, __LINE__,
-                     "bad switch");
+      internal_error (__FILE__, __LINE__, "bad switch");
     }
   upk->offset = offset;
   upk->regx = regx;
@@ -1302,13 +1204,12 @@ add_offset_16 (CORE_ADDR pc, int offset)
 
 static CORE_ADDR
 extended_mips16_next_pc (CORE_ADDR pc,
-                        unsigned int extension,
-                        unsigned int insn)
+                        unsigned int extension, unsigned int insn)
 {
   int op = (insn >> 11);
   switch (op)
     {
-    case 2:            /* Branch */
+    case 2:                    /* Branch */
       {
        CORE_ADDR offset;
        struct upk_mips16 upk;
@@ -1322,7 +1223,7 @@ extended_mips16_next_pc (CORE_ADDR pc,
        pc += (offset << 1) + 2;
        break;
       }
-    case 3:            /* JAL , JALX - Watch out, these are 32 bit instruction */
+    case 3:                    /* JAL , JALX - Watch out, these are 32 bit instruction */
       {
        struct upk_mips16 upk;
        unpack_mips16 (pc, extension, insn, jalxtype, &upk);
@@ -1333,7 +1234,7 @@ extended_mips16_next_pc (CORE_ADDR pc,
          pc |= 0x01;
        break;
       }
-    case 4:            /* beqz */
+    case 4:                    /* beqz */
       {
        struct upk_mips16 upk;
        int reg;
@@ -1345,7 +1246,7 @@ extended_mips16_next_pc (CORE_ADDR pc,
          pc += 2;
        break;
       }
-    case 5:            /* bnez */
+    case 5:                    /* bnez */
       {
        struct upk_mips16 upk;
        int reg;
@@ -1357,7 +1258,7 @@ extended_mips16_next_pc (CORE_ADDR pc,
          pc += 2;
        break;
       }
-    case 12:           /* I8 Formats btez btnez */
+    case 12:                   /* I8 Formats btez btnez */
       {
        struct upk_mips16 upk;
        int reg;
@@ -1372,7 +1273,7 @@ extended_mips16_next_pc (CORE_ADDR pc,
          pc += 2;
        break;
       }
-    case 29:           /* RR Formats JR, JALR, JALR-RA */
+    case 29:                   /* RR Formats JR, JALR, JALR-RA */
       {
        struct upk_mips16 upk;
        /* upk.fmt = rrtype; */
@@ -1389,13 +1290,13 @@ extended_mips16_next_pc (CORE_ADDR pc,
                break;
              case 1:
                reg = 31;
-               break;  /* Function return instruction */
+               break;          /* Function return instruction */
              case 2:
                reg = upk.regx;
                break;
              default:
                reg = 31;
-               break;  /* BOGUS Guess */
+               break;          /* BOGUS Guess */
              }
            pc = read_signed_register (reg);
          }
@@ -1442,224 +1343,783 @@ mips_next_pc (CORE_ADDR pc)
     return mips32_next_pc (pc);
 }
 
-/* Set up the 'saved_regs' array.  This is a data structure containing
-   the addresses on the stack where each register has been saved, for
-   each stack frame.  Registers that have not been saved will have
-   zero here.  The stack pointer register is special: rather than the
-   address where the stack register has been saved,
-   saved_regs[SP_REGNUM] will have the actual value of the previous
-   frame's stack register.  */
+struct mips_frame_cache
+{
+  CORE_ADDR base;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+/* Set a register's saved stack address in temp_saved_regs.  If an
+   address has already been set for this register, do nothing; this
+   way we will only recognize the first save of a given register in a
+   function prologue.
+
+   For simplicity, save the address in both [0 .. NUM_REGS) and
+   [NUM_REGS .. 2*NUM_REGS).  Strictly speaking, only the second range
+   is used as it is only second range (the ABI instead of ISA
+   registers) that comes into play when finding saved registers in a
+   frame.  */
 
 static void
-mips_find_saved_regs (struct frame_info *fci)
-{
-  int ireg;
-  /* r0 bit means kernel trap */
-  int kernel_trap;
-  /* What registers have been saved?  Bitmasks.  */
-  unsigned long gen_mask, float_mask;
-  mips_extra_func_info_t proc_desc;
-  t_inst inst;
-  CORE_ADDR *saved_regs;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+set_reg_offset (struct mips_frame_cache *this_cache, int regnum,
+               CORE_ADDR offset)
+{
+  if (this_cache != NULL
+      && this_cache->saved_regs[regnum].addr == -1)
+    {
+      this_cache->saved_regs[regnum + 0 * NUM_REGS].addr = offset;
+      this_cache->saved_regs[regnum + 1 * NUM_REGS].addr = offset;
+    }
+}
 
-  if (deprecated_get_frame_saved_regs (fci) != NULL)
-    return;
-  saved_regs = frame_saved_regs_zalloc (fci);
-
-  /* If it is the frame for sigtramp, the saved registers are located
-     in a sigcontext structure somewhere on the stack.  If the stack
-     layout for sigtramp changes we might have to change these
-     constants and the companion fixup_sigtramp in mdebugread.c */
-#ifndef SIGFRAME_BASE
-  /* To satisfy alignment restrictions, sigcontext is located 4 bytes
-     above the sigtramp frame.  */
-#define SIGFRAME_BASE          mips_regsize (current_gdbarch)
-/* FIXME!  Are these correct?? */
-#define SIGFRAME_PC_OFF                (SIGFRAME_BASE + 2 * mips_regsize (current_gdbarch))
-#define SIGFRAME_REGSAVE_OFF   (SIGFRAME_BASE + 3 * mips_regsize (current_gdbarch))
-#define SIGFRAME_FPREGSAVE_OFF \
-        (SIGFRAME_REGSAVE_OFF + MIPS_NUMREGS * mips_regsize (current_gdbarch) + 3 * mips_regsize (current_gdbarch))
-#endif
-  if ((get_frame_type (fci) == SIGTRAMP_FRAME))
+
+/* Fetch the immediate value from a MIPS16 instruction.
+   If the previous instruction was an EXTEND, use it to extend
+   the upper bits of the immediate value.  This is a helper function
+   for mips16_scan_prologue.  */
+
+static int
+mips16_get_imm (unsigned short prev_inst,      /* previous instruction */
+               unsigned short inst,    /* current instruction */
+               int nbits,      /* number of bits in imm field */
+               int scale,      /* scale factor to be applied to imm */
+               int is_signed)  /* is the imm field signed? */
+{
+  int offset;
+
+  if ((prev_inst & 0xf800) == 0xf000)  /* prev instruction was EXTEND? */
     {
-      for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
-       {
-         CORE_ADDR reg_position = (get_frame_base (fci) + SIGFRAME_REGSAVE_OFF
-                                   + ireg * mips_regsize (current_gdbarch));
-         set_reg_offset (saved_regs, ireg, reg_position);
-       }
-      for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
-       {
-         CORE_ADDR reg_position = (get_frame_base (fci)
-                                   + SIGFRAME_FPREGSAVE_OFF
-                                   + ireg * mips_regsize (current_gdbarch));
-         set_reg_offset (saved_regs, mips_regnum (current_gdbarch)->fp0 + ireg, reg_position);
-       }
+      offset = ((prev_inst & 0x1f) << 11) | (prev_inst & 0x7e0);
+      if (offset & 0x8000)     /* check for negative extend */
+       offset = 0 - (0x10000 - (offset & 0xffff));
+      return offset | (inst & 0x1f);
+    }
+  else
+    {
+      int max_imm = 1 << nbits;
+      int mask = max_imm - 1;
+      int sign_bit = max_imm >> 1;
 
-      set_reg_offset (saved_regs, PC_REGNUM, get_frame_base (fci) + SIGFRAME_PC_OFF);
-      /* SP_REGNUM, contains the value and not the address.  */
-      set_reg_offset (saved_regs, SP_REGNUM, get_frame_base (fci));
-      return;
+      offset = inst & mask;
+      if (is_signed && (offset & sign_bit))
+       offset = 0 - (max_imm - offset);
+      return offset * scale;
     }
+}
 
-  proc_desc = get_frame_extra_info (fci)->proc_desc;
-  if (proc_desc == NULL)
-    /* I'm not sure how/whether this can happen.  Normally when we
-       can't find a proc_desc, we "synthesize" one using
-       heuristic_proc_desc and set the saved_regs right away.  */
-    return;
 
-  kernel_trap = PROC_REG_MASK (proc_desc) & 1;
-  gen_mask = kernel_trap ? 0xFFFFFFFF : PROC_REG_MASK (proc_desc);
-  float_mask = kernel_trap ? 0xFFFFFFFF : PROC_FREG_MASK (proc_desc);
+/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
+   the associated FRAME_CACHE if not null.
+   Return the address of the first instruction past the prologue.  */
 
-  if (/* In any frame other than the innermost or a frame interrupted
-        by a signal, we assume that all registers have been saved.
-        This assumes that all register saves in a function happen
-        before the first function call.  */
-       (get_next_frame (fci) == NULL
-       || (get_frame_type (get_next_frame (fci)) == SIGTRAMP_FRAME))
+static CORE_ADDR
+mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                      struct frame_info *next_frame,
+                      struct mips_frame_cache *this_cache)
+{
+  CORE_ADDR cur_pc;
+  CORE_ADDR frame_addr = 0;    /* Value of $r17, used as frame pointer */
+  CORE_ADDR sp;
+  long frame_offset = 0;        /* Size of stack frame.  */
+  long frame_adjust = 0;        /* Offset of FP from SP.  */
+  int frame_reg = MIPS_SP_REGNUM;
+  unsigned short prev_inst = 0;        /* saved copy of previous instruction */
+  unsigned inst = 0;           /* current instruction */
+  unsigned entry_inst = 0;     /* the entry instruction */
+  int reg, offset;
 
-       /* In a dummy frame we know exactly where things are saved.  */
-       && !PROC_DESC_IS_DUMMY (proc_desc)
+  int extend_bytes = 0;
+  int prev_extend_bytes;
+  CORE_ADDR end_prologue_addr = 0;
 
-       /* Don't bother unless we are inside a function prologue.
-         Outside the prologue, we know where everything is. */
+  /* Can be called when there's no process, and hence when there's no
+     NEXT_FRAME.  */
+  if (next_frame != NULL)
+    sp = read_next_frame_reg (next_frame, NUM_REGS + MIPS_SP_REGNUM);
+  else
+    sp = 0;
 
-       && in_prologue (get_frame_pc (fci), PROC_LOW_ADDR (proc_desc))
+  if (limit_pc > start_pc + 200)
+    limit_pc = start_pc + 200;
 
-       /* Not sure exactly what kernel_trap means, but if it means the
-         kernel saves the registers without a prologue doing it, we
-         better not examine the prologue to see whether registers
-         have been saved yet.  */
-       && !kernel_trap)
+  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE)
     {
-      /* We need to figure out whether the registers that the
-         proc_desc claims are saved have been saved yet.  */
+      /* Save the previous instruction.  If it's an EXTEND, we'll extract
+         the immediate offset extension from it in mips16_get_imm.  */
+      prev_inst = inst;
 
-      CORE_ADDR addr;
+      /* Fetch and decode the instruction.   */
+      inst = (unsigned short) mips_fetch_instruction (cur_pc);
 
-      /* Bitmasks; set if we have found a save for the register.  */
-      unsigned long gen_save_found = 0;
-      unsigned long float_save_found = 0;
-      int instlen;
+      /* Normally we ignore extend instructions.  However, if it is
+         not followed by a valid prologue instruction, then this
+         instruction is not part of the prologue either.  We must
+         remember in this case to adjust the end_prologue_addr back
+         over the extend.  */
+      if ((inst & 0xf800) == 0xf000)    /* extend */
+        {
+          extend_bytes = MIPS_INSN16_SIZE;
+          continue;
+        }
 
-      /* If the address is odd, assume this is MIPS16 code.  */
-      addr = PROC_LOW_ADDR (proc_desc);
-      instlen = pc_is_mips16 (addr) ? MIPS16_INSTLEN : MIPS_INSTLEN;
+      prev_extend_bytes = extend_bytes;
+      extend_bytes = 0;
 
-      /* Scan through this function's instructions preceding the
-         current PC, and look for those that save registers.  */
-      while (addr < get_frame_pc (fci))
+      if ((inst & 0xff00) == 0x6300    /* addiu sp */
+         || (inst & 0xff00) == 0xfb00) /* daddiu sp */
        {
-         inst = mips_fetch_instruction (addr);
-         if (pc_is_mips16 (addr))
-           mips16_decode_reg_save (inst, &gen_save_found);
+         offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
+         if (offset < 0)       /* negative stack adjustment? */
+           frame_offset -= offset;
          else
-           mips32_decode_reg_save (inst, &gen_save_found, &float_save_found);
-         addr += instlen;
+           /* Exit loop if a positive stack adjustment is found, which
+              usually means that the stack cleanup code in the function
+              epilogue is reached.  */
+           break;
        }
-      gen_mask = gen_save_found;
-      float_mask = float_save_found;
-    }
-
-  /* Fill in the offsets for the registers which gen_mask says were
-     saved.  */
-  {
-    CORE_ADDR reg_position = (get_frame_base (fci)
-                             + PROC_REG_OFFSET (proc_desc));
-    for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1)
-      if (gen_mask & 0x80000000)
+      else if ((inst & 0xf800) == 0xd000)      /* sw reg,n($sp) */
        {
-         set_reg_offset (saved_regs, ireg, reg_position);
-         reg_position -= mips_saved_regsize (tdep);
+         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+         reg = mips16_to_32_reg[(inst & 0x700) >> 8];
+         set_reg_offset (this_cache, reg, sp + offset);
        }
-  }
-
-  /* The MIPS16 entry instruction saves $s0 and $s1 in the reverse
-     order of that normally used by gcc.  Therefore, we have to fetch
-     the first instruction of the function, and if it's an entry
-     instruction that saves $s0 or $s1, correct their saved addresses.  */
-  if (pc_is_mips16 (PROC_LOW_ADDR (proc_desc)))
-    {
-      inst = mips_fetch_instruction (PROC_LOW_ADDR (proc_desc));
-      if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)
-       /* entry */
+      else if ((inst & 0xff00) == 0xf900)      /* sd reg,n($sp) */
        {
-         int reg;
-         int sreg_count = (inst >> 6) & 3;
-
-         /* Check if the ra register was pushed on the stack.  */
-         CORE_ADDR reg_position = (get_frame_base (fci)
-                                   + PROC_REG_OFFSET (proc_desc));
-         if (inst & 0x20)
-           reg_position -= mips_saved_regsize (tdep);
-
-         /* Check if the s0 and s1 registers were pushed on the
-             stack.  */
-         for (reg = 16; reg < sreg_count + 16; reg++)
-           {
-             set_reg_offset (saved_regs, reg, reg_position);
-             reg_position -= mips_saved_regsize (tdep);
-           }
+         offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
+         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+         set_reg_offset (this_cache, reg, sp + offset);
+       }
+      else if ((inst & 0xff00) == 0x6200)      /* sw $ra,n($sp) */
+       {
+         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+         set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
+       }
+      else if ((inst & 0xff00) == 0xfa00)      /* sd $ra,n($sp) */
+       {
+         offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
+         set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
+       }
+      else if (inst == 0x673d) /* move $s1, $sp */
+       {
+         frame_addr = sp;
+         frame_reg = 17;
+       }
+      else if ((inst & 0xff00) == 0x0100)      /* addiu $s1,sp,n */
+       {
+         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
+         frame_addr = sp + offset;
+         frame_reg = 17;
+         frame_adjust = offset;
+       }
+      else if ((inst & 0xFF00) == 0xd900)      /* sw reg,offset($s1) */
+       {
+         offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
+         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+         set_reg_offset (this_cache, reg, frame_addr + offset);
+       }
+      else if ((inst & 0xFF00) == 0x7900)      /* sd reg,offset($s1) */
+       {
+         offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
+         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
+         set_reg_offset (this_cache, reg, frame_addr + offset);
        }
+      else if ((inst & 0xf81f) == 0xe809
+               && (inst & 0x700) != 0x700)     /* entry */
+       entry_inst = inst;      /* save for later processing */
+      else if ((inst & 0xf800) == 0x1800)      /* jal(x) */
+       cur_pc += MIPS_INSN16_SIZE;     /* 32-bit instruction */
+      else if ((inst & 0xff1c) == 0x6704)      /* move reg,$a0-$a3 */
+        {
+          /* This instruction is part of the prologue, but we don't
+             need to do anything special to handle it.  */
+        }
+      else
+        {
+          /* This instruction is not an instruction typically found
+             in a prologue, so we must have reached the end of the
+             prologue.  */
+          if (end_prologue_addr == 0)
+            end_prologue_addr = cur_pc - prev_extend_bytes;
+        }
     }
 
-  /* Fill in the offsets for the registers which float_mask says were
-     saved.  */
-  {
-    CORE_ADDR reg_position = (get_frame_base (fci)
-                             + PROC_FREG_OFFSET (proc_desc));
+  /* The entry instruction is typically the first instruction in a function,
+     and it stores registers at offsets relative to the value of the old SP
+     (before the prologue).  But the value of the sp parameter to this
+     function is the new SP (after the prologue has been executed).  So we
+     can't calculate those offsets until we've seen the entire prologue,
+     and can calculate what the old SP must have been. */
+  if (entry_inst != 0)
+    {
+      int areg_count = (entry_inst >> 8) & 7;
+      int sreg_count = (entry_inst >> 6) & 3;
+
+      /* The entry instruction always subtracts 32 from the SP.  */
+      frame_offset += 32;
+
+      /* Now we can calculate what the SP must have been at the
+         start of the function prologue.  */
+      sp += frame_offset;
 
-    /* Fill in the offsets for the float registers which float_mask
-       says were saved.  */
-    for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1)
-      if (float_mask & 0x80000000)
+      /* Check if a0-a3 were saved in the caller's argument save area.  */
+      for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
        {
-         if (mips_saved_regsize (tdep) == 4
-             && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-           {
-             /* On a big endian 32 bit ABI, floating point registers
-                are paired to form doubles such that the most
-                significant part is in $f[N+1] and the least
-                significant in $f[N] vis: $f[N+1] ||| $f[N].  The
-                registers are also spilled as a pair and stored as a
-                double.
-
-                When little-endian the least significant part is
-                stored first leading to the memory order $f[N] and
-                then $f[N+1].
-
-                Unfortunately, when big-endian the most significant
-                part of the double is stored first, and the least
-                significant is stored second.  This leads to the
-                registers being ordered in memory as firt $f[N+1] and
-                then $f[N].
-
-                For the big-endian case make certain that the
-                addresses point at the correct (swapped) locations
-                $f[N] and $f[N+1] pair (keep in mind that
-                reg_position is decremented each time through the
-                loop).  */
-             if ((ireg & 1))
-               set_reg_offset (saved_regs, mips_regnum (current_gdbarch)->fp0 + ireg,
-                               reg_position - mips_saved_regsize (tdep));
-             else
-               set_reg_offset (saved_regs, mips_regnum (current_gdbarch)->fp0 + ireg,
-                               reg_position + mips_saved_regsize (tdep));
-           }
-         else
-           set_reg_offset (saved_regs, mips_regnum (current_gdbarch)->fp0 + ireg, reg_position);
-         reg_position -= mips_saved_regsize (tdep);
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset += mips_abi_regsize (current_gdbarch);
        }
 
-    set_reg_offset (saved_regs, PC_REGNUM, saved_regs[RA_REGNUM]);
-  }
-
-  /* SP_REGNUM, contains the value and not the address.  */
-  set_reg_offset (saved_regs, SP_REGNUM, get_frame_base (fci));
-}
+      /* Check if the ra register was pushed on the stack.  */
+      offset = -4;
+      if (entry_inst & 0x20)
+       {
+         set_reg_offset (this_cache, MIPS_RA_REGNUM, sp + offset);
+         offset -= mips_abi_regsize (current_gdbarch);
+       }
+
+      /* Check if the s0 and s1 registers were pushed on the stack.  */
+      for (reg = 16; reg < sreg_count + 16; reg++)
+       {
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset -= mips_abi_regsize (current_gdbarch);
+       }
+    }
+
+  if (this_cache != NULL)
+    {
+      this_cache->base =
+        (frame_unwind_register_signed (next_frame, NUM_REGS + frame_reg)
+         + frame_offset - frame_adjust);
+      /* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
+         be able to get rid of the assignment below, evetually. But it's
+         still needed for now.  */
+      this_cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
+        = this_cache->saved_regs[NUM_REGS + MIPS_RA_REGNUM];
+    }
+
+  /* If we didn't reach the end of the prologue when scanning the function
+     instructions, then set end_prologue_addr to the address of the
+     instruction immediately after the last one we scanned.  */
+  if (end_prologue_addr == 0)
+    end_prologue_addr = cur_pc;
+
+  return end_prologue_addr;
+}
+
+/* Heuristic unwinder for 16-bit MIPS instruction set (aka MIPS16).
+   Procedures that use the 32-bit instruction set are handled by the
+   mips_insn32 unwinder.  */
+
+static struct mips_frame_cache *
+mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct mips_frame_cache *cache;
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+  cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  /* Analyze the function prologue.  */
+  {
+    const CORE_ADDR pc = frame_pc_unwind (next_frame);
+    CORE_ADDR start_addr;
+
+    find_pc_partial_function (pc, NULL, &start_addr, NULL);
+    if (start_addr == 0)
+      start_addr = heuristic_proc_start (pc);
+    /* We can't analyze the prologue if we couldn't find the begining
+       of the function.  */
+    if (start_addr == 0)
+      return cache;
+
+    mips16_scan_prologue (start_addr, pc, next_frame, *this_cache);
+  }
+  
+  /* SP_REGNUM, contains the value and not the address.  */
+  trad_frame_set_value (cache->saved_regs, NUM_REGS + MIPS_SP_REGNUM, cache->base);
+
+  return (*this_cache);
+}
+
+static void
+mips_insn16_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                          struct frame_id *this_id)
+{
+  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+                                                          this_cache);
+  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+}
+
+static void
+mips_insn16_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+                                                          this_cache);
+  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind mips_insn16_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_insn16_frame_this_id,
+  mips_insn16_frame_prev_register
+};
+
+static const struct frame_unwind *
+mips_insn16_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  if (mips_pc_is_mips16 (pc))
+    return &mips_insn16_frame_unwind;
+  return NULL;
+}
+
+static CORE_ADDR
+mips_insn16_frame_base_address (struct frame_info *next_frame,
+                               void **this_cache)
+{
+  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+                                                          this_cache);
+  return info->base;
+}
+
+static const struct frame_base mips_insn16_frame_base =
+{
+  &mips_insn16_frame_unwind,
+  mips_insn16_frame_base_address,
+  mips_insn16_frame_base_address,
+  mips_insn16_frame_base_address
+};
+
+static const struct frame_base *
+mips_insn16_frame_base_sniffer (struct frame_info *next_frame)
+{
+  if (mips_insn16_frame_sniffer (next_frame) != NULL)
+    return &mips_insn16_frame_base;
+  else
+    return NULL;
+}
+
+/* Mark all the registers as unset in the saved_regs array
+   of THIS_CACHE.  Do nothing if THIS_CACHE is null.  */
+
+void
+reset_saved_regs (struct mips_frame_cache *this_cache)
+{
+  if (this_cache == NULL || this_cache->saved_regs == NULL)
+    return;
+
+  {
+    const int num_regs = NUM_REGS;
+    int i;
+
+    for (i = 0; i < num_regs; i++)
+      {
+        this_cache->saved_regs[i].addr = -1;
+      }
+  }
+}
+
+/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
+   the associated FRAME_CACHE if not null.  
+   Return the address of the first instruction past the prologue.  */
+
+static CORE_ADDR
+mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                      struct frame_info *next_frame,
+                      struct mips_frame_cache *this_cache)
+{
+  CORE_ADDR cur_pc;
+  CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
+  CORE_ADDR sp;
+  long frame_offset;
+  int  frame_reg = MIPS_SP_REGNUM;
+
+  CORE_ADDR end_prologue_addr = 0;
+  int seen_sp_adjust = 0;
+  int load_immediate_bytes = 0;
+
+  /* Can be called when there's no process, and hence when there's no
+     NEXT_FRAME.  */
+  if (next_frame != NULL)
+    sp = read_next_frame_reg (next_frame, NUM_REGS + MIPS_SP_REGNUM);
+  else
+    sp = 0;
+
+  if (limit_pc > start_pc + 200)
+    limit_pc = start_pc + 200;
+
+restart:
+
+  frame_offset = 0;
+  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN32_SIZE)
+    {
+      unsigned long inst, high_word, low_word;
+      int reg;
+
+      /* Fetch the instruction.   */
+      inst = (unsigned long) mips_fetch_instruction (cur_pc);
+
+      /* Save some code by pre-extracting some useful fields.  */
+      high_word = (inst >> 16) & 0xffff;
+      low_word = inst & 0xffff;
+      reg = high_word & 0x1f;
+
+      if (high_word == 0x27bd  /* addiu $sp,$sp,-i */
+         || high_word == 0x23bd        /* addi $sp,$sp,-i */
+         || high_word == 0x67bd)       /* daddiu $sp,$sp,-i */
+       {
+         if (low_word & 0x8000)        /* negative stack adjustment? */
+            frame_offset += 0x10000 - low_word;
+         else
+           /* Exit loop if a positive stack adjustment is found, which
+              usually means that the stack cleanup code in the function
+              epilogue is reached.  */
+           break;
+          seen_sp_adjust = 1;
+       }
+      else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+       {
+         set_reg_offset (this_cache, reg, sp + low_word);
+       }
+      else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+       {
+         /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra.  */
+         set_reg_offset (this_cache, reg, sp + low_word);
+       }
+      else if (high_word == 0x27be)    /* addiu $30,$sp,size */
+       {
+         /* Old gcc frame, r30 is virtual frame pointer.  */
+         if ((long) low_word != frame_offset)
+           frame_addr = sp + low_word;
+         else if (frame_reg == MIPS_SP_REGNUM)
+           {
+             unsigned alloca_adjust;
+
+             frame_reg = 30;
+             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
+             alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
+             if (alloca_adjust > 0)
+               {
+                  /* FP > SP + frame_size. This may be because of
+                     an alloca or somethings similar.  Fix sp to
+                     "pre-alloca" value, and try again.  */
+                 sp += alloca_adjust;
+                  /* Need to reset the status of all registers.  Otherwise,
+                     we will hit a guard that prevents the new address
+                     for each register to be recomputed during the second
+                     pass.  */
+                  reset_saved_regs (this_cache);
+                 goto restart;
+               }
+           }
+       }
+      /* move $30,$sp.  With different versions of gas this will be either
+         `addu $30,$sp,$zero' or `or $30,$sp,$zero' or `daddu 30,sp,$0'.
+         Accept any one of these.  */
+      else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
+       {
+         /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */
+         if (frame_reg == MIPS_SP_REGNUM)
+           {
+             unsigned alloca_adjust;
+
+             frame_reg = 30;
+             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
+             alloca_adjust = (unsigned) (frame_addr - sp);
+             if (alloca_adjust > 0)
+               {
+                  /* FP > SP + frame_size. This may be because of
+                     an alloca or somethings similar.  Fix sp to
+                     "pre-alloca" value, and try again.  */
+                 sp = frame_addr;
+                  /* Need to reset the status of all registers.  Otherwise,
+                     we will hit a guard that prevents the new address
+                     for each register to be recomputed during the second
+                     pass.  */
+                  reset_saved_regs (this_cache);
+                 goto restart;
+               }
+           }
+       }
+      else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */
+       {
+         set_reg_offset (this_cache, reg, frame_addr + low_word);
+       }
+      else if ((high_word & 0xFFE0) == 0xE7A0 /* swc1 freg,n($sp) */
+               || (high_word & 0xF3E0) == 0xA3C0 /* sx reg,n($s8) */
+               || (inst & 0xFF9F07FF) == 0x00800021 /* move reg,$a0-$a3 */
+               || high_word == 0x3c1c /* lui $gp,n */
+               || high_word == 0x279c /* addiu $gp,$gp,n */
+               || inst == 0x0399e021 /* addu $gp,$gp,$t9 */
+               || inst == 0x033ce021 /* addu $gp,$t9,$gp */
+              )
+       {
+         /* These instructions are part of the prologue, but we don't
+            need to do anything special to handle them.  */
+       }
+      /* The instructions below load $at or $t0 with an immediate
+         value in preparation for a stack adjustment via
+         subu $sp,$sp,[$at,$t0]. These instructions could also
+         initialize a local variable, so we accept them only before
+         a stack adjustment instruction was seen.  */
+      else if (!seen_sp_adjust
+               && (high_word == 0x3c01 /* lui $at,n */
+                   || high_word == 0x3c08 /* lui $t0,n */
+                   || high_word == 0x3421 /* ori $at,$at,n */
+                   || high_word == 0x3508 /* ori $t0,$t0,n */
+                   || high_word == 0x3401 /* ori $at,$zero,n */
+                   || high_word == 0x3408 /* ori $t0,$zero,n */
+                  ))
+       {
+          load_immediate_bytes += MIPS_INSN32_SIZE;            /* FIXME!  */
+       }
+      else
+       {
+         /* This instruction is not an instruction typically found
+            in a prologue, so we must have reached the end of the
+            prologue.  */
+         /* FIXME: brobecker/2004-10-10: Can't we just break out of this
+            loop now?  Why would we need to continue scanning the function
+            instructions?  */
+         if (end_prologue_addr == 0)
+           end_prologue_addr = cur_pc;
+       }
+    }
+
+  if (this_cache != NULL)
+    {
+      this_cache->base = 
+        (frame_unwind_register_signed (next_frame, NUM_REGS + frame_reg)
+         + frame_offset);
+      /* FIXME: brobecker/2004-09-15: We should be able to get rid of
+         this assignment below, eventually.  But it's still needed
+         for now.  */
+      this_cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
+        = this_cache->saved_regs[NUM_REGS + MIPS_RA_REGNUM];
+    }
+
+  /* If we didn't reach the end of the prologue when scanning the function
+     instructions, then set end_prologue_addr to the address of the
+     instruction immediately after the last one we scanned.  */
+  /* brobecker/2004-10-10: I don't think this would ever happen, but
+     we may as well be careful and do our best if we have a null
+     end_prologue_addr.  */
+  if (end_prologue_addr == 0)
+    end_prologue_addr = cur_pc;
+     
+  /* In a frameless function, we might have incorrectly
+     skipped some load immediate instructions. Undo the skipping
+     if the load immediate was not followed by a stack adjustment.  */
+  if (load_immediate_bytes && !seen_sp_adjust)
+    end_prologue_addr -= load_immediate_bytes;
+
+  return end_prologue_addr;
+}
+
+/* Heuristic unwinder for procedures using 32-bit instructions (covers
+   both 32-bit and 64-bit MIPS ISAs).  Procedures using 16-bit
+   instructions (a.k.a. MIPS16) are handled by the mips_insn16
+   unwinder.  */
+
+static struct mips_frame_cache *
+mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  struct mips_frame_cache *cache;
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+
+  cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
+  (*this_cache) = cache;
+  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
+
+  /* Analyze the function prologue.  */
+  {
+    const CORE_ADDR pc = frame_pc_unwind (next_frame);
+    CORE_ADDR start_addr;
+
+    find_pc_partial_function (pc, NULL, &start_addr, NULL);
+    if (start_addr == 0)
+      start_addr = heuristic_proc_start (pc);
+    /* We can't analyze the prologue if we couldn't find the begining
+       of the function.  */
+    if (start_addr == 0)
+      return cache;
+
+    mips32_scan_prologue (start_addr, pc, next_frame, *this_cache);
+  }
+  
+  /* SP_REGNUM, contains the value and not the address.  */
+  trad_frame_set_value (cache->saved_regs, NUM_REGS + MIPS_SP_REGNUM, cache->base);
+
+  return (*this_cache);
+}
+
+static void
+mips_insn32_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                          struct frame_id *this_id)
+{
+  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+                                                          this_cache);
+  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+}
+
+static void
+mips_insn32_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+                                                          this_cache);
+  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind mips_insn32_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_insn32_frame_this_id,
+  mips_insn32_frame_prev_register
+};
+
+static const struct frame_unwind *
+mips_insn32_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  if (! mips_pc_is_mips16 (pc))
+    return &mips_insn32_frame_unwind;
+  return NULL;
+}
+
+static CORE_ADDR
+mips_insn32_frame_base_address (struct frame_info *next_frame,
+                               void **this_cache)
+{
+  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
+                                                          this_cache);
+  return info->base;
+}
+
+static const struct frame_base mips_insn32_frame_base =
+{
+  &mips_insn32_frame_unwind,
+  mips_insn32_frame_base_address,
+  mips_insn32_frame_base_address,
+  mips_insn32_frame_base_address
+};
+
+static const struct frame_base *
+mips_insn32_frame_base_sniffer (struct frame_info *next_frame)
+{
+  if (mips_insn32_frame_sniffer (next_frame) != NULL)
+    return &mips_insn32_frame_base;
+  else
+    return NULL;
+}
+
+static struct trad_frame_cache *
+mips_stub_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  CORE_ADDR pc;
+  CORE_ADDR start_addr;
+  CORE_ADDR stack_addr;
+  struct trad_frame_cache *this_trad_cache;
+
+  if ((*this_cache) != NULL)
+    return (*this_cache);
+  this_trad_cache = trad_frame_cache_zalloc (next_frame);
+  (*this_cache) = this_trad_cache;
+
+  /* The return address is in the link register.  */
+  trad_frame_set_reg_realreg (this_trad_cache, PC_REGNUM, MIPS_RA_REGNUM);
+
+  /* Frame ID, since it's a frameless / stackless function, no stack
+     space is allocated and SP on entry is the current SP.  */
+  pc = frame_pc_unwind (next_frame);
+  find_pc_partial_function (pc, NULL, &start_addr, NULL);
+  stack_addr = frame_unwind_register_signed (next_frame, MIPS_SP_REGNUM);
+  trad_frame_set_id (this_trad_cache, frame_id_build (start_addr, stack_addr));
+
+  /* Assume that the frame's base is the same as the
+     stack-pointer.  */
+  trad_frame_set_this_base (this_trad_cache, stack_addr);
+
+  return this_trad_cache;
+}
+
+static void
+mips_stub_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                        struct frame_id *this_id)
+{
+  struct trad_frame_cache *this_trad_cache
+    = mips_stub_frame_cache (next_frame, this_cache);
+  trad_frame_get_id (this_trad_cache, this_id);
+}
+
+static void
+mips_stub_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
+{
+  struct trad_frame_cache *this_trad_cache
+    = mips_stub_frame_cache (next_frame, this_cache);
+  trad_frame_get_register (this_trad_cache, next_frame, regnum, optimizedp,
+                          lvalp, addrp, realnump, valuep);
+}
+
+static const struct frame_unwind mips_stub_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_stub_frame_this_id,
+  mips_stub_frame_prev_register
+};
+
+static const struct frame_unwind *
+mips_stub_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  if (in_plt_section (pc, NULL))
+    return &mips_stub_frame_unwind;
+  else
+    return NULL;
+}
+
+static CORE_ADDR
+mips_stub_frame_base_address (struct frame_info *next_frame,
+                             void **this_cache)
+{
+  struct trad_frame_cache *this_trad_cache
+    = mips_stub_frame_cache (next_frame, this_cache);
+  return trad_frame_get_this_base (this_trad_cache);
+}
+
+static const struct frame_base mips_stub_frame_base =
+{
+  &mips_stub_frame_unwind,
+  mips_stub_frame_base_address,
+  mips_stub_frame_base_address,
+  mips_stub_frame_base_address
+};
+
+static const struct frame_base *
+mips_stub_frame_base_sniffer (struct frame_info *next_frame)
+{
+  if (mips_stub_frame_sniffer (next_frame) != NULL)
+    return &mips_stub_frame_base;
+  else
+    return NULL;
+}
 
 static CORE_ADDR
 read_next_frame_reg (struct frame_info *fi, int regno)
@@ -1672,12 +2132,6 @@ read_next_frame_reg (struct frame_info *fi, int regno)
       regcache_cooked_read_signed (current_regcache, regno, &val);
       return val;
     }
-  else if ((regno % NUM_REGS) == SP_REGNUM)
-    /* The SP_REGNUM is special, its value is stored in saved_regs.
-       In fact, it is so special that it can even only be fetched
-       using a raw register number!  Once this code as been converted
-       to frame-unwind the problem goes away.  */
-    return frame_unwind_register_signed (fi, regno % NUM_REGS);
   else
     return frame_unwind_register_signed (fi, regno);
 
@@ -1689,8 +2143,7 @@ static CORE_ADDR
 mips_addr_bits_remove (CORE_ADDR addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  if (mips_mask_address_p (tdep)
-      && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
+  if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
     /* This hack is a work-around for existing boards using PMON, the
        simulator, and any other 64-bit targets that doesn't have true
        64-bit addressing.  On these targets, the upper 32 bits of
@@ -1729,7 +2182,7 @@ mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
 
   if (insert_breakpoints_p)
     {
-      pc = read_register (PC_REGNUM);
+      pc = read_register (mips_regnum (current_gdbarch)->pc);
       next_pc = mips_next_pc (pc);
 
       target_insert_breakpoint (next_pc, break_mem);
@@ -1738,113 +2191,36 @@ mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
     target_remove_breakpoint (next_pc, break_mem);
 }
 
-static CORE_ADDR
-mips_init_frame_pc_first (int fromleaf, struct frame_info *prev)
-{
-  CORE_ADDR pc, tmp;
+/* Test whether the PC points to the return instruction at the
+   end of a function. */
 
-  pc = ((fromleaf)
-       ? DEPRECATED_SAVED_PC_AFTER_CALL (get_next_frame (prev))
-       : get_next_frame (prev)
-       ? DEPRECATED_FRAME_SAVED_PC (get_next_frame (prev))
-       : read_pc ());
-  tmp = SKIP_TRAMPOLINE_CODE (pc);
-  return tmp ? tmp : pc;
+static int
+mips_about_to_return (CORE_ADDR pc)
+{
+  if (mips_pc_is_mips16 (pc))
+    /* This mips16 case isn't necessarily reliable.  Sometimes the compiler
+       generates a "jr $ra"; other times it generates code to load
+       the return address from the stack to an accessible register (such
+       as $a3), then a "jr" using that register.  This second case
+       is almost impossible to distinguish from an indirect jump
+       used for switch statements, so we don't even try.  */
+    return mips_fetch_instruction (pc) == 0xe820;      /* jr $ra */
+  else
+    return mips_fetch_instruction (pc) == 0x3e00008;   /* jr $ra */
 }
 
 
+/* This fencepost looks highly suspicious to me.  Removing it also
+   seems suspicious as it could affect remote debugging across serial
+   lines.  */
+
 static CORE_ADDR
-mips_frame_saved_pc (struct frame_info *frame)
+heuristic_proc_start (CORE_ADDR pc)
 {
-  CORE_ADDR saved_pc;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
-    {
-      /* Always unwind the cooked PC register value.  */
-      saved_pc = frame_unwind_register_signed (frame, NUM_REGS + PC_REGNUM);
-    }
-  else
-    {
-      mips_extra_func_info_t proc_desc
-       = get_frame_extra_info (frame)->proc_desc;
-      if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
-       saved_pc = read_memory_integer ((get_frame_base (frame)
-                                        - mips_saved_regsize (tdep))
-                                       , mips_saved_regsize (tdep));
-      else
-       {
-         /* We have to get the saved pc from the sigcontext if it is
-            a signal handler frame.  */
-         int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME ? PC_REGNUM
-                      : proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM);
-         saved_pc = read_next_frame_reg (frame, NUM_REGS + pcreg);
-       }
-    }
-  return ADDR_BITS_REMOVE (saved_pc);
-}
-
-static struct mips_extra_func_info temp_proc_desc;
-
-/* This hack will go away once the get_prev_frame() code has been
-   modified to set the frame's type first.  That is BEFORE init extra
-   frame info et.al.  is called.  This is because it will become
-   possible to skip the init extra info call for sigtramp and dummy
-   frames.  */
-static CORE_ADDR *temp_saved_regs;
-
-/* Set a register's saved stack address in temp_saved_regs.  If an
-   address has already been set for this register, do nothing; this
-   way we will only recognize the first save of a given register in a
-   function prologue.
-
-   For simplicity, save the address in both [0 .. NUM_REGS) and
-   [NUM_REGS .. 2*NUM_REGS).  Strictly speaking, only the second range
-   is used as it is only second range (the ABI instead of ISA
-   registers) that comes into play when finding saved registers in a
-   frame.  */
-
-static void
-set_reg_offset (CORE_ADDR *saved_regs, int regno, CORE_ADDR offset)
-{
-  if (saved_regs[regno] == 0)
-    {
-      saved_regs[regno + 0 * NUM_REGS] = offset;
-      saved_regs[regno + 1 * NUM_REGS] = offset;
-    }
-}
-
-
-/* Test whether the PC points to the return instruction at the
-   end of a function. */
-
-static int
-mips_about_to_return (CORE_ADDR pc)
-{
-  if (pc_is_mips16 (pc))
-    /* This mips16 case isn't necessarily reliable.  Sometimes the compiler
-       generates a "jr $ra"; other times it generates code to load
-       the return address from the stack to an accessible register (such
-       as $a3), then a "jr" using that register.  This second case
-       is almost impossible to distinguish from an indirect jump
-       used for switch statements, so we don't even try.  */
-    return mips_fetch_instruction (pc) == 0xe820;      /* jr $ra */
-  else
-    return mips_fetch_instruction (pc) == 0x3e00008;   /* jr $ra */
-}
-
-
-/* This fencepost looks highly suspicious to me.  Removing it also
-   seems suspicious as it could affect remote debugging across serial
-   lines.  */
-
-static CORE_ADDR
-heuristic_proc_start (CORE_ADDR pc)
-{
-  CORE_ADDR start_pc;
-  CORE_ADDR fence;
-  int instlen;
-  int seen_adjsp = 0;
+  CORE_ADDR start_pc;
+  CORE_ADDR fence;
+  int instlen;
+  int seen_adjsp = 0;
 
   pc = ADDR_BITS_REMOVE (pc);
   start_pc = pc;
@@ -1852,11 +2228,10 @@ heuristic_proc_start (CORE_ADDR pc)
   if (start_pc == 0)
     return 0;
 
-  if (heuristic_fence_post == UINT_MAX
-      || fence < VM_MIN_ADDRESS)
+  if (heuristic_fence_post == UINT_MAX || fence < VM_MIN_ADDRESS)
     fence = VM_MIN_ADDRESS;
 
-  instlen = pc_is_mips16 (pc) ? MIPS16_INSTLEN : MIPS_INSTLEN;
+  instlen = mips_pc_is_mips16 (pc) ? MIPS_INSN16_SIZE : MIPS_INSN32_SIZE;
 
   /* search back for previous return */
   for (start_pc -= instlen;; start_pc -= instlen)
@@ -1870,7 +2245,7 @@ heuristic_proc_start (CORE_ADDR pc)
          {
            static int blurb_printed = 0;
 
-           warning ("Warning: GDB can't find the start of the function at 0x%s.",
+           warning ("GDB can't find the start of the function at 0x%s.",
                     paddr_nz (pc));
 
            if (!blurb_printed)
@@ -1891,15 +2266,14 @@ stack pointer.\n\
     However, if you think GDB should simply search farther back\n\
 from 0x%s for code which looks like the beginning of a\n\
 function, you can increase the range of the search using the `set\n\
-heuristic-fence-post' command.\n",
-                                paddr_nz (pc), paddr_nz (pc));
+heuristic-fence-post' command.\n", paddr_nz (pc), paddr_nz (pc));
                blurb_printed = 1;
              }
          }
 
        return 0;
       }
-    else if (pc_is_mips16 (start_pc))
+    else if (mips_pc_is_mips16 (start_pc))
       {
        unsigned short inst;
 
@@ -1923,808 +2297,381 @@ heuristic-fence-post' command.\n",
       }
     else if (mips_about_to_return (start_pc))
       {
-       start_pc += 2 * MIPS_INSTLEN;   /* skip return, and its delay slot */
+       /* Skip return and its delay slot.  */
+       start_pc += 2 * MIPS_INSN32_SIZE;
        break;
       }
 
   return start_pc;
 }
 
-/* Fetch the immediate value from a MIPS16 instruction.
-   If the previous instruction was an EXTEND, use it to extend
-   the upper bits of the immediate value.  This is a helper function
-   for mips16_heuristic_proc_desc.  */
+struct mips_objfile_private
+{
+  bfd_size_type size;
+  char *contents;
+};
+
+/* According to the current ABI, should the type be passed in a
+   floating-point register (assuming that there is space)?  When there
+   is no FPU, FP are not even considered as possibile candidates for
+   FP registers and, consequently this returns false - forces FP
+   arguments into integer registers. */
 
 static int
-mips16_get_imm (unsigned short prev_inst,      /* previous instruction */
-               unsigned short inst,    /* current instruction */
-               int nbits,              /* number of bits in imm field */
-               int scale,              /* scale factor to be applied to imm */
-               int is_signed)          /* is the imm field signed? */
+fp_register_arg_p (enum type_code typecode, struct type *arg_type)
 {
-  int offset;
+  return ((typecode == TYPE_CODE_FLT
+          || (MIPS_EABI
+              && (typecode == TYPE_CODE_STRUCT
+                  || typecode == TYPE_CODE_UNION)
+              && TYPE_NFIELDS (arg_type) == 1
+              && TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT))
+         && MIPS_FPU_TYPE != MIPS_FPU_NONE);
+}
 
-  if ((prev_inst & 0xf800) == 0xf000)  /* prev instruction was EXTEND? */
+/* On o32, argument passing in GPRs depends on the alignment of the type being
+   passed.  Return 1 if this type must be aligned to a doubleword boundary. */
+
+static int
+mips_type_needs_double_align (struct type *type)
+{
+  enum type_code typecode = TYPE_CODE (type);
+
+  if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+    return 1;
+  else if (typecode == TYPE_CODE_STRUCT)
     {
-      offset = ((prev_inst & 0x1f) << 11) | (prev_inst & 0x7e0);
-      if (offset & 0x8000)     /* check for negative extend */
-       offset = 0 - (0x10000 - (offset & 0xffff));
-      return offset | (inst & 0x1f);
+      if (TYPE_NFIELDS (type) < 1)
+       return 0;
+      return mips_type_needs_double_align (TYPE_FIELD_TYPE (type, 0));
     }
-  else
+  else if (typecode == TYPE_CODE_UNION)
     {
-      int max_imm = 1 << nbits;
-      int mask = max_imm - 1;
-      int sign_bit = max_imm >> 1;
+      int i, n;
 
-      offset = inst & mask;
-      if (is_signed && (offset & sign_bit))
-       offset = 0 - (max_imm - offset);
-      return offset * scale;
+      n = TYPE_NFIELDS (type);
+      for (i = 0; i < n; i++)
+       if (mips_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
+         return 1;
+      return 0;
     }
+  return 0;
 }
 
-
-/* Fill in values in temp_proc_desc based on the MIPS16 instruction
-   stream from start_pc to limit_pc.  */
-
-static void
-mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                           struct frame_info *next_frame, CORE_ADDR sp)
+/* Adjust the address downward (direction of stack growth) so that it
+   is correctly aligned for a new stack frame.  */
+static CORE_ADDR
+mips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
-  CORE_ADDR cur_pc;
-  CORE_ADDR frame_addr = 0;    /* Value of $r17, used as frame pointer */
-  unsigned short prev_inst = 0;        /* saved copy of previous instruction */
-  unsigned inst = 0;           /* current instruction */
-  unsigned entry_inst = 0;     /* the entry instruction */
-  int reg, offset;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  return align_down (addr, 16);
+}
 
-  PROC_FRAME_OFFSET (&temp_proc_desc) = 0;     /* size of stack frame */
-  PROC_FRAME_ADJUST (&temp_proc_desc) = 0;     /* offset of FP from SP */
+static CORE_ADDR
+mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                          struct regcache *regcache, CORE_ADDR bp_addr,
+                          int nargs, struct value **args, CORE_ADDR sp,
+                          int struct_return, CORE_ADDR struct_addr)
+{
+  int argreg;
+  int float_argreg;
+  int argnum;
+  int len = 0;
+  int stack_offset = 0;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
-  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS16_INSTLEN)
-    {
-      /* Save the previous instruction.  If it's an EXTEND, we'll extract
-         the immediate offset extension from it in mips16_get_imm.  */
-      prev_inst = inst;
+  /* For shared libraries, "t9" needs to point at the function
+     address.  */
+  regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr);
 
-      /* Fetch and decode the instruction.   */
-      inst = (unsigned short) mips_fetch_instruction (cur_pc);
-      if ((inst & 0xff00) == 0x6300    /* addiu sp */
-         || (inst & 0xff00) == 0xfb00)         /* daddiu sp */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
-         if (offset < 0)       /* negative stack adjustment? */
-           PROC_FRAME_OFFSET (&temp_proc_desc) -= offset;
-         else
-           /* Exit loop if a positive stack adjustment is found, which
-              usually means that the stack cleanup code in the function
-              epilogue is reached.  */
-           break;
-       }
-      else if ((inst & 0xf800) == 0xd000)      /* sw reg,n($sp) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
-         reg = mips16_to_32_reg[(inst & 0x700) >> 8];
-         PROC_REG_MASK (&temp_proc_desc) |= (1 << reg);
-         set_reg_offset (temp_saved_regs, reg, sp + offset);
-       }
-      else if ((inst & 0xff00) == 0xf900)      /* sd reg,n($sp) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
-         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
-         PROC_REG_MASK (&temp_proc_desc) |= (1 << reg);
-         set_reg_offset (temp_saved_regs, reg, sp + offset);
-       }
-      else if ((inst & 0xff00) == 0x6200)      /* sw $ra,n($sp) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
-         PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
-         set_reg_offset (temp_saved_regs, RA_REGNUM, sp + offset);
-       }
-      else if ((inst & 0xff00) == 0xfa00)      /* sd $ra,n($sp) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
-         PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
-         set_reg_offset (temp_saved_regs, RA_REGNUM, sp + offset);
-       }
-      else if (inst == 0x673d) /* move $s1, $sp */
-       {
-         frame_addr = sp;
-         PROC_FRAME_REG (&temp_proc_desc) = 17;
-       }
-      else if ((inst & 0xff00) == 0x0100)      /* addiu $s1,sp,n */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
-         frame_addr = sp + offset;
-         PROC_FRAME_REG (&temp_proc_desc) = 17;
-         PROC_FRAME_ADJUST (&temp_proc_desc) = offset;
-       }
-      else if ((inst & 0xFF00) == 0xd900)      /* sw reg,offset($s1) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 5, 4, 0);
-         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, frame_addr + offset);
-       }
-      else if ((inst & 0xFF00) == 0x7900)      /* sd reg,offset($s1) */
-       {
-         offset = mips16_get_imm (prev_inst, inst, 5, 8, 0);
-         reg = mips16_to_32_reg[(inst & 0xe0) >> 5];
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, frame_addr + offset);
-       }
-      else if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)   /* entry */
-       entry_inst = inst;      /* save for later processing */
-      else if ((inst & 0xf800) == 0x1800)      /* jal(x) */
-       cur_pc += MIPS16_INSTLEN;       /* 32-bit instruction */
-    }
+  /* Set the return address register to point to the entry point of
+     the program, where a breakpoint lies in wait.  */
+  regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr);
 
-  /* The entry instruction is typically the first instruction in a function,
-     and it stores registers at offsets relative to the value of the old SP
-     (before the prologue).  But the value of the sp parameter to this
-     function is the new SP (after the prologue has been executed).  So we
-     can't calculate those offsets until we've seen the entire prologue,
-     and can calculate what the old SP must have been. */
-  if (entry_inst != 0)
-    {
-      int areg_count = (entry_inst >> 8) & 7;
-      int sreg_count = (entry_inst >> 6) & 3;
+  /* First ensure that the stack and structure return address (if any)
+     are properly aligned.  The stack has to be at least 64-bit
+     aligned even on 32-bit machines, because doubles must be 64-bit
+     aligned.  For n32 and n64, stack frames need to be 128-bit
+     aligned, so we round to this widest known alignment.  */
 
-      /* The entry instruction always subtracts 32 from the SP.  */
-      PROC_FRAME_OFFSET (&temp_proc_desc) += 32;
+  sp = align_down (sp, 16);
+  struct_addr = align_down (struct_addr, 16);
 
-      /* Now we can calculate what the SP must have been at the
-         start of the function prologue.  */
-      sp += PROC_FRAME_OFFSET (&temp_proc_desc);
+  /* Now make space on the stack for the args.  We allocate more
+     than necessary for EABI, because the first few arguments are
+     passed in registers, but that's OK.  */
+  for (argnum = 0; argnum < nargs; argnum++)
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])),
+                    mips_stack_argsize (gdbarch));
+  sp -= align_up (len, 16);
 
-      /* Check if a0-a3 were saved in the caller's argument save area.  */
-      for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
-       {
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, sp + offset);
-         offset += mips_saved_regsize (tdep);
-       }
+  if (mips_debug)
+    fprintf_unfiltered (gdb_stdlog,
+                       "mips_eabi_push_dummy_call: sp=0x%s allocated %ld\n",
+                       paddr_nz (sp), (long) align_up (len, 16));
 
-      /* Check if the ra register was pushed on the stack.  */
-      offset = -4;
-      if (entry_inst & 0x20)
-       {
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << RA_REGNUM;
-         set_reg_offset (temp_saved_regs, RA_REGNUM, sp + offset);
-         offset -= mips_saved_regsize (tdep);
-       }
+  /* Initialize the integer and float register pointers.  */
+  argreg = MIPS_A0_REGNUM;
+  float_argreg = mips_fpa0_regnum (current_gdbarch);
 
-      /* Check if the s0 and s1 registers were pushed on the stack.  */
-      for (reg = 16; reg < sreg_count + 16; reg++)
-       {
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, sp + offset);
-         offset -= mips_saved_regsize (tdep);
-       }
+  /* The struct_return pointer occupies the first parameter-passing reg.  */
+  if (struct_return)
+    {
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "mips_eabi_push_dummy_call: struct_return reg=%d 0x%s\n",
+                           argreg, paddr_nz (struct_addr));
+      write_register (argreg++, struct_addr);
     }
-}
 
-static void
-mips32_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                           struct frame_info *next_frame, CORE_ADDR sp)
-{
-  CORE_ADDR cur_pc;
-  CORE_ADDR frame_addr = 0;    /* Value of $r30. Used by gcc for frame-pointer */
-restart:
-  temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
-  memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
-  PROC_FRAME_OFFSET (&temp_proc_desc) = 0;
-  PROC_FRAME_ADJUST (&temp_proc_desc) = 0;     /* offset of FP from SP */
-  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSTLEN)
+  /* Now load as many as possible of the first arguments into
+     registers, and push the rest onto the stack.  Loop thru args
+     from first to last.  */
+  for (argnum = 0; argnum < nargs; argnum++)
     {
-      unsigned long inst, high_word, low_word;
-      int reg;
-
-      /* Fetch the instruction.   */
-      inst = (unsigned long) mips_fetch_instruction (cur_pc);
+      char *val;
+      char valbuf[MAX_REGISTER_SIZE];
+      struct value *arg = args[argnum];
+      struct type *arg_type = check_typedef (value_type (arg));
+      int len = TYPE_LENGTH (arg_type);
+      enum type_code typecode = TYPE_CODE (arg_type);
 
-      /* Save some code by pre-extracting some useful fields.  */
-      high_word = (inst >> 16) & 0xffff;
-      low_word = inst & 0xffff;
-      reg = high_word & 0x1f;
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stdlog,
+                           "mips_eabi_push_dummy_call: %d len=%d type=%d",
+                           argnum + 1, len, (int) typecode);
 
-      if (high_word == 0x27bd  /* addiu $sp,$sp,-i */
-         || high_word == 0x23bd        /* addi $sp,$sp,-i */
-         || high_word == 0x67bd)       /* daddiu $sp,$sp,-i */
-       {
-         if (low_word & 0x8000)        /* negative stack adjustment? */
-           PROC_FRAME_OFFSET (&temp_proc_desc) += 0x10000 - low_word;
-         else
-           /* Exit loop if a positive stack adjustment is found, which
-              usually means that the stack cleanup code in the function
-              epilogue is reached.  */
-           break;
-       }
-      else if ((high_word & 0xFFE0) == 0xafa0) /* sw reg,offset($sp) */
+      /* The EABI passes structures that do not fit in a register by
+         reference.  */
+      if (len > mips_abi_regsize (gdbarch)
+         && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, sp + low_word);
+         store_unsigned_integer (valbuf, mips_abi_regsize (gdbarch),
+                                 VALUE_ADDRESS (arg));
+         typecode = TYPE_CODE_PTR;
+         len = mips_abi_regsize (gdbarch);
+         val = valbuf;
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stdlog, " push");
        }
-      else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
+      else
+       val = (char *) VALUE_CONTENTS (arg);
+
+      /* 32-bit ABIs always start floating point arguments in an
+         even-numbered floating point register.  Round the FP register
+         up before the check to see if there are any FP registers
+         left.  Non MIPS_EABI targets also pass the FP in the integer
+         registers so also round up normal registers.  */
+      if (mips_abi_regsize (gdbarch) < 8
+         && fp_register_arg_p (typecode, arg_type))
        {
-         /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra,
-            but the register size used is only 32 bits. Make the address
-            for the saved register point to the lower 32 bits.  */
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, sp + low_word + 8 - mips_regsize (current_gdbarch));
+         if ((float_argreg & 1))
+           float_argreg++;
        }
-      else if (high_word == 0x27be)    /* addiu $30,$sp,size */
+
+      /* Floating point arguments passed in registers have to be
+         treated specially.  On 32-bit architectures, doubles
+         are passed in register pairs; the even register gets
+         the low word, and the odd register gets the high word.
+         On non-EABI processors, the first two floating point arguments are
+         also copied to general registers, because MIPS16 functions
+         don't use float registers for arguments.  This duplication of
+         arguments in general registers can't hurt non-MIPS16 functions
+         because those registers are normally skipped.  */
+      /* MIPS_EABI squeezes a struct that contains a single floating
+         point value into an FP register instead of pushing it onto the
+         stack.  */
+      if (fp_register_arg_p (typecode, arg_type)
+         && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         /* Old gcc frame, r30 is virtual frame pointer.  */
-         if ((long) low_word != PROC_FRAME_OFFSET (&temp_proc_desc))
-           frame_addr = sp + low_word;
-         else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
            {
-             unsigned alloca_adjust;
-             PROC_FRAME_REG (&temp_proc_desc) = 30;
-             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
-             alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
-             if (alloca_adjust > 0)
-               {
-                 /* FP > SP + frame_size. This may be because
-                  * of an alloca or somethings similar.
-                  * Fix sp to "pre-alloca" value, and try again.
-                  */
-                 sp += alloca_adjust;
-                 goto restart;
-               }
+             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+             unsigned long regval;
+
+             /* Write the low word of the double to the even register(s).  */
+             regval = extract_unsigned_integer (val + low_offset, 4);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, 4));
+             write_register (float_argreg++, regval);
+
+             /* Write the high word of the double to the odd register(s).  */
+             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, 4));
+             write_register (float_argreg++, regval);
            }
-       }
-      /* move $30,$sp.  With different versions of gas this will be either
-         `addu $30,$sp,$zero' or `or $30,$sp,$zero' or `daddu 30,sp,$0'.
-         Accept any one of these.  */
-      else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
-       {
-         /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */
-         if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+         else
            {
-             unsigned alloca_adjust;
-             PROC_FRAME_REG (&temp_proc_desc) = 30;
-             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
-             alloca_adjust = (unsigned) (frame_addr - sp);
-             if (alloca_adjust > 0)
-               {
-                 /* FP > SP + frame_size. This may be because
-                  * of an alloca or somethings similar.
-                  * Fix sp to "pre-alloca" value, and try again.
-                  */
-                 sp += alloca_adjust;
-                 goto restart;
-               }
+             /* This is a floating point value that fits entirely
+                in a single register.  */
+             /* On 32 bit ABI's the float_argreg is further adjusted
+                above to ensure that it is even register aligned.  */
+             LONGEST regval = extract_unsigned_integer (val, len);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, len));
+             write_register (float_argreg++, regval);
            }
        }
-      else if ((high_word & 0xFFE0) == 0xafc0) /* sw reg,offset($30) */
+      else
        {
-         PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg, frame_addr + low_word);
-       }
-    }
-}
-
-static mips_extra_func_info_t
-heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                    struct frame_info *next_frame, int cur_frame)
-{
-  CORE_ADDR sp;
-
-  if (cur_frame)
-    sp = read_next_frame_reg (next_frame, NUM_REGS + SP_REGNUM);
-  else
-    sp = 0;
-
-  if (start_pc == 0)
-    return NULL;
-  memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
-  temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
-  memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
-  PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
-  PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
-  PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
-
-  if (start_pc + 200 < limit_pc)
-    limit_pc = start_pc + 200;
-  if (pc_is_mips16 (start_pc))
-    mips16_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
-  else
-    mips32_heuristic_proc_desc (start_pc, limit_pc, next_frame, sp);
-  return &temp_proc_desc;
-}
-
-struct mips_objfile_private
-{
-  bfd_size_type size;
-  char *contents;
-};
+         /* Copy the argument to general registers or the stack in
+            register-sized pieces.  Large arguments are split between
+            registers and stack.  */
+         /* Note: structs whose size is not a multiple of
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
 
-/* Global used to communicate between non_heuristic_proc_desc and
-   compare_pdr_entries within qsort ().  */
-static bfd *the_bfd;
+         /* Note: Floating-point values that didn't fit into an FP
+            register are only written to memory.  */
+         while (len > 0)
+           {
+             /* Remember if the argument was written to the stack.  */
+             int stack_used_p = 0;
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
-static int
-compare_pdr_entries (const void *a, const void *b)
-{
-  CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
-  CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
+                                   partial_len);
 
-  if (lhs < rhs)
-    return -1;
-  else if (lhs == rhs)
-    return 0;
-  else
-    return 1;
-}
+             /* Write this portion of the argument to the stack.  */
+             if (argreg > MIPS_LAST_ARG_REGNUM
+                 || odd_sized_struct
+                 || fp_register_arg_p (typecode, arg_type))
+               {
+                 /* Should shorter than int integer values be
+                    promoted to int before being stored? */
+                 int longword_offset = 0;
+                 CORE_ADDR addr;
+                 stack_used_p = 1;
+                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+                   {
+                     if (mips_stack_argsize (gdbarch) == 8
+                         && (typecode == TYPE_CODE_INT
+                             || typecode == TYPE_CODE_PTR
+                             || typecode == TYPE_CODE_FLT) && len <= 4)
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
+                     else if ((typecode == TYPE_CODE_STRUCT
+                               || typecode == TYPE_CODE_UNION)
+                              && (TYPE_LENGTH (arg_type)
+                                  < mips_stack_argsize (gdbarch)))
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
+                   }
 
-static mips_extra_func_info_t
-non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
-{
-  CORE_ADDR startaddr;
-  mips_extra_func_info_t proc_desc;
-  struct block *b = block_for_pc (pc);
-  struct symbol *sym;
-  struct obj_section *sec;
-  struct mips_objfile_private *priv;
+                 if (mips_debug)
+                   {
+                     fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s",
+                                         paddr_nz (stack_offset));
+                     fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s",
+                                         paddr_nz (longword_offset));
+                   }
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
-    return NULL;
+                 addr = sp + stack_offset + longword_offset;
 
-  find_pc_partial_function (pc, NULL, &startaddr, NULL);
-  if (addrptr)
-    *addrptr = startaddr;
+                 if (mips_debug)
+                   {
+                     int i;
+                     fprintf_unfiltered (gdb_stdlog, " @0x%s ",
+                                         paddr_nz (addr));
+                     for (i = 0; i < partial_len; i++)
+                       {
+                         fprintf_unfiltered (gdb_stdlog, "%02x",
+                                             val[i] & 0xff);
+                       }
+                   }
+                 write_memory (addr, val, partial_len);
+               }
 
-  priv = NULL;
+             /* Note!!! This is NOT an else clause.  Odd sized
+                structs may go thru BOTH paths.  Floating point
+                arguments will not.  */
+             /* Write this portion of the argument to a general
+                purpose register.  */
+             if (argreg <= MIPS_LAST_ARG_REGNUM
+                 && !fp_register_arg_p (typecode, arg_type))
+               {
+                 LONGEST regval =
+                   extract_unsigned_integer (val, partial_len);
 
-  sec = find_pc_section (pc);
-  if (sec != NULL)
-    {
-      priv = (struct mips_objfile_private *) sec->objfile->obj_private;
+                 if (mips_debug)
+                   fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
+                                     argreg,
+                                     phex (regval,
+                                           mips_abi_regsize (gdbarch)));
+                 write_register (argreg, regval);
+                 argreg++;
+               }
 
-      /* Search the ".pdr" section generated by GAS.  This includes most of
-        the information normally found in ECOFF PDRs.  */
+             len -= partial_len;
+             val += partial_len;
 
-      the_bfd = sec->objfile->obfd;
-      if (priv == NULL
-         && (the_bfd->format == bfd_object
-             && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour
-             && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64))
-       {
-         /* Right now GAS only outputs the address as a four-byte sequence.
-            This means that we should not bother with this method on 64-bit
-            targets (until that is fixed).  */
-
-         priv = obstack_alloc (& sec->objfile->psymbol_obstack,
-                               sizeof (struct mips_objfile_private));
-         priv->size = 0;
-         sec->objfile->obj_private = priv;
-       }
-      else if (priv == NULL)
-       {
-         asection *bfdsec;
+             /* Compute the the offset into the stack at which we
+                will copy the next parameter.
 
-         priv = obstack_alloc (& sec->objfile->psymbol_obstack,
-                               sizeof (struct mips_objfile_private));
+                In the new EABI (and the NABI32), the stack_offset
+                only needs to be adjusted when it has been used.  */
 
-         bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr");
-         if (bfdsec != NULL)
-           {
-             priv->size = bfd_section_size (sec->objfile->obfd, bfdsec);
-             priv->contents = obstack_alloc (& sec->objfile->psymbol_obstack,
-                                             priv->size);
-             bfd_get_section_contents (sec->objfile->obfd, bfdsec,
-                                       priv->contents, 0, priv->size);
-
-             /* In general, the .pdr section is sorted.  However, in the
-                presence of multiple code sections (and other corner cases)
-                it can become unsorted.  Sort it so that we can use a faster
-                binary search.  */
-             qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries);
+             if (stack_used_p)
+               stack_offset += align_up (partial_len,
+                                         mips_stack_argsize (gdbarch));
            }
-         else
-           priv->size = 0;
-
-         sec->objfile->obj_private = priv;
        }
-      the_bfd = NULL;
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stdlog, "\n");
+    }
 
-      if (priv->size != 0)
-       {
-         int low, mid, high;
-         char *ptr;
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
-         low = 0;
-         high = priv->size / 32;
+  /* Return adjusted stack pointer.  */
+  return sp;
+}
 
-         do
-           {
-             CORE_ADDR pdr_pc;
+/* Determin the return value convention being used.  */
 
-             mid = (low + high) / 2;
+static enum return_value_convention
+mips_eabi_return_value (struct gdbarch *gdbarch,
+                       struct type *type, struct regcache *regcache,
+                       void *readbuf, const void *writebuf)
+{
+  if (TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  if (readbuf)
+    memset (readbuf, 0, TYPE_LENGTH (type));
+  return RETURN_VALUE_REGISTER_CONVENTION;
+}
 
-             ptr = priv->contents + mid * 32;
-             pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
-             pdr_pc += ANOFFSET (sec->objfile->section_offsets,
-                                 SECT_OFF_TEXT (sec->objfile));
-             if (pdr_pc == startaddr)
-               break;
-             if (pdr_pc > startaddr)
-               high = mid;
-             else
-               low = mid + 1;
-           }
-         while (low != high);
 
-         if (low != high)
-           {
-             struct symbol *sym = find_pc_function (pc);
-
-             /* Fill in what we need of the proc_desc.  */
-             proc_desc = (mips_extra_func_info_t)
-               obstack_alloc (&sec->objfile->psymbol_obstack,
-                              sizeof (struct mips_extra_func_info));
-             PROC_LOW_ADDR (proc_desc) = startaddr;
-
-             /* Only used for dummy frames.  */
-             PROC_HIGH_ADDR (proc_desc) = 0;
-
-             PROC_FRAME_OFFSET (proc_desc)
-               = bfd_get_32 (sec->objfile->obfd, ptr + 20);
-             PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                      ptr + 24);
-             PROC_FRAME_ADJUST (proc_desc) = 0;
-             PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                     ptr + 4);
-             PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                      ptr + 12);
-             PROC_REG_OFFSET (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                       ptr + 8);
-             PROC_FREG_OFFSET (proc_desc)
-               = bfd_get_32 (sec->objfile->obfd, ptr + 16);
-             PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
-                                                   ptr + 28);
-             proc_desc->pdr.isym = (long) sym;
-
-             return proc_desc;
-           }
-       }
-    }
+/* N32/N64 ABI stuff.  */
 
-  if (b == NULL)
-    return NULL;
-
-  if (startaddr > BLOCK_START (b))
-    {
-      /* This is the "pathological" case referred to in a comment in
-        print_frame_info.  It might be better to move this check into
-        symbol reading.  */
-      return NULL;
-    }
-
-  sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
-
-  /* If we never found a PDR for this function in symbol reading, then
-     examine prologues to find the information.  */
-  if (sym)
-    {
-      proc_desc = (mips_extra_func_info_t) SYMBOL_VALUE (sym);
-      if (PROC_FRAME_REG (proc_desc) == -1)
-       return NULL;
-      else
-       return proc_desc;
-    }
-  else
-    return NULL;
-}
-
-
-static mips_extra_func_info_t
-find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame)
-{
-  mips_extra_func_info_t proc_desc;
-  CORE_ADDR startaddr = 0;
-
-  proc_desc = non_heuristic_proc_desc (pc, &startaddr);
-
-  if (proc_desc)
-    {
-      /* IF this is the topmost frame AND
-       * (this proc does not have debugging information OR
-       * the PC is in the procedure prologue)
-       * THEN create a "heuristic" proc_desc (by analyzing
-       * the actual code) to replace the "official" proc_desc.
-       */
-      if (next_frame == NULL)
-       {
-         struct symtab_and_line val;
-         struct symbol *proc_symbol =
-           PROC_DESC_IS_DUMMY (proc_desc) ? 0 : PROC_SYMBOL (proc_desc);
-
-         if (proc_symbol)
-           {
-             val = find_pc_line (BLOCK_START
-                                 (SYMBOL_BLOCK_VALUE (proc_symbol)),
-                                 0);
-             val.pc = val.end ? val.end : pc;
-           }
-         if (!proc_symbol || pc < val.pc)
-           {
-             mips_extra_func_info_t found_heuristic =
-               heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
-                                    pc, next_frame, cur_frame);
-             if (found_heuristic)
-               proc_desc = found_heuristic;
-           }
-       }
-    }
-  else
-    {
-      /* Is linked_proc_desc_table really necessary?  It only seems to be used
-         by procedure call dummys.  However, the procedures being called ought
-         to have their own proc_descs, and even if they don't,
-         heuristic_proc_desc knows how to create them! */
-
-      struct linked_proc_info *link;
-
-      for (link = linked_proc_desc_table; link; link = link->next)
-       if (PROC_LOW_ADDR (&link->info) <= pc
-           && PROC_HIGH_ADDR (&link->info) > pc)
-         return &link->info;
-
-      if (startaddr == 0)
-       startaddr = heuristic_proc_start (pc);
-
-      proc_desc =
-       heuristic_proc_desc (startaddr, pc, next_frame, cur_frame);
-    }
-  return proc_desc;
-}
-
-static CORE_ADDR
-get_frame_pointer (struct frame_info *frame,
-                  mips_extra_func_info_t proc_desc)
-{
-  return (read_next_frame_reg (frame, NUM_REGS + PROC_FRAME_REG (proc_desc))
-         + PROC_FRAME_OFFSET (proc_desc)
-         - PROC_FRAME_ADJUST (proc_desc));
-}
-
-static mips_extra_func_info_t cached_proc_desc;
-
-static CORE_ADDR
-mips_frame_chain (struct frame_info *frame)
-{
-  mips_extra_func_info_t proc_desc;
-  CORE_ADDR tmp;
-  CORE_ADDR saved_pc = DEPRECATED_FRAME_SAVED_PC (frame);
-
-  /* Check if the PC is inside a call stub.  If it is, fetch the
-     PC of the caller of that stub.  */
-  if ((tmp = SKIP_TRAMPOLINE_CODE (saved_pc)) != 0)
-    saved_pc = tmp;
-
-  if (DEPRECATED_PC_IN_CALL_DUMMY (saved_pc, 0, 0))
-    {
-      /* A dummy frame, uses SP not FP.  Get the old SP value.  If all
-         is well, frame->frame the bottom of the current frame will
-         contain that value.  */
-      return get_frame_base (frame);
-    }
-
-  /* Look up the procedure descriptor for this PC.  */
-  proc_desc = find_proc_desc (saved_pc, frame, 1);
-  if (!proc_desc)
-    return 0;
-
-  cached_proc_desc = proc_desc;
-
-  /* If no frame pointer and frame size is zero, we must be at end
-     of stack (or otherwise hosed).  If we don't check frame size,
-     we loop forever if we see a zero size frame.  */
-  if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
-      && PROC_FRAME_OFFSET (proc_desc) == 0
-      /* The previous frame from a sigtramp frame might be frameless
-        and have frame size zero.  */
-      && !(get_frame_type (frame) == SIGTRAMP_FRAME)
-      /* For a generic dummy frame, let get_frame_pointer() unwind a
-         register value saved as part of the dummy frame call.  */
-      && !(DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0)))
-    return 0;
-  else
-    return get_frame_pointer (frame, proc_desc);
-}
-
-static void
-mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
-{
-  int regnum;
-  mips_extra_func_info_t proc_desc;
-
-  if (get_frame_type (fci) == DUMMY_FRAME)
-    return;
-
-  /* Use proc_desc calculated in frame_chain.  When there is no
-     next frame, i.e, get_next_frame (fci) == NULL, we call
-     find_proc_desc () to calculate it, passing an explicit
-     NULL as the frame parameter.  */
-  proc_desc =
-    get_next_frame (fci)
-    ? cached_proc_desc
-    : find_proc_desc (get_frame_pc (fci),
-                      NULL /* i.e, get_next_frame (fci) */,
-                     1);
-
-  frame_extra_info_zalloc (fci, sizeof (struct frame_extra_info));
-
-  get_frame_extra_info (fci)->proc_desc =
-    proc_desc == &temp_proc_desc ? 0 : proc_desc;
-  if (proc_desc)
-    {
-      /* Fixup frame-pointer - only needed for top frame */
-      /* This may not be quite right, if proc has a real frame register.
-         Get the value of the frame relative sp, procedure might have been
-         interrupted by a signal at it's very start.  */
-      if (get_frame_pc (fci) == PROC_LOW_ADDR (proc_desc)
-         && !PROC_DESC_IS_DUMMY (proc_desc))
-       deprecated_update_frame_base_hack (fci, read_next_frame_reg (get_next_frame (fci), NUM_REGS + SP_REGNUM));
-      else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fci), 0, 0))
-       /* Do not ``fix'' fci->frame.  It will have the value of the
-           generic dummy frame's top-of-stack (since the draft
-           fci->frame is obtained by returning the unwound stack
-           pointer) and that is what we want.  That way the fci->frame
-           value will match the top-of-stack value that was saved as
-           part of the dummy frames data.  */
-       /* Do nothing.  */;
-      else
-       deprecated_update_frame_base_hack (fci, get_frame_pointer (get_next_frame (fci), proc_desc));
-
-      if (proc_desc == &temp_proc_desc)
-       {
-         char *name;
-
-         /* Do not set the saved registers for a sigtramp frame,
-            mips_find_saved_registers will do that for us.  We can't
-            use (get_frame_type (fci) == SIGTRAMP_FRAME), it is not
-            yet set.  */
-         /* FIXME: cagney/2002-11-18: This problem will go away once
-             frame.c:get_prev_frame() is modified to set the frame's
-             type before calling functions like this.  */
-         find_pc_partial_function (get_frame_pc (fci), &name,
-                                   (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
-         if (!PC_IN_SIGTRAMP (get_frame_pc (fci), name))
-           {
-             frame_saved_regs_zalloc (fci);
-             /* Set value of previous frame's stack pointer.
-                Remember that saved_regs[SP_REGNUM] is special in
-                that it contains the value of the stack pointer
-                register.  The other saved_regs values are addresses
-                (in the inferior) at which a given register's value
-                may be found.  */
-             set_reg_offset (temp_saved_regs, SP_REGNUM,
-                             get_frame_base (fci));
-             set_reg_offset (temp_saved_regs, PC_REGNUM,
-                             temp_saved_regs[RA_REGNUM]);
-             memcpy (deprecated_get_frame_saved_regs (fci), temp_saved_regs,
-                     SIZEOF_FRAME_SAVED_REGS);
-           }
-       }
-
-      /* hack: if argument regs are saved, guess these contain args */
-      /* assume we can't tell how many args for now */
-      get_frame_extra_info (fci)->num_args = -1;
-      for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
-       {
-         if (PROC_REG_MASK (proc_desc) & (1 << regnum))
-           {
-             get_frame_extra_info (fci)->num_args = regnum - A0_REGNUM + 1;
-             break;
-           }
-       }
-    }
-}
-
-/* MIPS stack frames are almost impenetrable.  When execution stops,
-   we basically have to look at symbol information for the function
-   that we stopped in, which tells us *which* register (if any) is
-   the base of the frame pointer, and what offset from that register
-   the frame itself is at.
-
-   This presents a problem when trying to examine a stack in memory
-   (that isn't executing at the moment), using the "frame" command.  We
-   don't have a PC, nor do we have any registers except SP.
-
-   This routine takes two arguments, SP and PC, and tries to make the
-   cached frames look as if these two arguments defined a frame on the
-   cache.  This allows the rest of info frame to extract the important
-   arguments without difficulty.  */
-
-struct frame_info *
-setup_arbitrary_frame (int argc, CORE_ADDR *argv)
-{
-  if (argc != 2)
-    error ("MIPS frame specifications require two arguments: sp and pc");
-
-  return create_new_frame (argv[0], argv[1]);
-}
-
-/* According to the current ABI, should the type be passed in a
-   floating-point register (assuming that there is space)?  When there
-   is no FPU, FP are not even considered as possibile candidates for
-   FP registers and, consequently this returns false - forces FP
-   arguments into integer registers. */
-
-static int
-fp_register_arg_p (enum type_code typecode, struct type *arg_type)
-{
-  return ((typecode == TYPE_CODE_FLT
-          || (MIPS_EABI
-              && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
-              && TYPE_NFIELDS (arg_type) == 1
-              && TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT))
-         && MIPS_FPU_TYPE != MIPS_FPU_NONE);
-}
-
-/* On o32, argument passing in GPRs depends on the alignment of the type being
-   passed.  Return 1 if this type must be aligned to a doubleword boundary. */
-
-static int
-mips_type_needs_double_align (struct type *type)
-{
-  enum type_code typecode = TYPE_CODE (type);
-
-  if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
-    return 1;
-  else if (typecode == TYPE_CODE_STRUCT)
-    {
-      if (TYPE_NFIELDS (type) < 1)
-       return 0;
-      return mips_type_needs_double_align (TYPE_FIELD_TYPE (type, 0));
-    }
-  else if (typecode == TYPE_CODE_UNION)
-    {
-      int i, n;
-
-      n = TYPE_NFIELDS (type);
-      for (i = 0; i < n; i++)
-       if (mips_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
-         return 1;
-      return 0;
-    }
-  return 0;
-}
-
-/* Adjust the address downward (direction of stack growth) so that it
-   is correctly aligned for a new stack frame.  */
-static CORE_ADDR
-mips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
-{
-  return align_down (addr, 16);
-}
-
-static CORE_ADDR
-mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
-                          struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                          struct value **args, CORE_ADDR sp, int struct_return,
-                          CORE_ADDR struct_addr)
-{
-  int argreg;
-  int float_argreg;
-  int argnum;
-  int len = 0;
-  int stack_offset = 0;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+static CORE_ADDR
+mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                            struct regcache *regcache, CORE_ADDR bp_addr,
+                            int nargs, struct value **args, CORE_ADDR sp,
+                            int struct_return, CORE_ADDR struct_addr)
+{
+  int argreg;
+  int float_argreg;
+  int argnum;
+  int len = 0;
+  int stack_offset = 0;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
-  regcache_cooked_write_signed (regcache, T9_REGNUM, func_addr);
+  regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr);
 
   /* Set the return address register to point to the entry point of
      the program, where a breakpoint lies in wait.  */
-  regcache_cooked_write_signed (regcache, RA_REGNUM, bp_addr);
+  regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -2735,21 +2682,19 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   sp = align_down (sp, 16);
   struct_addr = align_down (struct_addr, 16);
 
-  /* Now make space on the stack for the args.  We allocate more
-     than necessary for EABI, because the first few arguments are
-     passed in registers, but that's OK.  */
+  /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
-    len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])), 
-                    mips_stack_argsize (tdep));
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])),
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
-    fprintf_unfiltered (gdb_stdlog, 
-                       "mips_eabi_push_dummy_call: sp=0x%s allocated %ld\n",
+    fprintf_unfiltered (gdb_stdlog,
+                       "mips_n32n64_push_dummy_call: sp=0x%s allocated %ld\n",
                        paddr_nz (sp), (long) align_up (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
+  argreg = MIPS_A0_REGNUM;
   float_argreg = mips_fpa0_regnum (current_gdbarch);
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
@@ -2757,7 +2702,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_eabi_push_dummy_call: struct_return reg=%d 0x%s\n",
+                           "mips_n32n64_push_dummy_call: struct_return reg=%d 0x%s\n",
                            argreg, paddr_nz (struct_addr));
       write_register (argreg++, struct_addr);
     }
@@ -2768,91 +2713,36 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       char *val;
-      char valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
-      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+      struct type *arg_type = check_typedef (value_type (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
 
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_eabi_push_dummy_call: %d len=%d type=%d",
+                           "mips_n32n64_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
-      /* The EABI passes structures that do not fit in a register by
-         reference.  */
-      if (len > mips_saved_regsize (tdep)
-         && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
-       {
-         store_unsigned_integer (valbuf, mips_saved_regsize (tdep),
-                                 VALUE_ADDRESS (arg));
-         typecode = TYPE_CODE_PTR;
-         len = mips_saved_regsize (tdep);
-         val = valbuf;
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stdlog, " push");
-       }
-      else
-       val = (char *) VALUE_CONTENTS (arg);
-
-      /* 32-bit ABIs always start floating point arguments in an
-         even-numbered floating point register.  Round the FP register
-         up before the check to see if there are any FP registers
-         left.  Non MIPS_EABI targets also pass the FP in the integer
-         registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE
-         && fp_register_arg_p (typecode, arg_type))
-       {
-         if ((float_argreg & 1))
-           float_argreg++;
-       }
+      val = (char *) VALUE_CONTENTS (arg);
 
-      /* Floating point arguments passed in registers have to be
-         treated specially.  On 32-bit architectures, doubles
-         are passed in register pairs; the even register gets
-         the low word, and the odd register gets the high word.
-         On non-EABI processors, the first two floating point arguments are
-         also copied to general registers, because MIPS16 functions
-         don't use float registers for arguments.  This duplication of
-         arguments in general registers can't hurt non-MIPS16 functions
-         because those registers are normally skipped.  */
-      /* MIPS_EABI squeezes a struct that contains a single floating
-         point value into an FP register instead of pushing it onto the
-         stack.  */
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (!FP_REGISTER_DOUBLE && len == 8)
-           {
-             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
-             unsigned long regval;
-
-             /* Write the low word of the double to the even register(s).  */
-             regval = extract_unsigned_integer (val + low_offset, 4);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, 4));
-             write_register (float_argreg++, regval);
+         /* This is a floating point value that fits entirely
+            in a single register.  */
+         /* On 32 bit ABI's the float_argreg is further adjusted
+            above to ensure that it is even register aligned.  */
+         LONGEST regval = extract_unsigned_integer (val, len);
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                               float_argreg, phex (regval, len));
+         write_register (float_argreg++, regval);
 
-             /* Write the high word of the double to the odd register(s).  */
-             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, 4));
-             write_register (float_argreg++, regval);
-           }
-         else
-           {
-             /* This is a floating point value that fits entirely
-                in a single register.  */
-             /* On 32 bit ABI's the float_argreg is further adjusted
-                 above to ensure that it is even register aligned.  */
-             LONGEST regval = extract_unsigned_integer (val, len);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, len));
-             write_register (float_argreg++, regval);
-           }
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
+                               argreg, phex (regval, len));
+         write_register (argreg, regval);
+         argreg += 1;
        }
       else
        {
@@ -2860,21 +2750,20 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
-
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
          /* Note: Floating-point values that didn't fit into an FP
-             register are only written to memory.  */
+            register are only written to memory.  */
          while (len > 0)
            {
-             /* Remember if the argument was written to the stack.  */
+             /* Rememer if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -2892,17 +2781,11 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
-                             || typecode == TYPE_CODE_FLT)
-                         && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
-                     else if ((typecode == TYPE_CODE_STRUCT
-                               || typecode == TYPE_CODE_UNION)
-                              && (TYPE_LENGTH (arg_type)
-                                  < mips_stack_argsize (tdep)))
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                             || typecode == TYPE_CODE_FLT) && len <= 4)
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -2918,11 +2801,11 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  if (mips_debug)
                    {
                      int i;
-                     fprintf_unfiltered (gdb_stdlog, " @0x%s ", 
+                     fprintf_unfiltered (gdb_stdlog, " @0x%s ",
                                          paddr_nz (addr));
                      for (i = 0; i < partial_len; i++)
                        {
-                         fprintf_unfiltered (gdb_stdlog, "%02x", 
+                         fprintf_unfiltered (gdb_stdlog, "%02x",
                                              val[i] & 0xff);
                        }
                    }
@@ -2933,51 +2816,185 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 structs may go thru BOTH paths.  Floating point
                 arguments will not.  */
              /* Write this portion of the argument to a general
-                 purpose register.  */
+                purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM
                  && !fp_register_arg_p (typecode, arg_type))
                {
-                 LONGEST regval = extract_unsigned_integer (val, partial_len);
-
-                 if (mips_debug)
-                   fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
-                                     argreg,
-                                     phex (regval, mips_saved_regsize (tdep)));
-                 write_register (argreg, regval);
-                 argreg++;
-               }
+                 LONGEST regval =
+                   extract_unsigned_integer (val, partial_len);
 
-             len -= partial_len;
-             val += partial_len;
+                 /* A non-floating-point argument being passed in a
+                    general register.  If a struct or union, and if
+                    the remaining length is smaller than the register
+                    size, we have to adjust the register value on
+                    big endian targets.
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+                    It does not seem to be necessary to do the
+                    same for integral types.
 
-                In the new EABI (and the NABI32), the stack_offset
-                only needs to be adjusted when it has been used.  */
+                    cagney/2001-07-23: gdb/179: Also, GCC, when
+                    outputting LE O32 with sizeof (struct) <
+                    mips_abi_regsize(), generates a left shift as
+                    part of storing the argument in a register a
+                    register (the left shift isn't generated when
+                    sizeof (struct) >= mips_abi_regsize()).  Since
+                    it is quite possible that this is GCC
+                    contradicting the LE/O32 ABI, GDB has not been
+                    adjusted to accommodate this.  Either someone
+                    needs to demonstrate that the LE/O32 ABI
+                    specifies such a left shift OR this new ABI gets
+                    identified as such and GDB gets tweaked
+                    accordingly.  */
+
+                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+                     && partial_len < mips_abi_regsize (gdbarch)
+                     && (typecode == TYPE_CODE_STRUCT ||
+                         typecode == TYPE_CODE_UNION))
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
+                               TARGET_CHAR_BIT);
+
+                 if (mips_debug)
+                   fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
+                                     argreg,
+                                     phex (regval,
+                                           mips_abi_regsize (gdbarch)));
+                 write_register (argreg, regval);
+                 argreg++;
+               }
+
+             len -= partial_len;
+             val += partial_len;
+
+             /* Compute the the offset into the stack at which we
+                will copy the next parameter.
+
+                In N32 (N64?), the stack_offset only needs to be
+                adjusted when it has been used.  */
 
              if (stack_used_p)
                stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (tdep));
+                                         mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
 }
 
-/* N32/N64 version of push_dummy_call.  */
+static enum return_value_convention
+mips_n32n64_return_value (struct gdbarch *gdbarch,
+                         struct type *type, struct regcache *regcache,
+                         void *readbuf, const void *writebuf)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY
+      || TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A floating-point value belongs in the least significant part
+         of FP0.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
+      mips_xfer_register (regcache,
+                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+                         TYPE_LENGTH (type),
+                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+          && TYPE_NFIELDS (type) <= 2
+          && TYPE_NFIELDS (type) >= 1
+          && ((TYPE_NFIELDS (type) == 1
+               && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
+                   == TYPE_CODE_FLT))
+              || (TYPE_NFIELDS (type) == 2
+                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
+                      == TYPE_CODE_FLT)
+                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1))
+                      == TYPE_CODE_FLT)))
+          && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A struct that contains one or two floats.  Each value is part
+         in the least significant part of their floating point
+         register..  */
+      int regnum;
+      int field;
+      for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
+          field < TYPE_NFIELDS (type); field++, regnum += 2)
+       {
+         int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field])
+                       / TARGET_CHAR_BIT);
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n",
+                               offset);
+         mips_xfer_register (regcache, NUM_REGS + regnum,
+                             TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
+                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (type) == TYPE_CODE_UNION)
+    {
+      /* A structure or union.  Extract the left justified value,
+         regardless of the byte order.  I.e. DO NOT USE
+         mips_xfer_lower.  */
+      int offset;
+      int regnum;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
+          offset < TYPE_LENGTH (type);
+          offset += register_size (current_gdbarch, regnum), regnum++)
+       {
+         int xfer = register_size (current_gdbarch, regnum);
+         if (offset + xfer > TYPE_LENGTH (type))
+           xfer = TYPE_LENGTH (type) - offset;
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n",
+                               offset, xfer, regnum);
+         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
+                             BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else
+    {
+      /* A scalar extract each part but least-significant-byte
+         justified.  */
+      int offset;
+      int regnum;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
+          offset < TYPE_LENGTH (type);
+          offset += register_size (current_gdbarch, regnum), regnum++)
+       {
+         int xfer = register_size (current_gdbarch, regnum);
+         if (offset + xfer > TYPE_LENGTH (type))
+           xfer = TYPE_LENGTH (type) - offset;
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n",
+                               offset, xfer, regnum);
+         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
+                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+}
+
+/* O32 ABI stuff.  */
 
 static CORE_ADDR
-mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
-                            struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                            struct value **args, CORE_ADDR sp, int struct_return,
-                            CORE_ADDR struct_addr)
+mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                         struct regcache *regcache, CORE_ADDR bp_addr,
+                         int nargs, struct value **args, CORE_ADDR sp,
+                         int struct_return, CORE_ADDR struct_addr)
 {
   int argreg;
   int float_argreg;
@@ -2985,14 +3002,15 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
-  regcache_cooked_write_signed (regcache, T9_REGNUM, func_addr);
+  regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr);
 
   /* Set the return address register to point to the entry point of
      the program, where a breakpoint lies in wait.  */
-  regcache_cooked_write_signed (regcache, RA_REGNUM, bp_addr);
+  regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -3005,17 +3023,17 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
-    len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])), 
-                    mips_stack_argsize (tdep));
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])),
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
-    fprintf_unfiltered (gdb_stdlog, 
-                       "mips_n32n64_push_dummy_call: sp=0x%s allocated %ld\n",
+    fprintf_unfiltered (gdb_stdlog,
+                       "mips_o32_push_dummy_call: sp=0x%s allocated %ld\n",
                        paddr_nz (sp), (long) align_up (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
+  argreg = MIPS_A0_REGNUM;
   float_argreg = mips_fpa0_regnum (current_gdbarch);
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
@@ -3023,9 +3041,10 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_n32n64_push_dummy_call: struct_return reg=%d 0x%s\n",
+                           "mips_o32_push_dummy_call: struct_return reg=%d 0x%s\n",
                            argreg, paddr_nz (struct_addr));
       write_register (argreg++, struct_addr);
+      stack_offset += mips_stack_argsize (gdbarch);
     }
 
   /* Now load as many as possible of the first arguments into
@@ -3034,37 +3053,94 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       char *val;
-      char valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
-      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+      struct type *arg_type = check_typedef (value_type (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
 
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_n32n64_push_dummy_call: %d len=%d type=%d",
+                           "mips_o32_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
       val = (char *) VALUE_CONTENTS (arg);
 
+      /* 32-bit ABIs always start floating point arguments in an
+         even-numbered floating point register.  Round the FP register
+         up before the check to see if there are any FP registers
+         left.  O32/O64 targets also pass the FP in the integer
+         registers so also round up normal registers.  */
+      if (mips_abi_regsize (gdbarch) < 8
+         && fp_register_arg_p (typecode, arg_type))
+       {
+         if ((float_argreg & 1))
+           float_argreg++;
+       }
+
+      /* Floating point arguments passed in registers have to be
+         treated specially.  On 32-bit architectures, doubles
+         are passed in register pairs; the even register gets
+         the low word, and the odd register gets the high word.
+         On O32/O64, the first two floating point arguments are
+         also copied to general registers, because MIPS16 functions
+         don't use float registers for arguments.  This duplication of
+         arguments in general registers can't hurt non-MIPS16 functions
+         because those registers are normally skipped.  */
+
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         /* This is a floating point value that fits entirely
-            in a single register.  */
-         /* On 32 bit ABI's the float_argreg is further adjusted
-            above to ensure that it is even register aligned.  */
-         LONGEST regval = extract_unsigned_integer (val, len);
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                               float_argreg, phex (regval, len));
-         write_register (float_argreg++, regval);
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
+           {
+             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+             unsigned long regval;
 
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
-                               argreg, phex (regval, len));
-         write_register (argreg, regval);
-         argreg += 1;
+             /* Write the low word of the double to the even register(s).  */
+             regval = extract_unsigned_integer (val + low_offset, 4);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, 4));
+             write_register (float_argreg++, regval);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
+                                   argreg, phex (regval, 4));
+             write_register (argreg++, regval);
+
+             /* Write the high word of the double to the odd register(s).  */
+             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, 4));
+             write_register (float_argreg++, regval);
+
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
+                                   argreg, phex (regval, 4));
+             write_register (argreg++, regval);
+           }
+         else
+           {
+             /* This is a floating point value that fits entirely
+                in a single register.  */
+             /* On 32 bit ABI's the float_argreg is further adjusted
+                above to ensure that it is even register aligned.  */
+             LONGEST regval = extract_unsigned_integer (val, len);
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
+                                   float_argreg, phex (regval, len));
+             write_register (float_argreg++, regval);
+             /* CAGNEY: 32 bit MIPS ABI's always reserve two FP
+                registers for each argument.  The below is (my
+                guess) to ensure that the corresponding integer
+                register has reserved the same space.  */
+             if (mips_debug)
+               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
+                                   argreg, phex (regval, len));
+             write_register (argreg, regval);
+             argreg += (mips_abi_regsize (gdbarch) == 8) ? 1 : 2;
+           }
+         /* Reserve space for the FP register.  */
+         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
        }
       else
        {
@@ -3072,20 +3148,28 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
+         /* Structures should be aligned to eight bytes (even arg registers)
+            on MIPS_ABI_O32, if their first member has double precision.  */
+         if (mips_abi_regsize (gdbarch) < 8
+             && mips_type_needs_double_align (arg_type))
+           {
+             if ((argreg & 1))
+               argreg++;
+           }
          /* Note: Floating-point values that didn't fit into an FP
-             register are only written to memory.  */
+            register are only written to memory.  */
          while (len > 0)
            {
-             /* Rememer if the argument was written to the stack.  */
+             /* Remember if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3103,12 +3187,11 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
-                             || typecode == TYPE_CODE_FLT)
-                         && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                             || typecode == TYPE_CODE_FLT) && len <= 4)
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -3124,11 +3207,11 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  if (mips_debug)
                    {
                      int i;
-                     fprintf_unfiltered (gdb_stdlog, " @0x%s ", 
+                     fprintf_unfiltered (gdb_stdlog, " @0x%s ",
                                          paddr_nz (addr));
                      for (i = 0; i < partial_len; i++)
                        {
-                         fprintf_unfiltered (gdb_stdlog, "%02x", 
+                         fprintf_unfiltered (gdb_stdlog, "%02x",
                                              val[i] & 0xff);
                        }
                    }
@@ -3139,11 +3222,13 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 structs may go thru BOTH paths.  Floating point
                 arguments will not.  */
              /* Write this portion of the argument to a general
-                 purpose register.  */
+                purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM
                  && !fp_register_arg_p (typecode, arg_type))
                {
-                 LONGEST regval = extract_unsigned_integer (val, partial_len);
+                 LONGEST regval = extract_signed_integer (val, partial_len);
+                 /* Value may need to be sign extended, because
+                    mips_isa_regsize() != mips_abi_regsize().  */
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -3154,12 +3239,14 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     It does not seem to be necessary to do the
                     same for integral types.
 
+                    Also don't do this adjustment on O64 binaries.
+
                     cagney/2001-07-23: gdb/179: Also, GCC, when
                     outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
+                    mips_abi_regsize(), generates a left shift as
                     part of storing the argument in a register a
                     register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
+                    sizeof (struct) >= mips_abi_regsize()).  Since
                     it is quite possible that this is GCC
                     contradicting the LE/O32 ABI, GDB has not been
                     adjusted to accommodate this.  Either someone
@@ -3168,69 +3255,218 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     identified as such and GDB gets tweaked
                     accordingly.  */
 
-                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
+                 if (mips_abi_regsize (gdbarch) < 8
+                     && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+                     && partial_len < mips_abi_regsize (gdbarch)
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
                                TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval, mips_saved_regsize (tdep)));
+                                     phex (regval,
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
+
+                 /* Prevent subsequent floating point arguments from
+                    being passed in floating point registers.  */
+                 float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
                }
 
              len -= partial_len;
              val += partial_len;
 
              /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+                will copy the next parameter.
 
-                In N32 (N64?), the stack_offset only needs to be
-                adjusted when it has been used.  */
+                In older ABIs, the caller reserved space for
+                registers that contained arguments.  This was loosely
+                refered to as their "home".  Consequently, space is
+                always allocated.  */
 
-             if (stack_used_p)
-               stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (tdep));
+             stack_offset += align_up (partial_len,
+                                       mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
 }
 
-/* O32 version of push_dummy_call.  */
-
-static CORE_ADDR
-mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
-                         struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                         struct value **args, CORE_ADDR sp, int struct_return,
-                         CORE_ADDR struct_addr)
+static enum return_value_convention
+mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
+                      struct regcache *regcache,
+                      void *readbuf, const void *writebuf)
 {
-  int argreg;
-  int float_argreg;
-  int argnum;
-  int len = 0;
-  int stack_offset = 0;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
-  /* For shared libraries, "t9" needs to point at the function
-     address.  */
-  regcache_cooked_write_signed (regcache, T9_REGNUM, func_addr);
-
-  /* Set the return address register to point to the entry point of
-     the program, where a breakpoint lies in wait.  */
-  regcache_cooked_write_signed (regcache, RA_REGNUM, bp_addr);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-  /* First ensure that the stack and structure return address (if any)
+  if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+      || TYPE_CODE (type) == TYPE_CODE_UNION
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) == 4 && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A single-precision floating-point value.  It fits in the
+         least significant part of FP0.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
+      mips_xfer_register (regcache,
+                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+                         TYPE_LENGTH (type),
+                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) == 8 && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A double-precision floating-point value.  The most
+         significant part goes in FP1, and the least significant in
+         FP0.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $fp1/$fp0\n");
+      switch (TARGET_BYTE_ORDER)
+       {
+       case BFD_ENDIAN_LITTLE:
+         mips_xfer_register (regcache,
+                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
+                             0, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+         mips_xfer_register (regcache,
+                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
+                             1, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
+         break;
+       case BFD_ENDIAN_BIG:
+         mips_xfer_register (regcache,
+                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
+                             1, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+         mips_xfer_register (regcache,
+                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
+                             0, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
+         break;
+       default:
+         internal_error (__FILE__, __LINE__, "bad switch");
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+#if 0
+  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+          && TYPE_NFIELDS (type) <= 2
+          && TYPE_NFIELDS (type) >= 1
+          && ((TYPE_NFIELDS (type) == 1
+               && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
+                   == TYPE_CODE_FLT))
+              || (TYPE_NFIELDS (type) == 2
+                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
+                      == TYPE_CODE_FLT)
+                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1))
+                      == TYPE_CODE_FLT)))
+          && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A struct that contains one or two floats.  Each value is part
+         in the least significant part of their floating point
+         register..  */
+      bfd_byte reg[MAX_REGISTER_SIZE];
+      int regnum;
+      int field;
+      for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
+          field < TYPE_NFIELDS (type); field++, regnum += 2)
+       {
+         int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field])
+                       / TARGET_CHAR_BIT);
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n",
+                               offset);
+         mips_xfer_register (regcache, NUM_REGS + regnum,
+                             TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
+                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+#endif
+#if 0
+  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (type) == TYPE_CODE_UNION)
+    {
+      /* A structure or union.  Extract the left justified value,
+         regardless of the byte order.  I.e. DO NOT USE
+         mips_xfer_lower.  */
+      int offset;
+      int regnum;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
+          offset < TYPE_LENGTH (type);
+          offset += register_size (current_gdbarch, regnum), regnum++)
+       {
+         int xfer = register_size (current_gdbarch, regnum);
+         if (offset + xfer > TYPE_LENGTH (type))
+           xfer = TYPE_LENGTH (type) - offset;
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n",
+                               offset, xfer, regnum);
+         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
+                             BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+#endif
+  else
+    {
+      /* A scalar extract each part but least-significant-byte
+         justified.  o32 thinks registers are 4 byte, regardless of
+         the ISA.  mips_stack_argsize controls this.  */
+      int offset;
+      int regnum;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
+          offset < TYPE_LENGTH (type);
+          offset += mips_stack_argsize (gdbarch), regnum++)
+       {
+         int xfer = mips_stack_argsize (gdbarch);
+         if (offset + xfer > TYPE_LENGTH (type))
+           xfer = TYPE_LENGTH (type) - offset;
+         if (mips_debug)
+           fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n",
+                               offset, xfer, regnum);
+         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
+                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+}
+
+/* O64 ABI.  This is a hacked up kind of 64-bit version of the o32
+   ABI.  */
+
+static CORE_ADDR
+mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
+                         struct regcache *regcache, CORE_ADDR bp_addr,
+                         int nargs,
+                         struct value **args, CORE_ADDR sp,
+                         int struct_return, CORE_ADDR struct_addr)
+{
+  int argreg;
+  int float_argreg;
+  int argnum;
+  int len = 0;
+  int stack_offset = 0;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
+
+  /* For shared libraries, "t9" needs to point at the function
+     address.  */
+  regcache_cooked_write_signed (regcache, MIPS_T9_REGNUM, func_addr);
+
+  /* Set the return address register to point to the entry point of
+     the program, where a breakpoint lies in wait.  */
+  regcache_cooked_write_signed (regcache, MIPS_RA_REGNUM, bp_addr);
+
+  /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
      aligned even on 32-bit machines, because doubles must be 64-bit
      aligned.  For n32 and n64, stack frames need to be 128-bit
@@ -3241,17 +3477,17 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
-    len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])), 
-                    mips_stack_argsize (tdep));
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])),
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
-    fprintf_unfiltered (gdb_stdlog, 
-                       "mips_o32_push_dummy_call: sp=0x%s allocated %ld\n",
+    fprintf_unfiltered (gdb_stdlog,
+                       "mips_o64_push_dummy_call: sp=0x%s allocated %ld\n",
                        paddr_nz (sp), (long) align_up (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
+  argreg = MIPS_A0_REGNUM;
   float_argreg = mips_fpa0_regnum (current_gdbarch);
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
@@ -3259,10 +3495,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_o32_push_dummy_call: struct_return reg=%d 0x%s\n",
+                           "mips_o64_push_dummy_call: struct_return reg=%d 0x%s\n",
                            argreg, paddr_nz (struct_addr));
       write_register (argreg++, struct_addr);
-      stack_offset += mips_stack_argsize (tdep);
+      stack_offset += mips_stack_argsize (gdbarch);
     }
 
   /* Now load as many as possible of the first arguments into
@@ -3271,15 +3507,14 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       char *val;
-      char valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
-      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+      struct type *arg_type = check_typedef (value_type (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
 
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_o32_push_dummy_call: %d len=%d type=%d",
+                           "mips_o64_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
       val = (char *) VALUE_CONTENTS (arg);
@@ -3289,7 +3524,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
          up before the check to see if there are any FP registers
          left.  O32/O64 targets also pass the FP in the integer
          registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE
+      if (mips_abi_regsize (gdbarch) < 8
          && fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
@@ -3309,7 +3544,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (!FP_REGISTER_DOUBLE && len == 8)
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
            {
              int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
@@ -3342,24 +3577,24 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
              /* This is a floating point value that fits entirely
                 in a single register.  */
              /* On 32 bit ABI's the float_argreg is further adjusted
-                 above to ensure that it is even register aligned.  */
+                above to ensure that it is even register aligned.  */
              LONGEST regval = extract_unsigned_integer (val, len);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, len));
              write_register (float_argreg++, regval);
              /* CAGNEY: 32 bit MIPS ABI's always reserve two FP
-                registers for each argument.  The below is (my
-                guess) to ensure that the corresponding integer
-                register has reserved the same space.  */
+                registers for each argument.  The below is (my
+                guess) to ensure that the corresponding integer
+                register has reserved the same space.  */
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                    argreg, phex (regval, len));
              write_register (argreg, regval);
-             argreg += FP_REGISTER_DOUBLE ? 1 : 2;
+             argreg += (mips_abi_regsize (gdbarch) == 8) ? 1 : 2;
            }
          /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (tdep));
+         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
        }
       else
        {
@@ -3367,28 +3602,28 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
          /* Structures should be aligned to eight bytes (even arg registers)
             on MIPS_ABI_O32, if their first member has double precision.  */
-         if (mips_saved_regsize (tdep) < 8
+         if (mips_abi_regsize (gdbarch) < 8
              && mips_type_needs_double_align (arg_type))
            {
              if ((argreg & 1))
-               argreg++;
+               argreg++;
            }
          /* Note: Floating-point values that didn't fit into an FP
-             register are only written to memory.  */
+            register are only written to memory.  */
          while (len > 0)
            {
              /* Remember if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3406,12 +3641,11 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
-                             || typecode == TYPE_CODE_FLT)
-                         && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                             || typecode == TYPE_CODE_FLT) && len <= 4)
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -3427,11 +3661,11 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  if (mips_debug)
                    {
                      int i;
-                     fprintf_unfiltered (gdb_stdlog, " @0x%s ", 
+                     fprintf_unfiltered (gdb_stdlog, " @0x%s ",
                                          paddr_nz (addr));
                      for (i = 0; i < partial_len; i++)
                        {
-                         fprintf_unfiltered (gdb_stdlog, "%02x", 
+                         fprintf_unfiltered (gdb_stdlog, "%02x",
                                              val[i] & 0xff);
                        }
                    }
@@ -3442,13 +3676,13 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 structs may go thru BOTH paths.  Floating point
                 arguments will not.  */
              /* Write this portion of the argument to a general
-                 purpose register.  */
+                purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM
                  && !fp_register_arg_p (typecode, arg_type))
                {
                  LONGEST regval = extract_signed_integer (val, partial_len);
                  /* Value may need to be sign extended, because
-                    mips_regsize() != mips_saved_regsize().  */
+                    mips_isa_regsize() != mips_abi_regsize().  */
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -3463,10 +3697,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
                     cagney/2001-07-23: gdb/179: Also, GCC, when
                     outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
+                    mips_abi_regsize(), generates a left shift as
                     part of storing the argument in a register a
                     register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
+                    sizeof (struct) >= mips_abi_regsize()).  Since
                     it is quite possible that this is GCC
                     contradicting the LE/O32 ABI, GDB has not been
                     adjusted to accommodate this.  Either someone
@@ -3475,18 +3709,19 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     identified as such and GDB gets tweaked
                     accordingly.  */
 
-                 if (mips_saved_regsize (tdep) < 8
+                 if (mips_abi_regsize (gdbarch) < 8
                      && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
+                     && partial_len < mips_abi_regsize (gdbarch)
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
                                TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval, mips_saved_regsize (tdep)));
+                                     phex (regval,
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
 
@@ -3499,606 +3734,229 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
              val += partial_len;
 
              /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+                will copy the next parameter.
 
-                In older ABIs, the caller reserved space for
-                registers that contained arguments.  This was loosely
-                refered to as their "home".  Consequently, space is
-                always allocated.  */
+                In older ABIs, the caller reserved space for
+                registers that contained arguments.  This was loosely
+                refered to as their "home".  Consequently, space is
+                always allocated.  */
 
              stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (tdep));
+                                       mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
 }
 
-/* O64 version of push_dummy_call.  */
-
-static CORE_ADDR
-mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
-                         struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                         struct value **args, CORE_ADDR sp, int struct_return,
-                         CORE_ADDR struct_addr)
+static enum return_value_convention
+mips_o64_return_value (struct gdbarch *gdbarch,
+                      struct type *type, struct regcache *regcache,
+                      void *readbuf, const void *writebuf)
 {
-  int argreg;
-  int float_argreg;
-  int argnum;
-  int len = 0;
-  int stack_offset = 0;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  return RETURN_VALUE_STRUCT_CONVENTION;
+}
 
-  /* For shared libraries, "t9" needs to point at the function
-     address.  */
-  regcache_cooked_write_signed (regcache, T9_REGNUM, func_addr);
+/* Floating point register management.
 
-  /* Set the return address register to point to the entry point of
-     the program, where a breakpoint lies in wait.  */
-  regcache_cooked_write_signed (regcache, RA_REGNUM, bp_addr);
+   Background: MIPS1 & 2 fp registers are 32 bits wide.  To support
+   64bit operations, these early MIPS cpus treat fp register pairs
+   (f0,f1) as a single register (d0).  Later MIPS cpu's have 64 bit fp
+   registers and offer a compatibility mode that emulates the MIPS2 fp
+   model.  When operating in MIPS2 fp compat mode, later cpu's split
+   double precision floats into two 32-bit chunks and store them in
+   consecutive fp regs.  To display 64-bit floats stored in this
+   fashion, we have to combine 32 bits from f0 and 32 bits from f1.
+   Throw in user-configurable endianness and you have a real mess.
 
-  /* First ensure that the stack and structure return address (if any)
-     are properly aligned.  The stack has to be at least 64-bit
-     aligned even on 32-bit machines, because doubles must be 64-bit
-     aligned.  For n32 and n64, stack frames need to be 128-bit
-     aligned, so we round to this widest known alignment.  */
+   The way this works is:
+     - If we are in 32-bit mode or on a 32-bit processor, then a 64-bit
+       double-precision value will be split across two logical registers.
+       The lower-numbered logical register will hold the low-order bits,
+       regardless of the processor's endianness.
+     - If we are on a 64-bit processor, and we are looking for a
+       single-precision value, it will be in the low ordered bits
+       of a 64-bit GPR (after mfc1, for example) or a 64-bit register
+       save slot in memory.
+     - If we are in 64-bit mode, everything is straightforward.
 
-  sp = align_down (sp, 16);
-  struct_addr = align_down (struct_addr, 16);
+   Note that this code only deals with "live" registers at the top of the
+   stack.  We will attempt to deal with saved registers later, when
+   the raw/cooked register interface is in place. (We need a general
+   interface that can deal with dynamic saved register sizes -- fp
+   regs could be 32 bits wide in one frame and 64 on the frame above
+   and below).  */
 
-  /* Now make space on the stack for the args.  */
-  for (argnum = 0; argnum < nargs; argnum++)
-    len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])), 
-                    mips_stack_argsize (tdep));
-  sp -= align_up (len, 16);
+static struct type *
+mips_float_register_type (void)
+{
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+    return builtin_type_ieee_single_big;
+  else
+    return builtin_type_ieee_single_little;
+}
 
-  if (mips_debug)
-    fprintf_unfiltered (gdb_stdlog, 
-                       "mips_o64_push_dummy_call: sp=0x%s allocated %ld\n",
-                       paddr_nz (sp), (long) align_up (len, 16));
+static struct type *
+mips_double_register_type (void)
+{
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+    return builtin_type_ieee_double_big;
+  else
+    return builtin_type_ieee_double_little;
+}
 
-  /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
-  float_argreg = mips_fpa0_regnum (current_gdbarch);
+/* Copy a 32-bit single-precision value from the current frame
+   into rare_buffer.  */
 
-  /* The struct_return pointer occupies the first parameter-passing reg.  */
-  if (struct_return)
-    {
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "mips_o64_push_dummy_call: struct_return reg=%d 0x%s\n",
-                           argreg, paddr_nz (struct_addr));
-      write_register (argreg++, struct_addr);
-      stack_offset += mips_stack_argsize (tdep);
-    }
+static void
+mips_read_fp_register_single (struct frame_info *frame, int regno,
+                             char *rare_buffer)
+{
+  int raw_size = register_size (current_gdbarch, regno);
+  char *raw_buffer = alloca (raw_size);
 
-  /* Now load as many as possible of the first arguments into
-     registers, and push the rest onto the stack.  Loop thru args
-     from first to last.  */
-  for (argnum = 0; argnum < nargs; argnum++)
+  if (!frame_register_read (frame, regno, raw_buffer))
+    error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
+  if (raw_size == 8)
     {
-      char *val;
-      char valbuf[MAX_REGISTER_SIZE];
-      struct value *arg = args[argnum];
-      struct type *arg_type = check_typedef (VALUE_TYPE (arg));
-      int len = TYPE_LENGTH (arg_type);
-      enum type_code typecode = TYPE_CODE (arg_type);
+      /* We have a 64-bit value for this register.  Find the low-order
+         32 bits.  */
+      int offset;
 
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "mips_o64_push_dummy_call: %d len=%d type=%d",
-                           argnum + 1, len, (int) typecode);
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       offset = 4;
+      else
+       offset = 0;
 
-      val = (char *) VALUE_CONTENTS (arg);
+      memcpy (rare_buffer, raw_buffer + offset, 4);
+    }
+  else
+    {
+      memcpy (rare_buffer, raw_buffer, 4);
+    }
+}
 
-      /* 32-bit ABIs always start floating point arguments in an
-         even-numbered floating point register.  Round the FP register
-         up before the check to see if there are any FP registers
-         left.  O32/O64 targets also pass the FP in the integer
-         registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE
-         && fp_register_arg_p (typecode, arg_type))
-       {
-         if ((float_argreg & 1))
-           float_argreg++;
-       }
-
-      /* Floating point arguments passed in registers have to be
-         treated specially.  On 32-bit architectures, doubles
-         are passed in register pairs; the even register gets
-         the low word, and the odd register gets the high word.
-         On O32/O64, the first two floating point arguments are
-         also copied to general registers, because MIPS16 functions
-         don't use float registers for arguments.  This duplication of
-         arguments in general registers can't hurt non-MIPS16 functions
-         because those registers are normally skipped.  */
-
-      if (fp_register_arg_p (typecode, arg_type)
-         && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
-       {
-         if (!FP_REGISTER_DOUBLE && len == 8)
-           {
-             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
-             unsigned long regval;
+/* Copy a 64-bit double-precision value from the current frame into
+   rare_buffer.  This may include getting half of it from the next
+   register.  */
 
-             /* Write the low word of the double to the even register(s).  */
-             regval = extract_unsigned_integer (val + low_offset, 4);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, 4));
-             write_register (float_argreg++, regval);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
-                                   argreg, phex (regval, 4));
-             write_register (argreg++, regval);
+static void
+mips_read_fp_register_double (struct frame_info *frame, int regno,
+                             char *rare_buffer)
+{
+  int raw_size = register_size (current_gdbarch, regno);
 
-             /* Write the high word of the double to the odd register(s).  */
-             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, 4));
-             write_register (float_argreg++, regval);
+  if (raw_size == 8 && !mips2_fp_compat ())
+    {
+      /* We have a 64-bit value for this register, and we should use
+         all 64 bits.  */
+      if (!frame_register_read (frame, regno, rare_buffer))
+       error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
+    }
+  else
+    {
+      if ((regno - mips_regnum (current_gdbarch)->fp0) & 1)
+       internal_error (__FILE__, __LINE__,
+                       "mips_read_fp_register_double: bad access to "
+                       "odd-numbered FP register");
 
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
-                                   argreg, phex (regval, 4));
-             write_register (argreg++, regval);
-           }
-         else
-           {
-             /* This is a floating point value that fits entirely
-                in a single register.  */
-             /* On 32 bit ABI's the float_argreg is further adjusted
-                 above to ensure that it is even register aligned.  */
-             LONGEST regval = extract_unsigned_integer (val, len);
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
-                                   float_argreg, phex (regval, len));
-             write_register (float_argreg++, regval);
-             /* CAGNEY: 32 bit MIPS ABI's always reserve two FP
-                registers for each argument.  The below is (my
-                guess) to ensure that the corresponding integer
-                register has reserved the same space.  */
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
-                                   argreg, phex (regval, len));
-             write_register (argreg, regval);
-             argreg += FP_REGISTER_DOUBLE ? 1 : 2;
-           }
-         /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (tdep));
+      /* mips_read_fp_register_single will find the correct 32 bits from
+         each register.  */
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       {
+         mips_read_fp_register_single (frame, regno, rare_buffer + 4);
+         mips_read_fp_register_single (frame, regno + 1, rare_buffer);
        }
       else
        {
-         /* Copy the argument to general registers or the stack in
-            register-sized pieces.  Large arguments are split between
-            registers and stack.  */
-         /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
-         /* Structures should be aligned to eight bytes (even arg registers)
-            on MIPS_ABI_O32, if their first member has double precision.  */
-         if (mips_saved_regsize (tdep) < 8
-             && mips_type_needs_double_align (arg_type))
-           {
-             if ((argreg & 1))
-               argreg++;
-           }
-         /* Note: Floating-point values that didn't fit into an FP
-             register are only written to memory.  */
-         while (len > 0)
-           {
-             /* Remember if the argument was written to the stack.  */
-             int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
-
-             if (mips_debug)
-               fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
-                                   partial_len);
-
-             /* Write this portion of the argument to the stack.  */
-             if (argreg > MIPS_LAST_ARG_REGNUM
-                 || odd_sized_struct
-                 || fp_register_arg_p (typecode, arg_type))
-               {
-                 /* Should shorter than int integer values be
-                    promoted to int before being stored? */
-                 int longword_offset = 0;
-                 CORE_ADDR addr;
-                 stack_used_p = 1;
-                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-                   {
-                     if (mips_stack_argsize (tdep) == 8
-                         && (typecode == TYPE_CODE_INT
-                             || typecode == TYPE_CODE_PTR
-                             || typecode == TYPE_CODE_FLT)
-                         && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
-                   }
-
-                 if (mips_debug)
-                   {
-                     fprintf_unfiltered (gdb_stdlog, " - stack_offset=0x%s",
-                                         paddr_nz (stack_offset));
-                     fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%s",
-                                         paddr_nz (longword_offset));
-                   }
-
-                 addr = sp + stack_offset + longword_offset;
+         mips_read_fp_register_single (frame, regno, rare_buffer);
+         mips_read_fp_register_single (frame, regno + 1, rare_buffer + 4);
+       }
+    }
+}
 
-                 if (mips_debug)
-                   {
-                     int i;
-                     fprintf_unfiltered (gdb_stdlog, " @0x%s ", 
-                                         paddr_nz (addr));
-                     for (i = 0; i < partial_len; i++)
-                       {
-                         fprintf_unfiltered (gdb_stdlog, "%02x", 
-                                             val[i] & 0xff);
-                       }
-                   }
-                 write_memory (addr, val, partial_len);
-               }
+static void
+mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
+                       int regnum)
+{                              /* do values for FP (float) regs */
+  char *raw_buffer;
+  double doub, flt1;   /* doubles extracted from raw hex data */
+  int inv1, inv2;
 
-             /* Note!!! This is NOT an else clause.  Odd sized
-                structs may go thru BOTH paths.  Floating point
-                arguments will not.  */
-             /* Write this portion of the argument to a general
-                 purpose register.  */
-             if (argreg <= MIPS_LAST_ARG_REGNUM
-                 && !fp_register_arg_p (typecode, arg_type))
-               {
-                 LONGEST regval = extract_signed_integer (val, partial_len);
-                 /* Value may need to be sign extended, because
-                    mips_regsize() != mips_saved_regsize().  */
+  raw_buffer =
+    (char *) alloca (2 *
+                    register_size (current_gdbarch,
+                                   mips_regnum (current_gdbarch)->fp0));
 
-                 /* A non-floating-point argument being passed in a
-                    general register.  If a struct or union, and if
-                    the remaining length is smaller than the register
-                    size, we have to adjust the register value on
-                    big endian targets.
+  fprintf_filtered (file, "%s:", REGISTER_NAME (regnum));
+  fprintf_filtered (file, "%*s", 4 - (int) strlen (REGISTER_NAME (regnum)),
+                   "");
 
-                    It does not seem to be necessary to do the
-                    same for integral types.
+  if (register_size (current_gdbarch, regnum) == 4 || mips2_fp_compat ())
+    {
+      /* 4-byte registers: Print hex and floating.  Also print even
+         numbered registers as doubles.  */
+      mips_read_fp_register_single (frame, regnum, raw_buffer);
+      flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
 
-                    Also don't do this adjustment on O64 binaries.
+      print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w',
+                             file);
 
-                    cagney/2001-07-23: gdb/179: Also, GCC, when
-                    outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
-                    part of storing the argument in a register a
-                    register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
-                    it is quite possible that this is GCC
-                    contradicting the LE/O32 ABI, GDB has not been
-                    adjusted to accommodate this.  Either someone
-                    needs to demonstrate that the LE/O32 ABI
-                    specifies such a left shift OR this new ABI gets
-                    identified as such and GDB gets tweaked
-                    accordingly.  */
+      fprintf_filtered (file, " flt: ");
+      if (inv1)
+       fprintf_filtered (file, " <invalid float> ");
+      else
+       fprintf_filtered (file, "%-17.9g", flt1);
 
-                 if (mips_saved_regsize (tdep) < 8
-                     && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
-                     && (typecode == TYPE_CODE_STRUCT ||
-                         typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
-                               TARGET_CHAR_BIT);
+      if (regnum % 2 == 0)
+       {
+         mips_read_fp_register_double (frame, regnum, raw_buffer);
+         doub = unpack_double (mips_double_register_type (), raw_buffer,
+                               &inv2);
 
-                 if (mips_debug)
-                   fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
-                                     argreg,
-                                     phex (regval, mips_saved_regsize (tdep)));
-                 write_register (argreg, regval);
-                 argreg++;
+         fprintf_filtered (file, " dbl: ");
+         if (inv2)
+           fprintf_filtered (file, "<invalid double>");
+         else
+           fprintf_filtered (file, "%-24.17g", doub);
+       }
+    }
+  else
+    {
+      /* Eight byte registers: print each one as hex, float and double.  */
+      mips_read_fp_register_single (frame, regnum, raw_buffer);
+      flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
 
-                 /* Prevent subsequent floating point arguments from
-                    being passed in floating point registers.  */
-                 float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
-               }
+      mips_read_fp_register_double (frame, regnum, raw_buffer);
+      doub = unpack_double (mips_double_register_type (), raw_buffer, &inv2);
 
-             len -= partial_len;
-             val += partial_len;
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+      print_scalar_formatted (raw_buffer, builtin_type_uint64, 'x', 'g',
+                             file);
 
-                In older ABIs, the caller reserved space for
-                registers that contained arguments.  This was loosely
-                refered to as their "home".  Consequently, space is
-                always allocated.  */
+      fprintf_filtered (file, " flt: ");
+      if (inv1)
+       fprintf_filtered (file, "<invalid float>");
+      else
+       fprintf_filtered (file, "%-17.9g", flt1);
 
-             stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (tdep));
-           }
-       }
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stdlog, "\n");
+      fprintf_filtered (file, " dbl: ");
+      if (inv2)
+       fprintf_filtered (file, "<invalid double>");
+      else
+       fprintf_filtered (file, "%-24.17g", doub);
     }
-
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
-
-  /* Return adjusted stack pointer.  */
-  return sp;
 }
 
 static void
-mips_pop_frame (void)
-{
-  int regnum;
-  struct frame_info *frame = get_current_frame ();
-  CORE_ADDR new_sp = get_frame_base (frame);
-  mips_extra_func_info_t proc_desc;
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-  if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
-    {
-      generic_pop_dummy_frame ();
-      flush_cached_frames ();
-      return;
-    }
-
-  proc_desc = get_frame_extra_info (frame)->proc_desc;
-  write_register (PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
-  mips_find_saved_regs (frame);
-  for (regnum = 0; regnum < NUM_REGS; regnum++)
-    if (regnum != SP_REGNUM && regnum != PC_REGNUM
-       && deprecated_get_frame_saved_regs (frame)[regnum])
-      {
-       /* Floating point registers must not be sign extended, in case
-          mips_saved_regsize() = 4 but sizeof (FP0_REGNUM) == 8.  */
-
-       if (mips_regnum (current_gdbarch)->fp0 <= regnum && regnum < mips_regnum (current_gdbarch)->fp0 + 32)
-         write_register (regnum,
-                         read_memory_unsigned_integer (deprecated_get_frame_saved_regs (frame)[regnum],
-                                                       mips_saved_regsize (tdep)));
-       else
-         write_register (regnum,
-                         read_memory_integer (deprecated_get_frame_saved_regs (frame)[regnum],
-                                              mips_saved_regsize (tdep)));
-      }
-
-  write_register (SP_REGNUM, new_sp);
-  flush_cached_frames ();
-
-  if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
-    {
-      struct linked_proc_info *pi_ptr, *prev_ptr;
-
-      for (pi_ptr = linked_proc_desc_table, prev_ptr = NULL;
-          pi_ptr != NULL;
-          prev_ptr = pi_ptr, pi_ptr = pi_ptr->next)
-       {
-         if (&pi_ptr->info == proc_desc)
-           break;
-       }
-
-      if (pi_ptr == NULL)
-       error ("Can't locate dummy extra frame info\n");
-
-      if (prev_ptr != NULL)
-       prev_ptr->next = pi_ptr->next;
-      else
-       linked_proc_desc_table = pi_ptr->next;
-
-      xfree (pi_ptr);
-
-      write_register (mips_regnum (current_gdbarch)->hi,
-                     read_memory_integer ((new_sp
-                                           - 2 * mips_saved_regsize (tdep)),
-                                          mips_saved_regsize (tdep)));
-      write_register (mips_regnum (current_gdbarch)->lo,
-                     read_memory_integer ((new_sp
-                                           - 3 * mips_saved_regsize (tdep)),
-                                          mips_saved_regsize (tdep)));
-      if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
-       write_register (mips_regnum (current_gdbarch)->fp_control_status,
-                       read_memory_integer ((new_sp
-                                             - 4 * mips_saved_regsize (tdep)),
-                                            mips_saved_regsize (tdep)));
-    }
-}
-
-/* Floating point register management.
-
-   Background: MIPS1 & 2 fp registers are 32 bits wide.  To support
-   64bit operations, these early MIPS cpus treat fp register pairs
-   (f0,f1) as a single register (d0).  Later MIPS cpu's have 64 bit fp
-   registers and offer a compatibility mode that emulates the MIPS2 fp
-   model.  When operating in MIPS2 fp compat mode, later cpu's split
-   double precision floats into two 32-bit chunks and store them in
-   consecutive fp regs.  To display 64-bit floats stored in this
-   fashion, we have to combine 32 bits from f0 and 32 bits from f1.
-   Throw in user-configurable endianness and you have a real mess.
-
-   The way this works is:
-     - If we are in 32-bit mode or on a 32-bit processor, then a 64-bit
-       double-precision value will be split across two logical registers.
-       The lower-numbered logical register will hold the low-order bits,
-       regardless of the processor's endianness.
-     - If we are on a 64-bit processor, and we are looking for a
-       single-precision value, it will be in the low ordered bits
-       of a 64-bit GPR (after mfc1, for example) or a 64-bit register
-       save slot in memory.
-     - If we are in 64-bit mode, everything is straightforward.
-
-   Note that this code only deals with "live" registers at the top of the
-   stack.  We will attempt to deal with saved registers later, when
-   the raw/cooked register interface is in place. (We need a general
-   interface that can deal with dynamic saved register sizes -- fp
-   regs could be 32 bits wide in one frame and 64 on the frame above
-   and below).  */
-
-static struct type *
-mips_float_register_type (void)
-{
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-    return builtin_type_ieee_single_big;
-  else
-    return builtin_type_ieee_single_little;
-}
-
-static struct type *
-mips_double_register_type (void)
-{
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-    return builtin_type_ieee_double_big;
-  else
-    return builtin_type_ieee_double_little;
-}
-
-/* Copy a 32-bit single-precision value from the current frame
-   into rare_buffer.  */
-
-static void
-mips_read_fp_register_single (struct frame_info *frame, int regno,
-                             char *rare_buffer)
-{
-  int raw_size = register_size (current_gdbarch, regno);
-  char *raw_buffer = alloca (raw_size);
-
-  if (!frame_register_read (frame, regno, raw_buffer))
-    error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
-  if (raw_size == 8)
-    {
-      /* We have a 64-bit value for this register.  Find the low-order
-        32 bits.  */
-      int offset;
-
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       offset = 4;
-      else
-       offset = 0;
-
-      memcpy (rare_buffer, raw_buffer + offset, 4);
-    }
-  else
-    {
-      memcpy (rare_buffer, raw_buffer, 4);
-    }
-}
-
-/* Copy a 64-bit double-precision value from the current frame into
-   rare_buffer.  This may include getting half of it from the next
-   register.  */
-
-static void
-mips_read_fp_register_double (struct frame_info *frame, int regno,
-                             char *rare_buffer)
-{
-  int raw_size = register_size (current_gdbarch, regno);
-
-  if (raw_size == 8 && !mips2_fp_compat ())
-    {
-      /* We have a 64-bit value for this register, and we should use
-        all 64 bits.  */
-      if (!frame_register_read (frame, regno, rare_buffer))
-       error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
-    }
-  else
-    {
-      if ((regno - mips_regnum (current_gdbarch)->fp0) & 1)
-       internal_error (__FILE__, __LINE__,
-                       "mips_read_fp_register_double: bad access to "
-                       "odd-numbered FP register");
-
-      /* mips_read_fp_register_single will find the correct 32 bits from
-        each register.  */
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       {
-         mips_read_fp_register_single (frame, regno, rare_buffer + 4);
-         mips_read_fp_register_single (frame, regno + 1, rare_buffer);
-       }
-      else
-       {
-         mips_read_fp_register_single (frame, regno, rare_buffer);
-         mips_read_fp_register_single (frame, regno + 1, rare_buffer + 4);
-       }
-    }
-}
-
-static void
-mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
-                       int regnum)
-{                              /* do values for FP (float) regs */
-  char *raw_buffer;
-  double doub, flt1, flt2;     /* doubles extracted from raw hex data */
-  int inv1, inv2, namelen;
-
-  raw_buffer = (char *) alloca (2 * register_size (current_gdbarch, mips_regnum (current_gdbarch)->fp0));
-
-  fprintf_filtered (file, "%s:", REGISTER_NAME (regnum));
-  fprintf_filtered (file, "%*s", 4 - (int) strlen (REGISTER_NAME (regnum)),
-                   "");
-
-  if (register_size (current_gdbarch, regnum) == 4 || mips2_fp_compat ())
-    {
-      /* 4-byte registers: Print hex and floating.  Also print even
-         numbered registers as doubles.  */
-      mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
-
-      print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w', file);
-
-      fprintf_filtered (file, " flt: ");
-      if (inv1)
-       fprintf_filtered (file, " <invalid float> ");
-      else
-       fprintf_filtered (file, "%-17.9g", flt1);
-
-      if (regnum % 2 == 0)
-       {
-         mips_read_fp_register_double (frame, regnum, raw_buffer);
-         doub = unpack_double (mips_double_register_type (), raw_buffer,
-                               &inv2);
-
-         fprintf_filtered (file, " dbl: ");
-         if (inv2)
-           fprintf_filtered (file, "<invalid double>");
-         else
-           fprintf_filtered (file, "%-24.17g", doub);
-       }
-    }
-  else
-    {
-      /* Eight byte registers: print each one as hex, float and double.  */
-      mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
-
-      mips_read_fp_register_double (frame, regnum, raw_buffer);
-      doub = unpack_double (mips_double_register_type (), raw_buffer, &inv2);
-
-
-      print_scalar_formatted (raw_buffer, builtin_type_uint64, 'x', 'g', file);
-
-      fprintf_filtered (file, " flt: ");
-      if (inv1)
-       fprintf_filtered (file, "<invalid float>");
-      else
-       fprintf_filtered (file, "%-17.9g", flt1);
-
-      fprintf_filtered (file, " dbl: ");
-      if (inv2)
-       fprintf_filtered (file, "<invalid double>");
-      else
-       fprintf_filtered (file, "%-24.17g", doub);
-    }
-}
-
-static void
-mips_print_register (struct ui_file *file, struct frame_info *frame,
-                    int regnum, int all)
+mips_print_register (struct ui_file *file, struct frame_info *frame,
+                    int regnum, int all)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   char raw_buffer[MAX_REGISTER_SIZE];
@@ -4129,12 +3987,15 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
     fprintf_filtered (file, ": ");
 
   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-    offset = register_size (current_gdbarch, regnum) - register_size (current_gdbarch, regnum);
+    offset =
+      register_size (current_gdbarch,
+                    regnum) - register_size (current_gdbarch, regnum);
   else
     offset = 0;
 
-  print_scalar_formatted (raw_buffer + offset, gdbarch_register_type (gdbarch, regnum),
-                         'x', 0, file);
+  print_scalar_formatted (raw_buffer + offset,
+                         gdbarch_register_type (gdbarch, regnum), 'x', 0,
+                         file);
 }
 
 /* Replacement for generic do_registers_info.
@@ -4160,21 +4021,22 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   /* do values for GP (int) regs */
   char raw_buffer[MAX_REGISTER_SIZE];
-  int ncols = (mips_regsize (gdbarch) == 8 ? 4 : 8);   /* display cols per row */
+  int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8);       /* display cols per row */
   int col, byte;
   int regnum;
 
   /* For GP registers, we print a separate row of names above the vals */
   fprintf_filtered (file, "     ");
   for (col = 0, regnum = start_regnum;
-       col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS;
-       regnum++)
+       col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
     {
       if (*REGISTER_NAME (regnum) == '\0')
        continue;               /* unused register */
-      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
+      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+         TYPE_CODE_FLT)
        break;                  /* end the row: reached FP register */
-      fprintf_filtered (file, mips_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
+      fprintf_filtered (file,
+                       mips_abi_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
                        REGISTER_NAME (regnum));
       col++;
     }
@@ -4186,32 +4048,31 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
 
   /* now print the values in hex, 4 or 8 to the row */
   for (col = 0, regnum = start_regnum;
-       col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS;
-       regnum++)
+       col < ncols && regnum < NUM_REGS + NUM_PSEUDO_REGS; regnum++)
     {
       if (*REGISTER_NAME (regnum) == '\0')
        continue;               /* unused register */
-      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
+      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+         TYPE_CODE_FLT)
        break;                  /* end row: reached FP register */
       /* OK: get the data in raw format.  */
       if (!frame_register_read (frame, regnum, raw_buffer))
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
       /* pad small registers */
       for (byte = 0;
-          byte < (mips_regsize (current_gdbarch)
-                  - register_size (current_gdbarch, regnum));
-          byte++)
+          byte < (mips_abi_regsize (current_gdbarch)
+                  - register_size (current_gdbarch, regnum)); byte++)
        printf_filtered ("  ");
       /* Now print the register value in hex, endian order. */
       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-       for (byte = register_size (current_gdbarch, regnum) - register_size (current_gdbarch, regnum);
-            byte < register_size (current_gdbarch, regnum);
-            byte++)
+       for (byte =
+            register_size (current_gdbarch,
+                           regnum) - register_size (current_gdbarch, regnum);
+            byte < register_size (current_gdbarch, regnum); byte++)
          fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[byte]);
       else
        for (byte = register_size (current_gdbarch, regnum) - 1;
-            byte >= 0;
-            byte--)
+            byte >= 0; byte--)
          fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[byte]);
       fprintf_filtered (file, " ");
       col++;
@@ -4227,817 +4088,109 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
 static void
 mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
                           struct frame_info *frame, int regnum, int all)
-{
-  if (regnum != -1)            /* do one specified register */
-    {
-      gdb_assert (regnum >= NUM_REGS);
-      if (*(REGISTER_NAME (regnum)) == '\0')
-       error ("Not a valid register for the current processor type");
-
-      mips_print_register (file, frame, regnum, 0);
-      fprintf_filtered (file, "\n");
-    }
-  else
-    /* do all (or most) registers */
-    {
-      regnum = NUM_REGS;
-      while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
-       {
-         if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
-           {
-             if (all)          /* true for "INFO ALL-REGISTERS" command */
-               regnum = print_fp_register_row (file, frame, regnum);
-             else
-               regnum += MIPS_NUMREGS; /* skip floating point regs */
-           }
-         else
-           regnum = print_gp_register_row (file, frame, regnum);
-       }
-    }
-}
-
-/* Is this a branch with a delay slot?  */
-
-static int is_delayed (unsigned long);
-
-static int
-is_delayed (unsigned long insn)
-{
-  int i;
-  for (i = 0; i < NUMOPCODES; ++i)
-    if (mips_opcodes[i].pinfo != INSN_MACRO
-       && (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
-      break;
-  return (i < NUMOPCODES
-         && (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
-                                      | INSN_COND_BRANCH_DELAY
-                                      | INSN_COND_BRANCH_LIKELY)));
-}
-
-int
-mips_step_skips_delay (CORE_ADDR pc)
-{
-  char buf[MIPS_INSTLEN];
-
-  /* There is no branch delay slot on MIPS16.  */
-  if (pc_is_mips16 (pc))
-    return 0;
-
-  if (target_read_memory (pc, buf, MIPS_INSTLEN) != 0)
-    /* If error reading memory, guess that it is not a delayed branch.  */
-    return 0;
-  return is_delayed ((unsigned long) extract_unsigned_integer (buf, MIPS_INSTLEN));
-}
-
-
-/* Given PC at the function's start address, attempt to find the
-   prologue end using SAL information.  Return zero if the skip fails.
-
-   A non-optimized prologue traditionally has one SAL for the function
-   and a second for the function body.  A single line function has
-   them both pointing at the same line.
-
-   An optimized prologue is similar but the prologue may contain
-   instructions (SALs) from the instruction body.  Need to skip those
-   while not getting into the function body.
-
-   The functions end point and an increasing SAL line are used as
-   indicators of the prologue's endpoint.
-
-   This code is based on the function refine_prologue_limit (versions
-   found in both ia64 and ppc).  */
-
-static CORE_ADDR
-skip_prologue_using_sal (CORE_ADDR func_addr)
-{
-  struct symtab_and_line prologue_sal;
-  CORE_ADDR start_pc;
-  CORE_ADDR end_pc;
-
-  /* Get an initial range for the function.  */
-  find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
-  start_pc += FUNCTION_START_OFFSET;
-
-  prologue_sal = find_pc_line (start_pc, 0);
-  if (prologue_sal.line != 0)
-    {
-      while (prologue_sal.end < end_pc)
-       {
-         struct symtab_and_line sal;
-
-         sal = find_pc_line (prologue_sal.end, 0);
-         if (sal.line == 0)
-           break;
-         /* Assume that a consecutive SAL for the same (or larger)
-             line mark the prologue -> body transition.  */
-         if (sal.line >= prologue_sal.line)
-           break;
-         /* The case in which compiler's optimizer/scheduler has
-            moved instructions into the prologue.  We look ahead in
-            the function looking for address ranges whose
-            corresponding line number is less the first one that we
-            found for the function.  This is more conservative then
-            refine_prologue_limit which scans a large number of SALs
-            looking for any in the prologue */
-         prologue_sal = sal;
-       }
-    }
-  return prologue_sal.end;
-}
-
-/* Skip the PC past function prologue instructions (32-bit version).
-   This is a helper function for mips_skip_prologue.  */
-
-static CORE_ADDR
-mips32_skip_prologue (CORE_ADDR pc)
-{
-  t_inst inst;
-  CORE_ADDR end_pc;
-  int seen_sp_adjust = 0;
-  int load_immediate_bytes = 0;
-
-  /* Find an upper bound on the prologue.  */
-  end_pc = skip_prologue_using_sal (pc);
-  if (end_pc == 0)
-    end_pc = pc + 100; /* Magic.  */
-
-  /* Skip the typical prologue instructions. These are the stack adjustment
-     instruction and the instructions that save registers on the stack
-     or in the gcc frame.  */
-  for (; pc < end_pc; pc += MIPS_INSTLEN)
-    {
-      unsigned long high_word;
-
-      inst = mips_fetch_instruction (pc);
-      high_word = (inst >> 16) & 0xffff;
-
-      if (high_word == 0x27bd  /* addiu $sp,$sp,offset */
-         || high_word == 0x67bd)       /* daddiu $sp,$sp,offset */
-       seen_sp_adjust = 1;
-      else if (inst == 0x03a1e823 ||   /* subu $sp,$sp,$at */
-              inst == 0x03a8e823)      /* subu $sp,$sp,$t0 */
-       seen_sp_adjust = 1;
-      else if (((inst & 0xFFE00000) == 0xAFA00000      /* sw reg,n($sp) */
-               || (inst & 0xFFE00000) == 0xFFA00000)   /* sd reg,n($sp) */
-              && (inst & 0x001F0000))  /* reg != $zero */
-       continue;
-
-      else if ((inst & 0xFFE00000) == 0xE7A00000)      /* swc1 freg,n($sp) */
-       continue;
-      else if ((inst & 0xF3E00000) == 0xA3C00000 && (inst & 0x001F0000))
-       /* sx reg,n($s8) */
-       continue;               /* reg != $zero */
-
-      /* move $s8,$sp.  With different versions of gas this will be either
-         `addu $s8,$sp,$zero' or `or $s8,$sp,$zero' or `daddu s8,sp,$0'.
-         Accept any one of these.  */
-      else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
-       continue;
-
-      else if ((inst & 0xFF9F07FF) == 0x00800021)      /* move reg,$a0-$a3 */
-       continue;
-      else if (high_word == 0x3c1c)    /* lui $gp,n */
-       continue;
-      else if (high_word == 0x279c)    /* addiu $gp,$gp,n */
-       continue;
-      else if (inst == 0x0399e021      /* addu $gp,$gp,$t9 */
-              || inst == 0x033ce021)   /* addu $gp,$t9,$gp */
-       continue;
-      /* The following instructions load $at or $t0 with an immediate
-         value in preparation for a stack adjustment via
-         subu $sp,$sp,[$at,$t0]. These instructions could also initialize
-         a local variable, so we accept them only before a stack adjustment
-         instruction was seen.  */
-      else if (!seen_sp_adjust)
-       {
-         if (high_word == 0x3c01 ||    /* lui $at,n */
-             high_word == 0x3c08)      /* lui $t0,n */
-           {
-             load_immediate_bytes += MIPS_INSTLEN;     /* FIXME!! */
-             continue;
-           }
-         else if (high_word == 0x3421 ||       /* ori $at,$at,n */
-                  high_word == 0x3508 ||       /* ori $t0,$t0,n */
-                  high_word == 0x3401 ||       /* ori $at,$zero,n */
-                  high_word == 0x3408)         /* ori $t0,$zero,n */
-           {
-             load_immediate_bytes += MIPS_INSTLEN;     /* FIXME!! */
-             continue;
-           }
-         else
-           break;
-       }
-      else
-       break;
-    }
-
-  /* In a frameless function, we might have incorrectly
-     skipped some load immediate instructions. Undo the skipping
-     if the load immediate was not followed by a stack adjustment.  */
-  if (load_immediate_bytes && !seen_sp_adjust)
-    pc -= load_immediate_bytes;
-  return pc;
-}
-
-/* Skip the PC past function prologue instructions (16-bit version).
-   This is a helper function for mips_skip_prologue.  */
-
-static CORE_ADDR
-mips16_skip_prologue (CORE_ADDR pc)
-{
-  CORE_ADDR end_pc;
-  int extend_bytes = 0;
-  int prev_extend_bytes;
-
-  /* Table of instructions likely to be found in a function prologue.  */
-  static struct
-    {
-      unsigned short inst;
-      unsigned short mask;
-    }
-  table[] =
-  {
-    {
-      0x6300, 0xff00
-    }
-    ,                          /* addiu $sp,offset */
-    {
-      0xfb00, 0xff00
-    }
-    ,                          /* daddiu $sp,offset */
-    {
-      0xd000, 0xf800
-    }
-    ,                          /* sw reg,n($sp) */
-    {
-      0xf900, 0xff00
-    }
-    ,                          /* sd reg,n($sp) */
-    {
-      0x6200, 0xff00
-    }
-    ,                          /* sw $ra,n($sp) */
-    {
-      0xfa00, 0xff00
-    }
-    ,                          /* sd $ra,n($sp) */
-    {
-      0x673d, 0xffff
-    }
-    ,                          /* move $s1,sp */
-    {
-      0xd980, 0xff80
-    }
-    ,                          /* sw $a0-$a3,n($s1) */
-    {
-      0x6704, 0xff1c
-    }
-    ,                          /* move reg,$a0-$a3 */
-    {
-      0xe809, 0xf81f
-    }
-    ,                          /* entry pseudo-op */
-    {
-      0x0100, 0xff00
-    }
-    ,                          /* addiu $s1,$sp,n */
-    {
-      0, 0
-    }                          /* end of table marker */
-  };
-
-  /* Find an upper bound on the prologue.  */
-  end_pc = skip_prologue_using_sal (pc);
-  if (end_pc == 0)
-    end_pc = pc + 100; /* Magic.  */
-
-  /* Skip the typical prologue instructions. These are the stack adjustment
-     instruction and the instructions that save registers on the stack
-     or in the gcc frame.  */
-  for (; pc < end_pc; pc += MIPS16_INSTLEN)
-    {
-      unsigned short inst;
-      int i;
-
-      inst = mips_fetch_instruction (pc);
-
-      /* Normally we ignore an extend instruction.  However, if it is
-         not followed by a valid prologue instruction, we must adjust
-         the pc back over the extend so that it won't be considered
-         part of the prologue.  */
-      if ((inst & 0xf800) == 0xf000)   /* extend */
-       {
-         extend_bytes = MIPS16_INSTLEN;
-         continue;
-       }
-      prev_extend_bytes = extend_bytes;
-      extend_bytes = 0;
-
-      /* Check for other valid prologue instructions besides extend.  */
-      for (i = 0; table[i].mask != 0; i++)
-       if ((inst & table[i].mask) == table[i].inst)    /* found, get out */
-         break;
-      if (table[i].mask != 0)  /* it was in table? */
-       continue;               /* ignore it */
-      else
-       /* non-prologue */
-       {
-         /* Return the current pc, adjusted backwards by 2 if
-            the previous instruction was an extend.  */
-         return pc - prev_extend_bytes;
-       }
-    }
-  return pc;
-}
-
-/* To skip prologues, I use this predicate.  Returns either PC itself
-   if the code at PC does not look like a function prologue; otherwise
-   returns an address that (if we're lucky) follows the prologue.  If
-   LENIENT, then we must skip everything which is involved in setting
-   up the frame (it's OK to skip more, just so long as we don't skip
-   anything which might clobber the registers which are being saved.
-   We must skip more in the case where part of the prologue is in the
-   delay slot of a non-prologue instruction).  */
-
-static CORE_ADDR
-mips_skip_prologue (CORE_ADDR pc)
-{
-  /* See if we can determine the end of the prologue via the symbol table.
-     If so, then return either PC, or the PC after the prologue, whichever
-     is greater.  */
-
-  CORE_ADDR post_prologue_pc = after_prologue (pc, NULL);
-
-  if (post_prologue_pc != 0)
-    return max (pc, post_prologue_pc);
-
-  /* Can't determine prologue from the symbol table, need to examine
-     instructions.  */
-
-  if (pc_is_mips16 (pc))
-    return mips16_skip_prologue (pc);
-  else
-    return mips32_skip_prologue (pc);
-}
-
-/* Determine how a return value is stored within the MIPS register
-   file, given the return type `valtype'. */
-
-struct return_value_word
-{
-  int len;
-  int reg;
-  int reg_offset;
-  int buf_offset;
-};
-
-static void
-return_value_location (struct type *valtype,
-                      struct return_value_word *hi,
-                      struct return_value_word *lo)
-{
-  int len = TYPE_LENGTH (valtype);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-  if (TYPE_CODE (valtype) == TYPE_CODE_FLT
-      && ((MIPS_FPU_TYPE == MIPS_FPU_DOUBLE && (len == 4 || len == 8))
-         || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE && len == 4)))
-    {
-      if (!FP_REGISTER_DOUBLE && len == 8)
-       {
-         /* We need to break a 64bit float in two 32 bit halves and
-            spread them across a floating-point register pair. */
-         lo->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
-         hi->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 0 : 4;
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                            && register_size (current_gdbarch, mips_regnum (current_gdbarch)->fp0) == 8)
-                           ? 4 : 0);
-         hi->reg_offset = lo->reg_offset;
-         lo->reg = mips_regnum (current_gdbarch)->fp0 + 0;
-         hi->reg = mips_regnum (current_gdbarch)->fp0 + 1;
-         lo->len = 4;
-         hi->len = 4;
-       }
-      else
-       {
-         /* The floating point value fits in a single floating-point
-            register. */
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                            && register_size (current_gdbarch, mips_regnum (current_gdbarch)->fp0) == 8
-                            && len == 4)
-                           ? 4 : 0);
-         lo->reg = mips_regnum (current_gdbarch)->fp0;
-         lo->len = len;
-         lo->buf_offset = 0;
-         hi->len = 0;
-         hi->reg_offset = 0;
-         hi->buf_offset = 0;
-         hi->reg = 0;
-       }
-    }
-  else
-    {
-      /* Locate a result possibly spread across two registers. */
-      int regnum = 2;
-      lo->reg = regnum + 0;
-      hi->reg = regnum + 1;
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-         && len < mips_saved_regsize (tdep))
-       {
-         /* "un-left-justify" the value in the low register */
-         lo->reg_offset = mips_saved_regsize (tdep) - len;
-         lo->len = len;
-         hi->reg_offset = 0;
-         hi->len = 0;
-       }
-      else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-              && len > mips_saved_regsize (tdep)       /* odd-size structs */
-              && len < mips_saved_regsize (tdep) * 2
-              && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
-                  TYPE_CODE (valtype) == TYPE_CODE_UNION))
-       {
-         /* "un-left-justify" the value spread across two registers. */
-         lo->reg_offset = 2 * mips_saved_regsize (tdep) - len;
-         lo->len = mips_saved_regsize (tdep) - lo->reg_offset;
-         hi->reg_offset = 0;
-         hi->len = len - lo->len;
-       }
-      else
-       {
-         /* Only perform a partial copy of the second register. */
-         lo->reg_offset = 0;
-         hi->reg_offset = 0;
-         if (len > mips_saved_regsize (tdep))
-           {
-             lo->len = mips_saved_regsize (tdep);
-             hi->len = len - mips_saved_regsize (tdep);
-           }
-         else
-           {
-             lo->len = len;
-             hi->len = 0;
-           }
-       }
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-         && register_size (current_gdbarch, regnum) == 8
-         && mips_saved_regsize (tdep) == 4)
-       {
-         /* Account for the fact that only the least-signficant part
-            of the register is being used */
-         lo->reg_offset += 4;
-         hi->reg_offset += 4;
-       }
-      lo->buf_offset = 0;
-      hi->buf_offset = lo->len;
-    }
-}
-
-/* Given a return value in `regbuf' with a type `valtype', extract and
-   copy its value into `valbuf'. */
-
-static void
-mips_eabi_extract_return_value (struct type *valtype,
-                               char regbuf[],
-                               char *valbuf)
-{
-  struct return_value_word lo;
-  struct return_value_word hi;
-  return_value_location (valtype, &hi, &lo);
-
-  memcpy (valbuf + lo.buf_offset,
-         regbuf + DEPRECATED_REGISTER_BYTE (NUM_REGS + lo.reg) + lo.reg_offset,
-         lo.len);
-
-  if (hi.len > 0)
-    memcpy (valbuf + hi.buf_offset,
-           regbuf + DEPRECATED_REGISTER_BYTE (NUM_REGS + hi.reg) + hi.reg_offset,
-           hi.len);
-}
-
-static void
-mips_o64_extract_return_value (struct type *valtype,
-                              char regbuf[],
-                              char *valbuf)
-{
-  struct return_value_word lo;
-  struct return_value_word hi;
-  return_value_location (valtype, &hi, &lo);
-
-  memcpy (valbuf + lo.buf_offset,
-         regbuf + DEPRECATED_REGISTER_BYTE (NUM_REGS + lo.reg) + lo.reg_offset,
-         lo.len);
-
-  if (hi.len > 0)
-    memcpy (valbuf + hi.buf_offset,
-           regbuf + DEPRECATED_REGISTER_BYTE (NUM_REGS + hi.reg) + hi.reg_offset,
-           hi.len);
-}
-
-/* Given a return value in `valbuf' with a type `valtype', write it's
-   value into the appropriate register. */
-
-static void
-mips_eabi_store_return_value (struct type *valtype, char *valbuf)
-{
-  char raw_buffer[MAX_REGISTER_SIZE];
-  struct return_value_word lo;
-  struct return_value_word hi;
-  return_value_location (valtype, &hi, &lo);
-
-  memset (raw_buffer, 0, sizeof (raw_buffer));
-  memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
-  deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (lo.reg), raw_buffer,
-                                  register_size (current_gdbarch, lo.reg));
-
-  if (hi.len > 0)
-    {
-      memset (raw_buffer, 0, sizeof (raw_buffer));
-      memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len);
-      deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (hi.reg), raw_buffer,
-                                      register_size (current_gdbarch, hi.reg));
-    }
-}
-
-static void
-mips_o64_store_return_value (struct type *valtype, char *valbuf)
-{
-  char raw_buffer[MAX_REGISTER_SIZE];
-  struct return_value_word lo;
-  struct return_value_word hi;
-  return_value_location (valtype, &hi, &lo);
-
-  memset (raw_buffer, 0, sizeof (raw_buffer));
-  memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
-  deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (lo.reg), raw_buffer,
-                                  register_size (current_gdbarch, lo.reg));
-
-  if (hi.len > 0)
-    {
-      memset (raw_buffer, 0, sizeof (raw_buffer));
-      memcpy (raw_buffer + hi.reg_offset, valbuf + hi.buf_offset, hi.len);
-      deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (hi.reg), raw_buffer,
-                                      register_size (current_gdbarch, hi.reg));
-    }
-}
-
-/* O32 ABI stuff.  */
-
-static enum return_value_convention
-mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
-                      struct regcache *regcache,
-                      void *readbuf, const void *writebuf)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-
-  if (TYPE_CODE (type)== TYPE_CODE_STRUCT
-      || TYPE_CODE (type)== TYPE_CODE_UNION
-      || TYPE_CODE (type)== TYPE_CODE_ARRAY)
-    return RETURN_VALUE_STRUCT_CONVENTION;
-  else if (TYPE_CODE (type) == TYPE_CODE_FLT
-          && TYPE_LENGTH (type) == 4
-          && tdep->mips_fpu_type != MIPS_FPU_NONE)
-    {
-      /* A single-precision floating-point value.  It fits in the
-         least significant part of FP0.  */
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
-      mips_xfer_register (regcache,
-                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
-                         TYPE_LENGTH (type),
-                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else if (TYPE_CODE (type) == TYPE_CODE_FLT
-          && TYPE_LENGTH (type) == 8
-          && tdep->mips_fpu_type != MIPS_FPU_NONE)
-    {
-      /* A double-precision floating-point value.  The most
-         significant part goes in FP1, and the least significant in
-         FP0.  */
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stderr, "Return float in $fp1/$fp0\n");
-      switch (TARGET_BYTE_ORDER)
-       {
-       case BFD_ENDIAN_LITTLE:
-         mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 0,
-                             4, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
-         mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 1,
-                             4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
-         break;
-       case BFD_ENDIAN_BIG:
-         mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 1,
-                             4, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
-         mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 + 0,
-                             4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
-         break;
-       default:
-         internal_error (__FILE__, __LINE__, "bad switch");
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-#if 0
-  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-          && TYPE_NFIELDS (type) <= 2
-          && TYPE_NFIELDS (type) >= 1
-          && ((TYPE_NFIELDS (type) == 1
-               && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
-                   == TYPE_CODE_FLT))
-              || (TYPE_NFIELDS (type) == 2
-                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
-                      == TYPE_CODE_FLT)
-                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1))
-                      == TYPE_CODE_FLT)))
-          && tdep->mips_fpu_type != MIPS_FPU_NONE)
-    {
-      /* A struct that contains one or two floats.  Each value is part
-         in the least significant part of their floating point
-         register..  */
-      bfd_byte reg[MAX_REGISTER_SIZE];
-      int regnum;
-      int field;
-      for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
-          field < TYPE_NFIELDS (type);
-          field++, regnum += 2)
-       {
-         int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field])
-                       / TARGET_CHAR_BIT);
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n", offset);
-         mips_xfer_register (regcache, NUM_REGS + regnum,
-                             TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-#endif
-#if 0
-  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-          || TYPE_CODE (type) == TYPE_CODE_UNION)
-    {
-      /* A structure or union.  Extract the left justified value,
-         regardless of the byte order.  I.e. DO NOT USE
-         mips_xfer_lower.  */
-      int offset;
-      int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
-          offset < TYPE_LENGTH (type);
-          offset += register_size (current_gdbarch, regnum), regnum++)
-       {
-         int xfer = register_size (current_gdbarch, regnum);
-         if (offset + xfer > TYPE_LENGTH (type))
-           xfer = TYPE_LENGTH (type) - offset;
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n",
-                               offset, xfer, regnum);
-         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
-                             BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-#endif
-  else
-    {
-      /* A scalar extract each part but least-significant-byte
-         justified.  o32 thinks registers are 4 byte, regardless of
-         the ISA.  mips_stack_argsize controls this.  */
-      int offset;
-      int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
-          offset < TYPE_LENGTH (type);
-          offset += mips_stack_argsize (tdep), regnum++)
-       {
-         int xfer = mips_stack_argsize (tdep);
-         int pos = 0;
-         if (offset + xfer > TYPE_LENGTH (type))
-           xfer = TYPE_LENGTH (type) - offset;
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n",
-                               offset, xfer, regnum);
-         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-}
-
-/* N32/N44 ABI stuff.  */
-
-static enum return_value_convention
-mips_n32n64_return_value (struct gdbarch *gdbarch,
-                         struct type *type, struct regcache *regcache,
-                         void *readbuf, const void *writebuf)
-{
-  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  if (TYPE_CODE (type)== TYPE_CODE_STRUCT
-      || TYPE_CODE (type)== TYPE_CODE_UNION
-      || TYPE_CODE (type)== TYPE_CODE_ARRAY
-      || TYPE_LENGTH (type) > 2 * mips_saved_regsize (tdep))
-    return RETURN_VALUE_STRUCT_CONVENTION;
-  else if (TYPE_CODE (type) == TYPE_CODE_FLT
-          && tdep->mips_fpu_type != MIPS_FPU_NONE)
-    {
-      /* A floating-point value belongs in the least significant part
-         of FP0.  */
-      if (mips_debug)
-       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
-      mips_xfer_register (regcache,
-                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
-                         TYPE_LENGTH (type),
-                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-          && TYPE_NFIELDS (type) <= 2
-          && TYPE_NFIELDS (type) >= 1
-          && ((TYPE_NFIELDS (type) == 1
-               && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
-                   == TYPE_CODE_FLT))
-              || (TYPE_NFIELDS (type) == 2
-                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0))
-                      == TYPE_CODE_FLT)
-                  && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1))
-                      == TYPE_CODE_FLT)))
-          && tdep->mips_fpu_type != MIPS_FPU_NONE)
-    {
-      /* A struct that contains one or two floats.  Each value is part
-         in the least significant part of their floating point
-         register..  */
-      bfd_byte reg[MAX_REGISTER_SIZE];
-      int regnum;
-      int field;
-      for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
-          field < TYPE_NFIELDS (type);
-          field++, regnum += 2)
-       {
-         int offset = (FIELD_BITPOS (TYPE_FIELDS (type)[field])
-                       / TARGET_CHAR_BIT);
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n", offset);
-         mips_xfer_register (regcache, NUM_REGS + regnum,
-                             TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
-    }
-  else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-          || TYPE_CODE (type) == TYPE_CODE_UNION)
+{
+  if (regnum != -1)            /* do one specified register */
     {
-      /* A structure or union.  Extract the left justified value,
-         regardless of the byte order.  I.e. DO NOT USE
-         mips_xfer_lower.  */
-      int offset;
-      int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
-          offset < TYPE_LENGTH (type);
-          offset += register_size (current_gdbarch, regnum), regnum++)
-       {
-         int xfer = register_size (current_gdbarch, regnum);
-         if (offset + xfer > TYPE_LENGTH (type))
-           xfer = TYPE_LENGTH (type) - offset;
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return struct+%d:%d in $%d\n",
-                               offset, xfer, regnum);
-         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
-                             BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
-       }
-      return RETURN_VALUE_REGISTER_CONVENTION;
+      gdb_assert (regnum >= NUM_REGS);
+      if (*(REGISTER_NAME (regnum)) == '\0')
+       error ("Not a valid register for the current processor type");
+
+      mips_print_register (file, frame, regnum, 0);
+      fprintf_filtered (file, "\n");
     }
   else
+    /* do all (or most) registers */
     {
-      /* A scalar extract each part but least-significant-byte
-         justified.  */
-      int offset;
-      int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
-          offset < TYPE_LENGTH (type);
-          offset += register_size (current_gdbarch, regnum), regnum++)
+      regnum = NUM_REGS;
+      while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
        {
-         int xfer = register_size (current_gdbarch, regnum);
-         int pos = 0;
-         if (offset + xfer > TYPE_LENGTH (type))
-           xfer = TYPE_LENGTH (type) - offset;
-         if (mips_debug)
-           fprintf_unfiltered (gdb_stderr, "Return scalar+%d:%d in $%d\n",
-                               offset, xfer, regnum);
-         mips_xfer_register (regcache, NUM_REGS + regnum, xfer,
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+         if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+             TYPE_CODE_FLT)
+           {
+             if (all)          /* true for "INFO ALL-REGISTERS" command */
+               regnum = print_fp_register_row (file, frame, regnum);
+             else
+               regnum += MIPS_NUMREGS; /* skip floating point regs */
+           }
+         else
+           regnum = print_gp_register_row (file, frame, regnum);
        }
-      return RETURN_VALUE_REGISTER_CONVENTION;
     }
 }
 
-/* Exported procedure: Is PC in the signal trampoline code */
+/* Is this a branch with a delay slot?  */
 
 static int
-mips_pc_in_sigtramp (CORE_ADDR pc, char *ignore)
+is_delayed (unsigned long insn)
+{
+  int i;
+  for (i = 0; i < NUMOPCODES; ++i)
+    if (mips_opcodes[i].pinfo != INSN_MACRO
+       && (insn & mips_opcodes[i].mask) == mips_opcodes[i].match)
+      break;
+  return (i < NUMOPCODES
+         && (mips_opcodes[i].pinfo & (INSN_UNCOND_BRANCH_DELAY
+                                      | INSN_COND_BRANCH_DELAY
+                                      | INSN_COND_BRANCH_LIKELY)));
+}
+
+int
+mips_single_step_through_delay (struct gdbarch *gdbarch,
+                               struct frame_info *frame)
+{
+  CORE_ADDR pc = get_frame_pc (frame);
+  char buf[MIPS_INSN32_SIZE];
+
+  /* There is no branch delay slot on MIPS16.  */
+  if (mips_pc_is_mips16 (pc))
+    return 0;
+
+  if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
+    /* If error reading memory, guess that it is not a delayed
+       branch.  */
+    return 0;
+  return is_delayed (extract_unsigned_integer (buf, sizeof buf));
+}
+
+/* To skip prologues, I use this predicate.  Returns either PC itself
+   if the code at PC does not look like a function prologue; otherwise
+   returns an address that (if we're lucky) follows the prologue.  If
+   LENIENT, then we must skip everything which is involved in setting
+   up the frame (it's OK to skip more, just so long as we don't skip
+   anything which might clobber the registers which are being saved.
+   We must skip more in the case where part of the prologue is in the
+   delay slot of a non-prologue instruction).  */
+
+static CORE_ADDR
+mips_skip_prologue (CORE_ADDR pc)
 {
-  if (sigtramp_address == 0)
-    fixup_sigtramp ();
-  return (pc >= sigtramp_address && pc < sigtramp_end);
+  CORE_ADDR limit_pc;
+  CORE_ADDR func_addr;
+
+  /* See if we can determine the end of the prologue via the symbol table.
+     If so, then return either PC, or the PC after the prologue, whichever
+     is greater.  */
+  if (find_pc_partial_function (pc, NULL, &func_addr, NULL))
+    {
+      CORE_ADDR post_prologue_pc = skip_prologue_using_sal (func_addr);
+      if (post_prologue_pc != 0)
+       return max (pc, post_prologue_pc);
+    }
+
+  /* Can't determine prologue from the symbol table, need to examine
+     instructions.  */
+
+  /* Find an upper limit on the function prologue using the debug
+     information.  If the debug information could not be used to provide
+     that bound, then use an arbitrary large number as the upper bound.  */
+  limit_pc = skip_prologue_using_sal (pc);
+  if (limit_pc == 0)
+    limit_pc = pc + 100;          /* Magic.  */
+
+  if (mips_pc_is_mips16 (pc))
+    return mips16_scan_prologue (pc, limit_pc, NULL, NULL);
+  else
+    return mips32_scan_prologue (pc, limit_pc, NULL, NULL);
 }
 
 /* Root of all "set mips "/"show mips " commands. This will eventually be
@@ -5052,7 +4205,8 @@ show_mips_command (char *args, int from_tty)
 static void
 set_mips_command (char *args, int from_tty)
 {
-  printf_unfiltered ("\"set mips\" must be followed by an appropriate subcommand.\n");
+  printf_unfiltered
+    ("\"set mips\" must be followed by an appropriate subcommand.\n");
   help_list (setmipscmdlist, "set mips ", all_commands, gdb_stdout);
 }
 
@@ -5077,18 +4231,20 @@ show_mipsfpu_command (char *args, int from_tty)
       internal_error (__FILE__, __LINE__, "bad switch");
     }
   if (mips_fpu_type_auto)
-    printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
-                      fpu);
+    printf_unfiltered
+      ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
+       fpu);
   else
-    printf_unfiltered ("The MIPS floating-point coprocessor is assumed to be %s\n",
-                      fpu);
+    printf_unfiltered
+      ("The MIPS floating-point coprocessor is assumed to be %s\n", fpu);
 }
 
 
 static void
 set_mipsfpu_command (char *args, int from_tty)
 {
-  printf_unfiltered ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
+  printf_unfiltered
+    ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
   show_mipsfpu_command (args, from_tty);
 }
 
@@ -5152,7 +4308,7 @@ deprecated_mips_set_processor_regs_hack (void)
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
   CORE_ADDR prid;
 
-  prid = read_register (PRID_REGNUM);
+  prid = read_register (MIPS_PRID_REGNUM);
 
   if ((prid & ~0xf) == 0x700)
     tdep->mips_processor_reg_names = mips_r3041_reg_names;
@@ -5172,44 +4328,22 @@ static int
 gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  mips_extra_func_info_t proc_desc;
-
-  /* Search for the function containing this address.  Set the low bit
-     of the address when searching, in case we were given an even address
-     that is the start of a 16-bit function.  If we didn't do this,
-     the search would fail because the symbol table says the function
-     starts at an odd address, i.e. 1 byte past the given address.  */
-  memaddr = ADDR_BITS_REMOVE (memaddr);
-  proc_desc = non_heuristic_proc_desc (make_mips16_addr (memaddr), NULL);
-
-  /* Make an attempt to determine if this is a 16-bit function.  If
-     the procedure descriptor exists and the address therein is odd,
-     it's definitely a 16-bit function.  Otherwise, we have to just
-     guess that if the address passed in is odd, it's 16-bits.  */
+
   /* FIXME: cagney/2003-06-26: Is this even necessary?  The
      disassembler needs to be able to locally determine the ISA, and
      not rely on GDB.  Otherwize the stand-alone 'objdump -d' will not
      work.  */
-  if (proc_desc)
-    {
-      if (pc_is_mips16 (PROC_LOW_ADDR (proc_desc)))
-       info->mach =  bfd_mach_mips16;
-    }
-  else
-    {
-      if (pc_is_mips16 (memaddr))
-       info->mach = bfd_mach_mips16;
-    } 
+  if (mips_pc_is_mips16 (memaddr))
+    info->mach = bfd_mach_mips16;
 
   /* Round down the instruction address to the appropriate boundary.  */
   memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
 
   /* Set the disassembler options.  */
-  if (tdep->mips_abi == MIPS_ABI_N32
-      || tdep->mips_abi == MIPS_ABI_N64)
+  if (tdep->mips_abi == MIPS_ABI_N32 || tdep->mips_abi == MIPS_ABI_N64)
     {
       /* Set up the disassembler info, so that we get the right
-        register names from libopcodes.  */
+         register names from libopcodes.  */
       if (tdep->mips_abi == MIPS_ABI_N32)
        info->disassembler_options = "gpr-names=n32";
       else
@@ -5239,13 +4373,13 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
    breakpoint should be inserted.  */
 
 static const unsigned char *
-mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
+mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
   if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     {
-      if (pc_is_mips16 (*pcptr))
+      if (mips_pc_is_mips16 (*pcptr))
        {
-         static unsigned char mips16_big_breakpoint[] = {0xe8, 0xa5};
+         static unsigned char mips16_big_breakpoint[] = { 0xe8, 0xa5 };
          *pcptr = unmake_mips16_addr (*pcptr);
          *lenptr = sizeof (mips16_big_breakpoint);
          return mips16_big_breakpoint;
@@ -5255,9 +4389,9 @@ mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
          /* The IDT board uses an unusual breakpoint value, and
             sometimes gets confused when it sees the usual MIPS
             breakpoint instruction.  */
-         static unsigned char big_breakpoint[] = {0, 0x5, 0, 0xd};
-         static unsigned char pmon_big_breakpoint[] = {0, 0, 0, 0xd};
-         static unsigned char idt_big_breakpoint[] = {0, 0, 0x0a, 0xd};
+         static unsigned char big_breakpoint[] = { 0, 0x5, 0, 0xd };
+         static unsigned char pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
+         static unsigned char idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
 
          *lenptr = sizeof (big_breakpoint);
 
@@ -5273,18 +4407,18 @@ mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
     }
   else
     {
-      if (pc_is_mips16 (*pcptr))
+      if (mips_pc_is_mips16 (*pcptr))
        {
-         static unsigned char mips16_little_breakpoint[] = {0xa5, 0xe8};
+         static unsigned char mips16_little_breakpoint[] = { 0xa5, 0xe8 };
          *pcptr = unmake_mips16_addr (*pcptr);
          *lenptr = sizeof (mips16_little_breakpoint);
          return mips16_little_breakpoint;
        }
       else
        {
-         static unsigned char little_breakpoint[] = {0xd, 0, 0x5, 0};
-         static unsigned char pmon_little_breakpoint[] = {0xd, 0, 0, 0};
-         static unsigned char idt_little_breakpoint[] = {0xd, 0x0a, 0, 0};
+         static unsigned char little_breakpoint[] = { 0xd, 0, 0x5, 0 };
+         static unsigned char pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
+         static unsigned char idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
 
          *lenptr = sizeof (little_breakpoint);
 
@@ -5314,13 +4448,10 @@ mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
    a return stub and the target PC is in $18.
 
    See the source code for the stubs in gcc/config/mips/mips16.S for
-   gory details.
-
-   This function implements the SKIP_TRAMPOLINE_CODE macro.
- */
+   gory details.  */
 
 static CORE_ADDR
-mips_skip_stub (CORE_ADDR pc)
+mips_skip_trampoline_code (CORE_ADDR pc)
 {
   char *name;
   CORE_ADDR start_addr;
@@ -5333,7 +4464,7 @@ mips_skip_stub (CORE_ADDR pc)
      target PC is in $31 ($ra).  */
   if (strcmp (name, "__mips16_ret_sf") == 0
       || strcmp (name, "__mips16_ret_df") == 0)
-    return read_signed_register (RA_REGNUM);
+    return read_signed_register (MIPS_RA_REGNUM);
 
   if (strncmp (name, "__mips16_call_stub_", 19) == 0)
     {
@@ -5363,11 +4494,12 @@ mips_skip_stub (CORE_ADDR pc)
                 address from those two instructions.  */
 
              CORE_ADDR target_pc = read_signed_register (2);
-             t_inst inst;
+             ULONGEST inst;
              int i;
 
              /* See if the name of the target function is  __fn_stub_*.  */
-             if (find_pc_partial_function (target_pc, &name, NULL, NULL) == 0)
+             if (find_pc_partial_function (target_pc, &name, NULL, NULL) ==
+                 0)
                return target_pc;
              if (strncmp (name, "__fn_stub_", 10) != 0
                  && strcmp (name, "etext") != 0
@@ -5377,7 +4509,7 @@ mips_skip_stub (CORE_ADDR pc)
              /* Scan through this _fn_stub_ code for the lui/addiu pair.
                 The limit on the search is arbitrarily set to 20
                 instructions.  FIXME.  */
-             for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSTLEN)
+             for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSN32_SIZE)
                {
                  inst = mips_fetch_instruction (target_pc);
                  if ((inst & 0xffff0000) == 0x3c010000)        /* lui $at */
@@ -5398,142 +4530,6 @@ mips_skip_stub (CORE_ADDR pc)
   return 0;                    /* not a stub */
 }
 
-
-/* Return non-zero if the PC is inside a call thunk (aka stub or trampoline).
-   This implements the IN_SOLIB_CALL_TRAMPOLINE macro.  */
-
-static int
-mips_in_call_stub (CORE_ADDR pc, char *name)
-{
-  CORE_ADDR start_addr;
-
-  /* Find the starting address of the function containing the PC.  If the
-     caller didn't give us a name, look it up at the same time.  */
-  if (find_pc_partial_function (pc, name ? NULL : &name, &start_addr, NULL) == 0)
-    return 0;
-
-  if (strncmp (name, "__mips16_call_stub_", 19) == 0)
-    {
-      /* If the PC is in __mips16_call_stub_{1..10}, this is a call stub.  */
-      if (name[19] >= '0' && name[19] <= '9')
-       return 1;
-      /* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
-         before the jal instruction, this is effectively a call stub.  */
-      else if (name[19] == 's' || name[19] == 'd')
-       return pc == start_addr;
-    }
-
-  return 0;                    /* not a stub */
-}
-
-
-/* Return non-zero if the PC is inside a return thunk (aka stub or trampoline).
-   This implements the IN_SOLIB_RETURN_TRAMPOLINE macro.  */
-
-static int
-mips_in_return_stub (CORE_ADDR pc, char *name)
-{
-  CORE_ADDR start_addr;
-
-  /* Find the starting address of the function containing the PC.  */
-  if (find_pc_partial_function (pc, NULL, &start_addr, NULL) == 0)
-    return 0;
-
-  /* If the PC is in __mips16_ret_{d,s}f, this is a return stub.  */
-  if (strcmp (name, "__mips16_ret_sf") == 0
-      || strcmp (name, "__mips16_ret_df") == 0)
-    return 1;
-
-  /* If the PC is in __mips16_call_stub_{s,d}f_{0..10} but not at the start,
-     i.e. after the jal instruction, this is effectively a return stub.  */
-  if (strncmp (name, "__mips16_call_stub_", 19) == 0
-      && (name[19] == 's' || name[19] == 'd')
-      && pc != start_addr)
-    return 1;
-
-  return 0;                    /* not a stub */
-}
-
-
-/* Return non-zero if the PC is in a library helper function that should
-   be ignored.  This implements the IGNORE_HELPER_CALL macro.  */
-
-int
-mips_ignore_helper (CORE_ADDR pc)
-{
-  char *name;
-
-  /* Find the starting address and name of the function containing the PC.  */
-  if (find_pc_partial_function (pc, &name, NULL, NULL) == 0)
-    return 0;
-
-  /* If the PC is in __mips16_ret_{d,s}f, this is a library helper function
-     that we want to ignore.  */
-  return (strcmp (name, "__mips16_ret_sf") == 0
-         || strcmp (name, "__mips16_ret_df") == 0);
-}
-
-
-/* When debugging a 64 MIPS target running a 32 bit ABI, the size of
-   the register stored on the stack (32) is different to its real raw
-   size (64).  The below ensures that registers are fetched from the
-   stack using their ABI size and then stored into the RAW_BUFFER
-   using their raw size.
-
-   The alternative to adding this function would be to add an ABI
-   macro - REGISTER_STACK_SIZE(). */
-
-static void
-mips_get_saved_register (char *raw_buffer,
-                        int *optimizedp,
-                        CORE_ADDR *addrp,
-                        struct frame_info *frame,
-                        int regnum,
-                        enum lval_type *lvalp)
-{
-  CORE_ADDR addrx;
-  enum lval_type lvalx;
-  int optimizedx;
-  int realnumx;
-
-  /* Always a pseudo.  */
-  gdb_assert (regnum >= NUM_REGS);
-
-  /* Make certain that all needed parameters are present.  */
-  if (addrp == NULL)
-    addrp = &addrx;
-  if (lvalp == NULL)
-    lvalp = &lvalx;
-  if (optimizedp == NULL)
-    optimizedp = &optimizedx;
-
-  if ((regnum % NUM_REGS) == SP_REGNUM)
-    /* The SP_REGNUM is special, its value is stored in saved_regs.
-       In fact, it is so special that it can even only be fetched
-       using a raw register number!  Once this code as been converted
-       to frame-unwind the problem goes away.  */
-    frame_register_unwind (deprecated_get_next_frame_hack (frame),
-                          regnum % NUM_REGS, optimizedp, lvalp, addrp,
-                          &realnumx, raw_buffer);
-  else
-    /* Get it from the next frame.  */
-    frame_register_unwind (deprecated_get_next_frame_hack (frame),
-                          regnum, optimizedp, lvalp, addrp,
-                          &realnumx, raw_buffer);
-}
-
-/* Immediately after a function call, return the saved pc.
-   Can't always go through the frames for this because on some machines
-   the new frame is not set up until the new function executes
-   some instructions.  */
-
-static CORE_ADDR
-mips_saved_pc_after_call (struct frame_info *frame)
-{
-  return read_signed_register (RA_REGNUM);
-}
-
-
 /* Convert a dbx stab register number (from `r' declaration) to a GDB
    [1 * NUM_REGS .. 2 * NUM_REGS) REGNUM.  */
 
@@ -5591,7 +4587,7 @@ mips_register_sim_regno (int regnum)
       && REGISTER_NAME (NUM_REGS + regnum)[0] != '\0')
     return regnum;
   else
-    return LEGACY_SIM_REGNO_IGNORE;    
+    return LEGACY_SIM_REGNO_IGNORE;
 }
 
 
@@ -5646,13 +4642,11 @@ global_mips_abi (void)
     if (mips_abi_strings[i] == mips_abi_string)
       return (enum mips_abi) i;
 
-  internal_error (__FILE__, __LINE__,
-                 "unknown ABI string");
+  internal_error (__FILE__, __LINE__, "unknown ABI string");
 }
 
 static struct gdbarch *
-mips_gdbarch_init (struct gdbarch_info info,
-                  struct gdbarch_list *arches)
+mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
@@ -5670,8 +4664,7 @@ mips_gdbarch_init (struct gdbarch_info info,
     elf_flags = 0;
   if (gdbarch_debug)
     fprintf_unfiltered (gdb_stdlog,
-                       "mips_gdbarch_init: elf_flags = 0x%08x\n",
-                       elf_flags);
+                       "mips_gdbarch_init: elf_flags = 0x%08x\n", elf_flags);
 
   /* Check ELF_FLAGS to see if it specifies the ABI being used.  */
   switch ((elf_flags & EF_MIPS_ABI))
@@ -5700,7 +4693,7 @@ mips_gdbarch_init (struct gdbarch_info info,
   if (found_abi == MIPS_ABI_UNKNOWN && info.abfd != NULL)
     bfd_map_over_sections (info.abfd, mips_find_abi_section, &found_abi);
 
-  /* If we have no usefu BFD information, use the ABI from the last
+  /* If we have no useful BFD information, use the ABI from the last
      MIPS architecture (if there is one).  */
   if (found_abi == MIPS_ABI_UNKNOWN && info.abfd == NULL && arches != NULL)
     found_abi = gdbarch_tdep (arches->gdbarch)->found_abi;
@@ -5771,6 +4764,7 @@ mips_gdbarch_init (struct gdbarch_info info,
       case bfd_mach_mips3900:
       case bfd_mach_mips4100:
       case bfd_mach_mips4111:
+      case bfd_mach_mips4120:
        fpu_type = MIPS_FPU_NONE;
        break;
       case bfd_mach_mips4650:
@@ -5786,8 +4780,7 @@ mips_gdbarch_init (struct gdbarch_info info,
     fpu_type = MIPS_FPU_DOUBLE;
   if (gdbarch_debug)
     fprintf_unfiltered (gdb_stdlog,
-                       "mips_gdbarch_init: fpu_type = %d\n",
-                       fpu_type);
+                       "mips_gdbarch_init: fpu_type = %d\n", fpu_type);
 
   /* try to find a pre-existing architecture */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
@@ -5830,7 +4823,7 @@ mips_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
 
-  set_gdbarch_elf_make_msymbol_special (gdbarch, 
+  set_gdbarch_elf_make_msymbol_special (gdbarch,
                                        mips_elf_make_msymbol_special);
 
   /* Fill in the OS dependant register numbers and names.  */
@@ -5870,7 +4863,8 @@ mips_gdbarch_init (struct gdbarch_info info,
       }
     /* FIXME: cagney/2003-11-15: For MIPS, hasn't PC_REGNUM been
        replaced by read_pc?  */
-    set_gdbarch_pc_regnum (gdbarch, regnum->pc);
+    set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
+    set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
     set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
     set_gdbarch_num_regs (gdbarch, num_regs);
     set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
@@ -5884,10 +4878,7 @@ mips_gdbarch_init (struct gdbarch_info info,
     case MIPS_ABI_O32:
       set_gdbarch_push_dummy_call (gdbarch, mips_o32_push_dummy_call);
       set_gdbarch_return_value (gdbarch, mips_o32_return_value);
-      tdep->mips_default_saved_regsize = 4;
-      tdep->mips_default_stack_argsize = 4;
-      tdep->mips_fp_register_double = 0;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 4 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
@@ -5896,84 +4887,62 @@ mips_gdbarch_init (struct gdbarch_info info,
       break;
     case MIPS_ABI_O64:
       set_gdbarch_push_dummy_call (gdbarch, mips_o64_push_dummy_call);
-      set_gdbarch_deprecated_store_return_value (gdbarch, mips_o64_store_return_value);
-      set_gdbarch_deprecated_extract_return_value (gdbarch, mips_o64_extract_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
+      set_gdbarch_return_value (gdbarch, mips_o64_return_value);
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 4 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
-      set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
       break;
     case MIPS_ABI_EABI32:
       set_gdbarch_push_dummy_call (gdbarch, mips_eabi_push_dummy_call);
-      set_gdbarch_deprecated_store_return_value (gdbarch, mips_eabi_store_return_value);
-      set_gdbarch_deprecated_extract_return_value (gdbarch, mips_eabi_extract_return_value);
-      tdep->mips_default_saved_regsize = 4;
-      tdep->mips_default_stack_argsize = 4;
-      tdep->mips_fp_register_double = 0;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+      set_gdbarch_return_value (gdbarch, mips_eabi_return_value);
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
-      set_gdbarch_deprecated_reg_struct_has_addr
-       (gdbarch, mips_eabi_reg_struct_has_addr);
-      set_gdbarch_use_struct_convention (gdbarch, 
-                                        mips_eabi_use_struct_convention);
       break;
     case MIPS_ABI_EABI64:
       set_gdbarch_push_dummy_call (gdbarch, mips_eabi_push_dummy_call);
-      set_gdbarch_deprecated_store_return_value (gdbarch, mips_eabi_store_return_value);
-      set_gdbarch_deprecated_extract_return_value (gdbarch, mips_eabi_extract_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+      set_gdbarch_return_value (gdbarch, mips_eabi_return_value);
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 64);
       set_gdbarch_ptr_bit (gdbarch, 64);
       set_gdbarch_long_long_bit (gdbarch, 64);
-      set_gdbarch_deprecated_reg_struct_has_addr
-       (gdbarch, mips_eabi_reg_struct_has_addr);
-      set_gdbarch_use_struct_convention (gdbarch, 
-                                        mips_eabi_use_struct_convention);
       break;
     case MIPS_ABI_N32:
       set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call);
       set_gdbarch_return_value (gdbarch, mips_n32n64_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_long_double_bit (gdbarch, 128);
+      set_gdbarch_long_double_format (gdbarch,
+                                      &floatformat_n32n64_long_double_big);
       break;
     case MIPS_ABI_N64:
       set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call);
       set_gdbarch_return_value (gdbarch, mips_n32n64_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
+      tdep->mips_last_arg_regnum = MIPS_A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 64);
       set_gdbarch_ptr_bit (gdbarch, 64);
       set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_long_double_bit (gdbarch, 128);
+      set_gdbarch_long_double_format (gdbarch,
+                                      &floatformat_n32n64_long_double_big);
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     "unknown ABI in switch");
+      internal_error (__FILE__, __LINE__, "unknown ABI in switch");
     }
 
   /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE
@@ -5998,64 +4967,51 @@ mips_gdbarch_init (struct gdbarch_info info,
      as 32-bit programs by default.  */
 
   set_gdbarch_read_pc (gdbarch, mips_read_pc);
-  set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
-  set_gdbarch_deprecated_target_read_fp (gdbarch, mips_read_sp); /* Draft FRAME base.  */
+  set_gdbarch_write_pc (gdbarch, mips_write_pc);
   set_gdbarch_read_sp (gdbarch, mips_read_sp);
 
   /* Add/remove bits from an address.  The MIPS needs be careful to
      ensure that all 32 bit addresses are sign extended to 64 bits.  */
   set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove);
 
-  /* There's a mess in stack frame creation.  See comments in
-     blockframe.c near reference to DEPRECATED_INIT_FRAME_PC_FIRST.  */
-  set_gdbarch_deprecated_init_frame_pc_first (gdbarch, mips_init_frame_pc_first);
+  /* Unwind the frame.  */
+  set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc);
+  set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id);
 
   /* Map debug register numbers onto internal register numbers.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
-  set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum);
-  set_gdbarch_dwarf_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum);
-  set_gdbarch_dwarf2_reg_to_regnum (gdbarch, mips_dwarf_dwarf2_ecoff_reg_to_regnum);
+  set_gdbarch_ecoff_reg_to_regnum (gdbarch,
+                                  mips_dwarf_dwarf2_ecoff_reg_to_regnum);
+  set_gdbarch_dwarf_reg_to_regnum (gdbarch,
+                                  mips_dwarf_dwarf2_ecoff_reg_to_regnum);
+  set_gdbarch_dwarf2_reg_to_regnum (gdbarch,
+                                   mips_dwarf_dwarf2_ecoff_reg_to_regnum);
   set_gdbarch_register_sim_regno (gdbarch, mips_register_sim_regno);
 
-  /* Initialize a frame */
-  set_gdbarch_deprecated_frame_init_saved_regs (gdbarch, mips_find_saved_regs);
-  set_gdbarch_deprecated_init_extra_frame_info (gdbarch, mips_init_extra_frame_info);
-
   /* MIPS version of CALL_DUMMY */
 
   /* NOTE: cagney/2003-08-05: Eventually call dummy location will be
      replaced by a command, and all targets will default to on stack
      (regardless of the stack's execute status).  */
   set_gdbarch_call_dummy_location (gdbarch, AT_SYMBOL);
-  set_gdbarch_deprecated_pop_frame (gdbarch, mips_pop_frame);
   set_gdbarch_frame_align (gdbarch, mips_frame_align);
-  set_gdbarch_deprecated_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
-
-  set_gdbarch_deprecated_frame_chain (gdbarch, mips_frame_chain);
-  set_gdbarch_frameless_function_invocation (gdbarch, 
-                                            generic_frameless_function_invocation_not);
-  set_gdbarch_deprecated_frame_saved_pc (gdbarch, mips_frame_saved_pc);
-  set_gdbarch_frame_args_skip (gdbarch, 0);
 
-  set_gdbarch_deprecated_get_saved_register (gdbarch, mips_get_saved_register);
+  set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p);
+  set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
+  set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
-  set_gdbarch_decr_pc_after_break (gdbarch, 0);
 
   set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
-  set_gdbarch_deprecated_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
 
   set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
   set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
   set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
 
-  set_gdbarch_function_start_offset (gdbarch, 0);
-
   set_gdbarch_register_type (gdbarch, mips_register_type);
 
   set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
-  set_gdbarch_pc_in_sigtramp (gdbarch, mips_pc_in_sigtramp);
 
   set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
 
@@ -6067,20 +5023,26 @@ mips_gdbarch_init (struct gdbarch_info info,
      is sitting on?  */
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
+  set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_trampoline_code);
+
+  set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_stub);
-
-  set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub);
-  set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
+  /* Unwind the frame.  */
+  frame_unwind_append_sniffer (gdbarch, mips_stub_frame_sniffer);
+  frame_unwind_append_sniffer (gdbarch, mips_insn16_frame_sniffer);
+  frame_unwind_append_sniffer (gdbarch, mips_insn32_frame_sniffer);
+  frame_base_append_sniffer (gdbarch, mips_stub_frame_base_sniffer);
+  frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer);
+  frame_base_append_sniffer (gdbarch, mips_insn32_frame_base_sniffer);
 
   return gdbarch;
 }
 
 static void
-mips_abi_update (char *ignore_args, int from_tty, 
-                struct cmd_list_element *c)
+mips_abi_update (char *ignore_args, int from_tty, struct cmd_list_element *c)
 {
   struct gdbarch_info info;
 
@@ -6096,8 +5058,8 @@ static void
 show_mips_abi (char *ignore_args, int from_tty)
 {
   if (gdbarch_bfd_arch_info (current_gdbarch)->arch != bfd_arch_mips)
-    printf_filtered (
-      "The MIPS ABI is unknown because the current architecture is not MIPS.\n");
+    printf_filtered
+      ("The MIPS ABI is unknown because the current architecture is not MIPS.\n");
   else
     {
       enum mips_abi global_abi = global_mips_abi ();
@@ -6105,19 +5067,19 @@ show_mips_abi (char *ignore_args, int from_tty)
       const char *actual_abi_str = mips_abi_strings[actual_abi];
 
       if (global_abi == MIPS_ABI_UNKNOWN)
-       printf_filtered ("The MIPS ABI is set automatically (currently \"%s\").\n",
-                        actual_abi_str);
+       printf_filtered
+         ("The MIPS ABI is set automatically (currently \"%s\").\n",
+          actual_abi_str);
       else if (global_abi == actual_abi)
-       printf_filtered (
-         "The MIPS ABI is assumed to be \"%s\" (due to user setting).\n",
-         actual_abi_str);
+       printf_filtered
+         ("The MIPS ABI is assumed to be \"%s\" (due to user setting).\n",
+          actual_abi_str);
       else
        {
          /* Probably shouldn't happen...  */
-         printf_filtered (
-           "The (auto detected) MIPS ABI \"%s\" is in use even though the user setting was \"%s\".\n",
-           actual_abi_str,
-           mips_abi_strings[global_abi]);
+         printf_filtered
+           ("The (auto detected) MIPS ABI \"%s\" is in use even though the user setting was \"%s\".\n",
+            actual_abi_str, mips_abi_strings[global_abi]);
        }
     }
 }
@@ -6162,16 +5124,12 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                          ef_mips_arch);
       fprintf_unfiltered (file,
                          "mips_dump_tdep: tdep->mips_abi = %d (%s)\n",
-                         tdep->mips_abi,
-                         mips_abi_strings[tdep->mips_abi]);
+                         tdep->mips_abi, mips_abi_strings[tdep->mips_abi]);
       fprintf_unfiltered (file,
                          "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
                          mips_mask_address_p (tdep),
                          tdep->default_mask_address_p);
     }
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
-                     FP_REGISTER_DOUBLE);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: MIPS_DEFAULT_FPU_TYPE = %d (%s)\n",
                      MIPS_DEFAULT_FPU_TYPE,
@@ -6179,9 +5137,7 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                       : MIPS_DEFAULT_FPU_TYPE == MIPS_FPU_SINGLE ? "single"
                       : MIPS_DEFAULT_FPU_TYPE == MIPS_FPU_DOUBLE ? "double"
                       : "???"));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_EABI = %d\n",
-                     MIPS_EABI);
+  fprintf_unfiltered (file, "mips_dump_tdep: MIPS_EABI = %d\n", MIPS_EABI);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: MIPS_FPU_TYPE = %d (%s)\n",
                      MIPS_FPU_TYPE,
@@ -6189,219 +5145,12 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                       : MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? "single"
                       : MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? "double"
                       : "???"));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
-                     FP_REGISTER_DOUBLE);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: mips_stack_argsize() = %d\n",
-                     mips_stack_argsize (tdep));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: A0_REGNUM = %d\n",
-                     A0_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: ADDR_BITS_REMOVE # %s\n",
-                     XSTRING (ADDR_BITS_REMOVE(ADDR)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: ATTACH_DETACH # %s\n",
-                     XSTRING (ATTACH_DETACH));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: DWARF_REG_TO_REGNUM # %s\n",
-                     XSTRING (DWARF_REG_TO_REGNUM (REGNUM)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: ECOFF_REG_TO_REGNUM # %s\n",
-                     XSTRING (ECOFF_REG_TO_REGNUM (REGNUM)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: FIRST_EMBED_REGNUM = %d\n",
-                     FIRST_EMBED_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
-                     XSTRING (IGNORE_HELPER_CALL (PC)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: IN_SOLIB_CALL_TRAMPOLINE # %s\n",
-                     XSTRING (IN_SOLIB_CALL_TRAMPOLINE (PC, NAME)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: IN_SOLIB_RETURN_TRAMPOLINE # %s\n",
-                     XSTRING (IN_SOLIB_RETURN_TRAMPOLINE (PC, NAME)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: LAST_EMBED_REGNUM = %d\n",
-                     LAST_EMBED_REGNUM);
-#ifdef MACHINE_CPROC_FP_OFFSET
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MACHINE_CPROC_FP_OFFSET = %d\n",
-                     MACHINE_CPROC_FP_OFFSET);
-#endif
-#ifdef MACHINE_CPROC_PC_OFFSET
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MACHINE_CPROC_PC_OFFSET = %d\n",
-                     MACHINE_CPROC_PC_OFFSET);
-#endif
-#ifdef MACHINE_CPROC_SP_OFFSET
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MACHINE_CPROC_SP_OFFSET = %d\n",
-                     MACHINE_CPROC_SP_OFFSET);
-#endif
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS16_INSTLEN = %d\n",
-                     MIPS16_INSTLEN);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_DEFAULT_ABI = FIXME!\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_EFI_SYMBOL_NAME = multi-arch!!\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_INSTLEN = %d\n",
-                     MIPS_INSTLEN);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_LAST_ARG_REGNUM = %d (%d regs)\n",
-                     MIPS_LAST_ARG_REGNUM,
-                     MIPS_LAST_ARG_REGNUM - A0_REGNUM + 1);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: MIPS_NUMREGS = %d\n",
-                     MIPS_NUMREGS);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: mips_saved_regsize() = %d\n",
-                     mips_saved_regsize (tdep));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PRID_REGNUM = %d\n",
-                     PRID_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_DESC_IS_DUMMY = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_FRAME_ADJUST = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_FRAME_OFFSET = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_FRAME_REG = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_FREG_MASK = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_FREG_OFFSET = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_HIGH_ADDR = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_LOW_ADDR = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_PC_REG = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_REG_MASK = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_REG_OFFSET = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PROC_SYMBOL = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PS_REGNUM = %d\n",
-                     PS_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: RA_REGNUM = %d\n",
-                     RA_REGNUM);
-#ifdef SAVED_BYTES
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SAVED_BYTES = %d\n",
-                     SAVED_BYTES);
-#endif
-#ifdef SAVED_FP
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SAVED_FP = %d\n",
-                     SAVED_FP);
-#endif
-#ifdef SAVED_PC
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SAVED_PC = %d\n",
-                     SAVED_PC);
-#endif
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SETUP_ARBITRARY_FRAME # %s\n",
-                     XSTRING (SETUP_ARBITRARY_FRAME (NUMARGS, ARGS)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SET_PROC_DESC_IS_DUMMY = function?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SIGFRAME_BASE = %d\n",
-                     SIGFRAME_BASE);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SIGFRAME_FPREGSAVE_OFF = %d\n",
-                     SIGFRAME_FPREGSAVE_OFF);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SIGFRAME_PC_OFF = %d\n",
-                     SIGFRAME_PC_OFF);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SIGFRAME_REGSAVE_OFF = %d\n",
-                     SIGFRAME_REGSAVE_OFF);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SKIP_TRAMPOLINE_CODE # %s\n",
-                     XSTRING (SKIP_TRAMPOLINE_CODE (PC)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SOFTWARE_SINGLE_STEP # %s\n",
-                     XSTRING (SOFTWARE_SINGLE_STEP (SIG, BP_P)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P () = %d\n",
-                     SOFTWARE_SINGLE_STEP_P ());
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: STAB_REG_TO_REGNUM # %s\n",
-                     XSTRING (STAB_REG_TO_REGNUM (REGNUM)));
-#ifdef STACK_END_ADDR
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: STACK_END_ADDR = %d\n",
-                     STACK_END_ADDR);
-#endif
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: STEP_SKIPS_DELAY # %s\n",
-                     XSTRING (STEP_SKIPS_DELAY (PC)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: STEP_SKIPS_DELAY_P = %d\n",
-                     STEP_SKIPS_DELAY_P);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
-                     XSTRING (STOPPED_BY_WATCHPOINT (WS)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: T9_REGNUM = %d\n",
-                     T9_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TABULAR_REGISTER_OUTPUT = used?\n");
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TARGET_CAN_USE_HARDWARE_WATCHPOINT # %s\n",
-                     XSTRING (TARGET_CAN_USE_HARDWARE_WATCHPOINT (TYPE,CNT,OTHERTYPE)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TARGET_HAS_HARDWARE_WATCHPOINTS # %s\n",
-                     XSTRING (TARGET_HAS_HARDWARE_WATCHPOINTS));
-#ifdef TRACE_CLEAR
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TRACE_CLEAR # %s\n",
-                     XSTRING (TRACE_CLEAR (THREAD, STATE)));
-#endif
-#ifdef TRACE_FLAVOR
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TRACE_FLAVOR = %d\n",
-                     TRACE_FLAVOR);
-#endif
-#ifdef TRACE_FLAVOR_SIZE
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TRACE_FLAVOR_SIZE = %d\n",
-                     TRACE_FLAVOR_SIZE);
-#endif
-#ifdef TRACE_SET
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: TRACE_SET # %s\n",
-                     XSTRING (TRACE_SET (X,STATE)));
-#endif
-#ifdef UNUSED_REGNUM
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: UNUSED_REGNUM = %d\n",
-                     UNUSED_REGNUM);
-#endif
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: V0_REGNUM = %d\n",
-                     V0_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: VM_MIN_ADDRESS = %ld\n",
-                     (long) VM_MIN_ADDRESS);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: ZERO_REGNUM = %d\n",
-                     ZERO_REGNUM);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: _PROC_MAGIC_ = %d\n",
-                     _PROC_MAGIC_);
+                     mips_stack_argsize (current_gdbarch));
 }
 
-extern initialize_file_ftype _initialize_mips_tdep; /* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_mips_tdep;    /* -Wmissing-prototypes */
 
 void
 _initialize_mips_tdep (void)
@@ -6409,13 +5158,15 @@ _initialize_mips_tdep (void)
   static struct cmd_list_element *mipsfpulist = NULL;
   struct cmd_list_element *c;
 
-  mips_abi_string = mips_abi_strings [MIPS_ABI_UNKNOWN];
+  mips_abi_string = mips_abi_strings[MIPS_ABI_UNKNOWN];
   if (MIPS_ABI_LAST + 1
       != sizeof (mips_abi_strings) / sizeof (mips_abi_strings[0]))
     internal_error (__FILE__, __LINE__, "mips_abi_strings out of sync");
 
   gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
 
+  mips_pdr_data = register_objfile_data ();
+
   /* Add root prefix command for all "set mips"/"show mips" commands */
   add_prefix_cmd ("mips", no_class, set_mips_command,
                  "Various MIPS specific commands.",
@@ -6426,33 +5177,31 @@ _initialize_mips_tdep (void)
                  &showmipscmdlist, "show mips ", 0, &showlist);
 
   /* Allow the user to override the saved register size. */
-  add_show_from_set (add_set_enum_cmd ("saved-gpreg-size",
-                                      class_obscure,
-                                      size_enums,
-                                      &mips_saved_regsize_string, "\
-Set size of general purpose registers saved on the stack.\n\
+  add_setshow_enum_cmd ("saved-gpreg-size", class_obscure,
+                       size_enums, &mips_abi_regsize_string, "\
+Set size of general purpose registers saved on the stack.\n", "\
+Show size of general purpose registers saved on the stack.\n", "\
 This option can be set to one of:\n\
   32    - Force GDB to treat saved GP registers as 32-bit\n\
   64    - Force GDB to treat saved GP registers as 64-bit\n\
   auto  - Allow GDB to use the target's default setting or autodetect the\n\
           saved GP register size from information contained in the executable.\n\
-          (default: auto)",
-                                      &setmipscmdlist),
-                    &showmipscmdlist);
+          (default: auto)", "\
+Size of general purpose registers saved on the stack is %s.\n",
+                       NULL, NULL, &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to override the argument stack size. */
-  add_show_from_set (add_set_enum_cmd ("stack-arg-size",
-                                      class_obscure,
-                                      size_enums,
-                                      &mips_stack_argsize_string, "\
-Set the amount of stack space reserved for each argument.\n\
+  add_setshow_enum_cmd ("stack-arg-size", class_obscure,
+                      size_enums, &mips_stack_argsize_string, "\
+Set the amount of stack space reserved for each argument.\n", "\
+Show the amount of stack space reserved for each argument.\n", "\
 This option can be set to one of:\n\
   32    - Force GDB to allocate 32-bit chunks per argument\n\
   64    - Force GDB to allocate 64-bit chunks per argument\n\
   auto  - Allow GDB to determine the correct setting from the current\n\
-          target and executable (default)",
-                                      &setmipscmdlist),
-                    &showmipscmdlist);
+          target and executable (default)", "\
+The amount of stack space reserved for each argument is %s.\n",
+                       NULL, NULL, &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to override the ABI. */
   c = add_set_enum_cmd
@@ -6461,15 +5210,10 @@ This option can be set to one of:\n\
      "This option can be set to one of:\n"
      "  auto  - the default ABI associated with the current binary\n"
      "  o32\n"
-     "  o64\n"
-     "  n32\n"
-     "  n64\n"
-     "  eabi32\n"
-     "  eabi64",
-     &setmipscmdlist);
+     "  o64\n" "  n32\n" "  n64\n" "  eabi32\n" "  eabi64", &setmipscmdlist);
   set_cmd_sfunc (c, mips_abi_update);
   add_cmd ("abi", class_obscure, show_mips_abi,
-           "Show ABI in use by MIPS target", &showmipscmdlist);
+          "Show ABI in use by MIPS target", &showmipscmdlist);
 
   /* Let the user turn off floating point and set the fence post for
      heuristic_proc_start.  */
@@ -6487,8 +5231,7 @@ This option can be set to one of:\n\
   add_alias_cmd ("yes", "double", class_support, 1, &mipsfpulist);
   add_alias_cmd ("1", "double", class_support, 1, &mipsfpulist);
   add_cmd ("none", class_support, set_mipsfpu_none_command,
-          "Select no MIPS floating-point coprocessor.",
-          &mipsfpulist);
+          "Select no MIPS floating-point coprocessor.", &mipsfpulist);
   add_alias_cmd ("off", "none", class_support, 1, &mipsfpulist);
   add_alias_cmd ("no", "none", class_support, 1, &mipsfpulist);
   add_alias_cmd ("0", "none", class_support, 1, &mipsfpulist);
@@ -6502,47 +5245,46 @@ This option can be set to one of:\n\
   /* We really would like to have both "0" and "unlimited" work, but
      command.c doesn't deal with that.  So make it a var_zinteger
      because the user can always use "999999" or some such for unlimited.  */
-  c = add_set_cmd ("heuristic-fence-post", class_support, var_zinteger,
-                  (char *) &heuristic_fence_post,
-                  "\
-Set the distance searched for the start of a function.\n\
+  add_setshow_zinteger_cmd ("heuristic-fence-post", class_support,
+                           &heuristic_fence_post, "\
+Set the distance searched for the start of a function.\n", "\
+Show the distance searched for the start of a function.\n", "\
 If you are debugging a stripped executable, GDB needs to search through the\n\
 program for the start of a function.  This command sets the distance of the\n\
-search.  The only need to set it is when debugging a stripped executable.",
-                  &setlist);
-  /* We need to throw away the frame cache when we set this, since it
-     might change our ability to get backtraces.  */
-  set_cmd_sfunc (c, reinit_frame_cache_sfunc);
-  add_show_from_set (c, &showlist);
+search.  The only need to set it is when debugging a stripped executable.", "\
+The distance searched for the start of a function is %s.\n",
+                           reinit_frame_cache_sfunc, NULL,
+                           &setlist, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
      addresses should be zeroed.  */
   add_setshow_auto_boolean_cmd ("mask-address", no_class, &mask_address_var, "\
-Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Set zeroing of upper 32 bits of 64-bit addresses.", "\
+Show zeroing of upper 32 bits of 64-bit addresses.", "\
 Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\
 allow GDB to determine the correct value.\n", "\
-Show zeroing of upper 32 bits of 64-bit addresses.",
-                               NULL, show_mask_address,
-                               &setmipscmdlist, &showmipscmdlist);
+Zerroing of upper 32 bits of 64-bit address is %s.",
+                               NULL, show_mask_address, &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to control the size of 32 bit registers within the
      raw remote packet.  */
-  add_setshow_cmd ("remote-mips64-transfers-32bit-regs", class_obscure,
-                  var_boolean, &mips64_transfers_32bit_regs_p, "\
-Set compatibility with 64-bit MIPS targets that transfer 32-bit quantities.\n\
-Use \"on\" to enable backward compatibility with older MIPS 64 GDB+target\n\
-that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
-64 bits for others.  Use \"off\" to disable compatibility mode",  "\
-Show compatibility with 64-bit MIPS targets that transfer 32-bit quantities.\n\
+  add_setshow_boolean_cmd ("remote-mips64-transfers-32bit-regs", class_obscure,
+                          &mips64_transfers_32bit_regs_p, "\
+Set compatibility with 64-bit MIPS target that transfers 32-bit quantities.", "\
+Show compatibility with 64-bit MIPS target that transfers 32-bit quantities.", "\
 Use \"on\" to enable backward compatibility with older MIPS 64 GDB+target\n\
 that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
-64 bits for others.  Use \"off\" to disable compatibility mode",
-                  set_mips64_transfers_32bit_regs, NULL,
                 &setlist, &showlist);
+64 bits for others.  Use \"off\" to disable compatibility mode", "\
+Compatibility with 64-bit MIPS target that transfers 32-bit quantities is %s.",
set_mips64_transfers_32bit_regs, NULL, &setlist, &showlist);
 
   /* Debug this files internals. */
-  add_show_from_set (add_set_cmd ("mips", class_maintenance, var_zinteger,
-                                 &mips_debug, "Set mips debugging.\n\
-When non-zero, mips specific debugging is enabled.", &setdebuglist),
-                    &showdebuglist);
+  add_setshow_zinteger_cmd ("mips", class_maintenance,
+                           &mips_debug, "\
+Set mips debugging.\n", "\
+Show mips debugging.\n", "\
+When non-zero, mips specific debugging is enabled.\n", "\
+Mips debugging is currently %s.\n",
+                           NULL, NULL,
+                           &setdebuglist, &showdebuglist);
 }
This page took 0.106336 seconds and 4 git commands to generate.