* config/mips/linux.mh (TDEP_XML): New.
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 313b8b1e590cc253c03888c66dd37448f3088815..288d9747fab5bc4d1ce20fb8e344527f35aaad87 100644 (file)
@@ -1,8 +1,8 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software
-   Foundation, Inc.
+   Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+   Free Software Foundation, Inc.
 
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
    and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
@@ -21,8 +21,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
 
 #include "defs.h"
 #include "gdb_string.h"
 #include "trad-frame.h"
 #include "infcall.h"
 #include "floatformat.h"
+#include "remote.h"
+#include "target-descriptions.h"
+#include "dwarf2-frame.h"
+#include "user-regs.h"
 
 static const struct objfile_data *mips_pdr_data;
 
 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)
 
@@ -72,6 +76,11 @@ enum
   MIPS_FPU_DOUBLE_REGSIZE = 8
 };
 
+enum
+{
+  MIPS32_REGSIZE = 4,
+  MIPS64_REGSIZE = 8
+};
 
 static const char *mips_abi_string;
 
@@ -86,25 +95,53 @@ static const char *mips_abi_strings[] = {
   NULL
 };
 
-struct frame_extra_info
+/* The standard register names, and all the valid aliases for them.  */
+struct register_alias
 {
-  mips_extra_func_info_t proc_desc;
-  int num_args;
+  const char *name;
+  int regnum;
 };
 
-/* Various MIPS ISA options (related to stack analysis) can be
-   overridden dynamically.  Establish an enum/array for managing
-   them. */
+/* Aliases for o32 and most other ABIs.  */
+const struct register_alias mips_o32_aliases[] = {
+  { "ta0", 12 },
+  { "ta1", 13 },
+  { "ta2", 14 },
+  { "ta3", 15 }
+};
 
-static const char size_auto[] = "auto";
-static const char size_32[] = "32";
-static const char size_64[] = "64";
+/* Aliases for n32 and n64.  */
+const struct register_alias mips_n32_n64_aliases[] = {
+  { "ta0", 8 },
+  { "ta1", 9 },
+  { "ta2", 10 },
+  { "ta3", 11 }
+};
 
-static const char *size_enums[] = {
-  size_auto,
-  size_32,
-  size_64,
-  0
+/* Aliases for ABI-independent registers.  */
+const struct register_alias mips_register_aliases[] = {
+  /* The architecture manuals specify these ABI-independent names for
+     the GPRs.  */
+#define R(n) { "r" #n, n }
+  R(0), R(1), R(2), R(3), R(4), R(5), R(6), R(7),
+  R(8), R(9), R(10), R(11), R(12), R(13), R(14), R(15),
+  R(16), R(17), R(18), R(19), R(20), R(21), R(22), R(23),
+  R(24), R(25), R(26), R(27), R(28), R(29), R(30), R(31),
+#undef R
+
+  /* k0 and k1 are sometimes called these instead (for "kernel
+     temp").  */
+  { "kt0", 26 },
+  { "kt1", 27 },
+
+  /* This is the traditional GDB name for the CP0 status register.  */
+  { "sr", MIPS_PS_REGNUM },
+
+  /* This is the traditional GDB name for the CP0 BadVAddr register.  */
+  { "bad", MIPS_EMBED_BADVADDR_REGNUM },
+
+  /* This is the traditional GDB name for the FCSR.  */
+  { "fsr", MIPS_EMBED_FP0_REGNUM + 32 }
 };
 
 /* Some MIPS boards don't support floating point while others only
@@ -125,6 +162,11 @@ static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
 
 static int mips_debug = 0;
 
+/* Properties (for struct target_desc) describing the g/G packet
+   layout.  */
+#define PROPERTY_GP32 "internal: transfers-32bit-registers"
+#define PROPERTY_GP64 "internal: transfers-64bit-registers"
+
 /* MIPS specific per-architecture information */
 struct gdbarch_tdep
 {
@@ -147,11 +189,18 @@ struct gdbarch_tdep
   const struct mips_regnum *regnum;
   /* Register names table for the current register set.  */
   const char **mips_processor_reg_names;
+
+  /* The size of register data available from the target, if known.
+     This doesn't quite obsolete the manual
+     mips64_transfers_32bit_regs_p, since that is documented to force
+     left alignment even for big endian (very strange).  */
+  int register_size_valid_p;
+  int register_size;
 };
 
 static int
 n32n64_floatformat_always_valid (const struct floatformat *fmt,
-                                 const char *from)
+                                 const void *from)
 {
   return 1;
 }
@@ -171,10 +220,16 @@ 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",
+  "floatformat_n32n64_long_double_big",
   n32n64_floatformat_always_valid
 };
 
+static const struct floatformat *floatformats_n32n64_long[BFD_ENDIAN_UNKNOWN] =
+{
+  &floatformat_n32n64_long_double_big,
+  &floatformat_n32n64_long_double_big
+};
+
 const struct mips_regnum *
 mips_regnum (struct gdbarch *gdbarch)
 {
@@ -205,16 +260,10 @@ 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)
 {
-  return ((addr) & ~1);
+  return ((addr) & ~(CORE_ADDR) 1);
 }
 
 /* Return the contents of register REGNUM as a signed integer.  */
@@ -222,10 +271,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
@@ -258,44 +306,44 @@ mips_abi (struct gdbarch *gdbarch)
 int
 mips_isa_regsize (struct gdbarch *gdbarch)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  /* If we know how big the registers are, use that size.  */
+  if (tdep->register_size_valid_p)
+    return tdep->register_size;
+
+  /* Fall back to the previous behavior.  */
   return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
          / gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
 }
 
 /* Return the currently configured (or set) saved register size. */
 
-static const char *mips_abi_regsize_string = size_auto;
-
-static unsigned int
+unsigned int
 mips_abi_regsize (struct gdbarch *gdbarch)
 {
-  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_abi_regsize_string == size_32) */
-    return 4;
+  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"));
+    }
 }
 
 /* Functions for setting and testing a bit in a minimal symbol that
    marks it as 16-bit function.  The MSB of the minimal symbol's
    "info" field is used for this purpose.
 
-   ELF_MAKE_MSYMBOL_SPECIAL tests whether an ELF symbol is "special",
+   gdbarch_elf_make_msymbol_special tests whether an ELF symbol is "special",
    i.e. refers to a 16-bit function, and sets a "special" bit in a
    minimal symbol to mark it as a 16-bit function
 
@@ -325,11 +373,11 @@ 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, gdb_byte *in,
+                   const gdb_byte *out, int buf_offset)
 {
   int reg_offset = 0;
-  gdb_assert (reg_num >= NUM_REGS);
+  gdb_assert (reg_num >= gdbarch_num_regs (current_gdbarch));
   /* Need to transfer the left or right part of the register, based on
      the targets byte order.  */
   switch (endian)
@@ -344,7 +392,7 @@ mips_xfer_register (struct regcache *regcache, int reg_num, int length,
       reg_offset = 0;
       break;
     default:
-      internal_error (__FILE__, __LINE__, "bad switch");
+      internal_error (__FILE__, __LINE__, _("bad switch"));
     }
   if (mips_debug)
     fprintf_unfiltered (gdb_stderr,
@@ -393,47 +441,21 @@ 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;
 }
 
-/* The amount of space reserved on the stack for registers. This is
-   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 *gdbarch)
-{
-  if (mips_stack_argsize_string == size_auto)
-    return mips_abi_regsize (gdbarch);
-  else if (mips_stack_argsize_string == size_64)
-    return 8;
-  else                         /* if (mips_stack_argsize_string == size_32) */
-    return 4;
-}
-
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
-struct mips_frame_cache;
-static mips_extra_func_info_t heuristic_proc_desc (CORE_ADDR, CORE_ADDR,
-                                                  struct frame_info *,
-                                                  struct mips_frame_cache *);
-static mips_extra_func_info_t non_heuristic_proc_desc (CORE_ADDR pc,
-                                                      CORE_ADDR *addrptr);
-
 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 CORE_ADDR after_prologue (CORE_ADDR pc);
-
 static struct type *mips_float_register_type (void);
 static struct type *mips_double_register_type (void);
 
@@ -444,7 +466,7 @@ static struct cmd_list_element *showmipscmdlist = NULL;
 
 /* Integer registers 0 thru 31 are handled explicitly by
    mips_register_name().  Processor specific registers 32 and above
-   are listed in the followign tables.  */
+   are listed in the following tables.  */
 
 enum
 { NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
@@ -521,10 +543,10 @@ mips_register_name (int regno)
 
   enum mips_abi abi = mips_abi (current_gdbarch);
 
-  /* Map [NUM_REGS .. 2*NUM_REGS) onto the raw registers, but then
-     don't make the raw register names visible.  */
-  int rawnum = regno % NUM_REGS;
-  if (regno < NUM_REGS)
+  /* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers, 
+     but then don't make the raw register names visible.  */
+  int rawnum = regno % gdbarch_num_regs (current_gdbarch);
+  if (regno < gdbarch_num_regs (current_gdbarch))
     return "";
 
   /* The MIPS integer registers are always mapped from 0 to 31.  The
@@ -537,14 +559,16 @@ mips_register_name (int regno)
       else
        return mips_gpr_names[rawnum];
     }
-  else if (32 <= rawnum && rawnum < NUM_REGS)
+  else if (tdesc_has_registers (gdbarch_target_desc (current_gdbarch)))
+    return tdesc_register_name (rawnum);
+  else if (32 <= rawnum && rawnum < gdbarch_num_regs (current_gdbarch))
     {
       gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
       return tdep->mips_processor_reg_names[rawnum - 32];
     }
   else
     internal_error (__FILE__, __LINE__,
-                   "mips_register_name: bad register number %d", rawnum);
+                   _("mips_register_name: bad register number %d"), rawnum);
 }
 
 /* Return the groups that a MIPS register can be categorised into.  */
@@ -556,16 +580,17 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   int vector_p;
   int float_p;
   int raw_p;
-  int rawnum = regnum % NUM_REGS;
-  int pseudo = regnum / NUM_REGS;
+  int rawnum = regnum % gdbarch_num_regs (current_gdbarch);
+  int pseudo = regnum / gdbarch_num_regs (current_gdbarch);
   if (reggroup == all_reggroup)
     return pseudo;
   vector_p = TYPE_VECTOR (register_type (gdbarch, regnum));
   float_p = TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT;
   /* 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')
+  raw_p = rawnum < gdbarch_num_regs (current_gdbarch);
+  if (gdbarch_register_name (current_gdbarch, regnum) == NULL
+      || gdbarch_register_name (current_gdbarch, regnum)[0] == '\0')
     return 0;
   if (reggroup == float_reggroup)
     return float_p && pseudo;
@@ -584,51 +609,82 @@ mips_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
   return 0;
 }
 
+/* Return the groups that a MIPS register can be categorised into.
+   This version is only used if we have a target description which
+   describes real registers (and their groups).  */
+
+static int
+mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+                               struct reggroup *reggroup)
+{
+  int rawnum = regnum % gdbarch_num_regs (gdbarch);
+  int pseudo = regnum / gdbarch_num_regs (gdbarch);
+  int ret;
+
+  /* Only save, restore, and display the pseudo registers.  Need to
+     make certain that any code extracting register values from a
+     saved register cache also uses pseudo registers.
+
+     Note: saving and restoring the pseudo registers is slightly
+     strange; if we have 64 bits, we should save and restore all
+     64 bits.  But this is hard and has little benefit.  */
+  if (!pseudo)
+    return 0;
+
+  ret = tdesc_register_in_reggroup_p (gdbarch, rawnum, reggroup);
+  if (ret != -1)
+    return ret;
+
+  return mips_register_reggroup_p (gdbarch, regnum, reggroup);
+}
+
 /* Map the symbol table registers which live in the range [1 *
-   NUM_REGS .. 2 * NUM_REGS) back onto the corresponding raw
+   gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
    registers.  Take care of alignment and size problems.  */
 
 static void
 mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
-                          int cookednum, void *buf)
+                          int cookednum, gdb_byte *buf)
 {
-  int rawnum = cookednum % NUM_REGS;
-  gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
+  int rawnum = cookednum % gdbarch_num_regs (current_gdbarch);
+  gdb_assert (cookednum >= gdbarch_num_regs (current_gdbarch)
+             && cookednum < 2 * gdbarch_num_regs (current_gdbarch));
   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))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
-         || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+         || gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE)
        regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
       else
        regcache_raw_read_part (regcache, rawnum, 4, 4, buf);
     }
   else
-    internal_error (__FILE__, __LINE__, "bad register size");
+    internal_error (__FILE__, __LINE__, _("bad register size"));
 }
 
 static void
 mips_pseudo_register_write (struct gdbarch *gdbarch,
                            struct regcache *regcache, int cookednum,
-                           const void *buf)
+                           const gdb_byte *buf)
 {
-  int rawnum = cookednum % NUM_REGS;
-  gdb_assert (cookednum >= NUM_REGS && cookednum < 2 * NUM_REGS);
+  int rawnum = cookednum % gdbarch_num_regs (current_gdbarch);
+  gdb_assert (cookednum >= gdbarch_num_regs (current_gdbarch)
+             && cookednum < 2 * gdbarch_num_regs (current_gdbarch));
   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))
     {
       if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
-         || TARGET_BYTE_ORDER == BFD_ENDIAN_LITTLE)
+         || gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE)
        regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
       else
        regcache_raw_write_part (regcache, rawnum, 4, 4, buf);
     }
   else
-    internal_error (__FILE__, __LINE__, "bad register size");
+    internal_error (__FILE__, __LINE__, _("bad register size"));
 }
 
 /* Table to translate MIPS16 register field to actual register number.  */
@@ -640,21 +696,6 @@ static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
 
 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
-
 /* 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.  */
@@ -673,7 +714,7 @@ set_mips64_transfers_32bit_regs (char *args, int from_tty,
   if (!gdbarch_update_p (info))
     {
       mips64_transfers_32bit_regs_p = 0;
-      error ("32-bit compatibility mode not supported");
+      error (_("32-bit compatibility mode not supported"));
     }
 }
 
@@ -682,27 +723,29 @@ set_mips64_transfers_32bit_regs (char *args, int from_tty,
 static int
 mips_convert_register_p (int regnum, struct type *type)
 {
-  return (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
+  return (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
          && register_size (current_gdbarch, regnum) == 4
-         && (regnum % NUM_REGS) >= mips_regnum (current_gdbarch)->fp0
-         && (regnum % NUM_REGS) < mips_regnum (current_gdbarch)->fp0 + 32
+         && (regnum % gdbarch_num_regs (current_gdbarch))
+               >= mips_regnum (current_gdbarch)->fp0
+         && (regnum % gdbarch_num_regs (current_gdbarch))
+               < mips_regnum (current_gdbarch)->fp0 + 32
          && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
 }
 
 static void
 mips_register_to_value (struct frame_info *frame, int regnum,
-                       struct type *type, void *to)
+                       struct type *type, gdb_byte *to)
 {
-  get_frame_register (frame, regnum + 0, (char *) to + 4);
-  get_frame_register (frame, regnum + 1, (char *) to + 0);
+  get_frame_register (frame, regnum + 0, to + 4);
+  get_frame_register (frame, regnum + 1, to + 0);
 }
 
 static void
 mips_value_to_register (struct frame_info *frame, int regnum,
-                       struct type *type, const void *from)
+                       struct type *type, const gdb_byte *from)
 {
-  put_frame_register (frame, regnum + 0, (const char *) from + 4);
-  put_frame_register (frame, regnum + 1, (const char *) from + 0);
+  put_frame_register (frame, regnum + 0, from + 4);
+  put_frame_register (frame, regnum + 1, from + 0);
 }
 
 /* Return the GDB type object for the "standard" data type of data in
@@ -711,30 +754,20 @@ mips_value_to_register (struct frame_info *frame, int regnum,
 static struct type *
 mips_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  gdb_assert (regnum >= 0 && regnum < 2 * NUM_REGS);
-  if ((regnum % NUM_REGS) >= mips_regnum (current_gdbarch)->fp0
-      && (regnum % NUM_REGS) < mips_regnum (current_gdbarch)->fp0 + 32)
+  gdb_assert (regnum >= 0 && regnum < 2 * gdbarch_num_regs (current_gdbarch));
+  if ((regnum % gdbarch_num_regs (current_gdbarch))
+       >= mips_regnum (current_gdbarch)->fp0
+      && (regnum % gdbarch_num_regs (current_gdbarch))
+       < mips_regnum (current_gdbarch)->fp0 + 32)
     {
       /* The floating-point registers raw, or cooked, always match
          mips_isa_regsize(), and also map 1:1, byte for byte.  */
-      switch (gdbarch_byte_order (gdbarch))
-       {
-       case BFD_ENDIAN_BIG:
-         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_isa_regsize (gdbarch) == 4)
-           return builtin_type_ieee_single_little;
-         else
-           return builtin_type_ieee_double_little;
-       case BFD_ENDIAN_UNKNOWN:
-       default:
-         internal_error (__FILE__, __LINE__, "bad switch");
-       }
+      if (mips_isa_regsize (gdbarch) == 4)
+       return builtin_type_ieee_single;
+      else
+       return builtin_type_ieee_double;
     }
-  else if (regnum < NUM_REGS)
+  else if (regnum < gdbarch_num_regs (current_gdbarch))
     {
       /* The raw or ISA registers.  These are all sized according to
         the ISA regsize.  */
@@ -747,9 +780,10 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
     {
       /* The cooked or ABI registers.  These are sized according to
         the ABI (with a few complications).  */
-      if (regnum >= (NUM_REGS
+      if (regnum >= (gdbarch_num_regs (current_gdbarch)
                     + mips_regnum (current_gdbarch)->fp_control_status)
-         && regnum <= NUM_REGS + LAST_EMBED_REGNUM)
+         && regnum <= gdbarch_num_regs (current_gdbarch)
+                      + 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;
@@ -768,12 +802,58 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
     }
 }
 
-/* TARGET_READ_SP -- Remove useless bits from the stack pointer.  */
+/* Return the GDB type for the pseudo register REGNUM, which is the
+   ABI-level view.  This function is only called if there is a target
+   description which includes registers, so we know precisely the
+   types of hardware registers.  */
 
-static CORE_ADDR
-mips_read_sp (void)
+static struct type *
+mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 {
-  return read_signed_register (MIPS_SP_REGNUM);
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int rawnum = regnum % num_regs;
+  struct type *rawtype;
+
+  gdb_assert (regnum >= num_regs && regnum < 2 * num_regs);
+
+  /* Absent registers are still absent.  */
+  rawtype = gdbarch_register_type (gdbarch, rawnum);
+  if (TYPE_LENGTH (rawtype) == 0)
+    return rawtype;
+
+  if (rawnum >= MIPS_EMBED_FP0_REGNUM && rawnum < MIPS_EMBED_FP0_REGNUM + 32)
+    /* Present the floating point registers however the hardware did;
+       do not try to convert between FPU layouts.  */
+    return rawtype;
+
+  if (rawnum >= MIPS_EMBED_FP0_REGNUM + 32 && rawnum <= MIPS_LAST_EMBED_REGNUM)
+    {
+      /* The pseudo/cooked view of embedded registers is always
+        32-bit, even if the target transfers 64-bit values for them.
+        New targets relying on XML descriptions should only transfer
+        the necessary 32 bits, but older versions of GDB expected 64,
+        so allow the target to provide 64 bits without interfering
+        with the displayed type.  */
+      return builtin_type_int32;
+    }
+
+  /* Use pointer types for registers if we can.  For n32 we can not,
+     since we do not have a 64-bit pointer type.  */
+  if (mips_abi_regsize (gdbarch) == TYPE_LENGTH (builtin_type_void_data_ptr))
+    {
+      if (rawnum == MIPS_SP_REGNUM || rawnum == MIPS_EMBED_BADVADDR_REGNUM)
+       return builtin_type_void_data_ptr;
+      else if (rawnum == MIPS_EMBED_PC_REGNUM)
+       return builtin_type_void_func_ptr;
+    }
+
+  if (mips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8
+      && rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_EMBED_PC_REGNUM)
+    return builtin_type_int32;
+
+  /* For all other registers, pass through the hardware type.  */
+  return rawtype;
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
@@ -792,15 +872,18 @@ 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;
     }
 }
 
 static void
-show_mask_address (char *cmd, int from_tty, struct cmd_list_element *c)
+show_mask_address (struct ui_file *file, int from_tty,
+                  struct cmd_list_element *c, const char *value)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+
+  deprecated_show_value_hack (file, from_tty, c, value);
   switch (mask_address_var)
     {
     case AUTO_BOOLEAN_TRUE:
@@ -815,15 +898,15 @@ show_mask_address (char *cmd, int from_tty, struct cmd_list_element *c)
         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;
     }
 }
 
 /* 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;
 
@@ -854,7 +937,16 @@ static CORE_ADDR
 mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
   return frame_unwind_register_signed (next_frame,
-                                      NUM_REGS + mips_regnum (gdbarch)->pc);
+                                      gdbarch_num_regs (current_gdbarch)
+                                      + mips_regnum (gdbarch)->pc);
+}
+
+static CORE_ADDR
+mips_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
+{
+  return frame_unwind_register_signed (next_frame,
+                                      gdbarch_num_regs (current_gdbarch)
+                                      + MIPS_SP_REGNUM);
 }
 
 /* Assuming NEXT_FRAME->prev is a dummy, return the frame ID of that
@@ -865,8 +957,11 @@ mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 static struct frame_id
 mips_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  return frame_id_build (frame_unwind_register_signed (next_frame, NUM_REGS + MIPS_SP_REGNUM),
-                        frame_pc_unwind (next_frame));
+  return frame_id_build
+          (frame_unwind_register_signed (next_frame,
+                                         gdbarch_num_regs (current_gdbarch)
+                                         + MIPS_SP_REGNUM),
+                                         frame_pc_unwind (next_frame));
 }
 
 static void
@@ -875,109 +970,24 @@ mips_write_pc (CORE_ADDR pc, ptid_t ptid)
   write_register_pid (mips_regnum (current_gdbarch)->pc, 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;
-  struct symtab_and_line sal;
-  CORE_ADDR func_addr, func_end;
-  CORE_ADDR startaddr = 0;
-
-  /* Pass a NULL next_frame to heuristic_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.  */
-  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.  */
-      struct symtab_and_line val;
-      if (PROC_SYMBOL (proc_desc))
-       {
-         val = find_pc_line (BLOCK_START
-                             (SYMBOL_BLOCK_VALUE (PROC_SYMBOL (proc_desc))),
-                             0);
-         val.pc = val.end ? val.end : pc;
-       }
-      if (!PROC_SYMBOL (proc_desc) || pc < val.pc)
-       {
-         mips_extra_func_info_t found_heuristic =
-           heuristic_proc_desc (PROC_LOW_ADDR (proc_desc), pc, NULL, NULL);
-         if (found_heuristic)
-           proc_desc = found_heuristic;
-       }
-    }
-  else
-    {
-      if (startaddr == 0)
-       startaddr = heuristic_proc_start (pc);
-
-      proc_desc = heuristic_proc_desc (startaddr, pc, NULL, NULL);
-    }
-
-  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) == MIPS_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;
-}
-
 /* 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];
+  gdb_byte 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 = deprecated_read_memory_nobpt (addr, buf, instlen);
-  if (status)
-    memory_error (status, addr);
-  return extract_unsigned_integer (buf, instlen);
-}
-
-static ULONGEST
-mips16_fetch_instruction (CORE_ADDR addr)
-{
-  char buf[MIPS_INSTLEN];
-  int instlen;
-  int status;
-
-  instlen = MIPS16_INSTLEN;
-  addr = unmake_mips16_addr (addr);
-  status = deprecated_read_memory_nobpt (addr, buf, instlen);
+    instlen = MIPS_INSN32_SIZE;
+  status = read_memory_nobpt (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
@@ -1000,21 +1010,14 @@ mips16_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
-   branch prediction */
+/* Determine where to set a single step breakpoint while considering
+   branch prediction */
 static CORE_ADDR
 mips32_next_pc (CORE_ADDR pc)
 {
@@ -1115,14 +1118,14 @@ mips32_next_pc (CORE_ADDR pc)
            unsigned long reg;
            reg = jtype_target (inst) << 2;
            /* Upper four bits get never changed... */
-           pc = reg + ((pc + 4) & 0xf0000000);
+           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff);
          }
          break;
          /* FIXME case JALX : */
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
-           pc = reg + ((pc + 4) & 0xf0000000) + 1;     /* yes, +1 */
+           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + 1;        /* yes, +1 */
            /* Add 1 to indicate 16 bit mode - Invert ISA mode */
          }
          break;                /* The new PC will be alternate mode */
@@ -1234,7 +1237,7 @@ extended_offset (unsigned int extension)
 static unsigned int
 fetch_mips_16 (CORE_ADDR pc)
 {
-  char buf[8];
+  gdb_byte buf[8];
   pc &= 0xfffffffe;            /* clear the low order bit */
   target_read_memory (pc, buf, 2);
   return extract_unsigned_integer (buf, 2);
@@ -1317,7 +1320,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;
@@ -1328,7 +1331,7 @@ unpack_mips16 (CORE_ADDR pc,
 static CORE_ADDR
 add_offset_16 (CORE_ADDR pc, int offset)
 {
-  return ((offset << 2) | ((pc + 2) & (0xf0000000)));
+  return ((offset << 2) | ((pc + 2) & (~(CORE_ADDR) 0x0fffffff)));
 }
 
 static CORE_ADDR
@@ -1463,7 +1466,7 @@ mips16_next_pc (CORE_ADDR pc)
    It works by decoding the current instruction and predicting where a
    branch will go. This isnt hard because all the data is available.
    The MIPS32 and MIPS16 variants are quite different */
-CORE_ADDR
+static CORE_ADDR
 mips_next_pc (CORE_ADDR pc)
 {
   if (pc & 0x01)
@@ -1478,236 +1481,269 @@ struct mips_frame_cache
   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.
 
-static struct mips_frame_cache *
-mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
-{
-  CORE_ADDR startaddr = 0;
-  mips_extra_func_info_t proc_desc;
-  struct mips_frame_cache *cache;
-  struct gdbarch *gdbarch = get_frame_arch (next_frame);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  /* r0 bit means kernel trap */
-  int kernel_trap;
-  /* What registers have been saved?  Bitmasks.  */
-  unsigned long gen_mask, float_mask;
-
-  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);
-
-  /* Get the mdebug proc descriptor.  */
-  proc_desc = non_heuristic_proc_desc (frame_pc_unwind (next_frame),
-                                      &startaddr);
-  /* Must be true.  This is only called when the sniffer detected a
-     proc descriptor.  */
-  gdb_assert (proc_desc != NULL);
+   For simplicity, save the address in both [0 .. gdbarch_num_regs) and
+   [gdbarch_num_regs .. 2*gdbarch_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.  */
 
-  /* Extract the frame's base.  */
-  cache->base = (frame_unwind_register_signed (next_frame, NUM_REGS + PROC_FRAME_REG (proc_desc))
-                + PROC_FRAME_OFFSET (proc_desc) - PROC_FRAME_ADJUST (proc_desc));
+static void
+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 * gdbarch_num_regs (current_gdbarch)].addr
+      = offset;
+      this_cache->saved_regs[regnum
+                            + 1 * gdbarch_num_regs (current_gdbarch)].addr
+      = offset;
+    }
+}
 
-  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);
-  
-  /* Must be true.  The in_prologue case is left for the heuristic
-     unwinder.  This is always used on kernel traps.  */
-  gdb_assert (!in_prologue (frame_pc_unwind (next_frame), PROC_LOW_ADDR (proc_desc))
-             || kernel_trap);
 
-  /* Fill in the offsets for the registers which gen_mask says were
-     saved.  */
-  {
-    CORE_ADDR reg_position = (cache->base + PROC_REG_OFFSET (proc_desc));
-    int ireg;
+/* 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.  */
 
-    for (ireg = MIPS_NUMREGS - 1; gen_mask; --ireg, gen_mask <<= 1)
-      if (gen_mask & 0x80000000)
-       {
-         cache->saved_regs[NUM_REGS + ireg].addr = reg_position;
-         reg_position -= mips_abi_regsize (gdbarch);
-       }
-  }
+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;
 
-  /* 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)))
+  if ((prev_inst & 0xf800) == 0xf000)  /* prev instruction was EXTEND? */
     {
-      ULONGEST inst = mips16_fetch_instruction (PROC_LOW_ADDR (proc_desc));
-      if ((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)
-       /* entry */
-       {
-         int reg;
-         int sreg_count = (inst >> 6) & 3;
-
-         /* Check if the ra register was pushed on the stack.  */
-         CORE_ADDR reg_position = (cache->base
-                                   + PROC_REG_OFFSET (proc_desc));
-         if (inst & 0x20)
-           reg_position -= mips_abi_regsize (gdbarch);
-
-         /* Check if the s0 and s1 registers were pushed on the
-            stack.  */
-         /* NOTE: cagney/2004-02-08: Huh?  This is doing no such
-             check.  */
-         for (reg = 16; reg < sreg_count + 16; reg++)
-           {
-             cache->saved_regs[NUM_REGS + reg].addr = reg_position;
-             reg_position -= mips_abi_regsize (gdbarch);
-           }
-       }
+      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;
 
-  /* Fill in the offsets for the registers which float_mask says were
-     saved.  */
-  {
-    CORE_ADDR reg_position = (cache->base
-                             + PROC_FREG_OFFSET (proc_desc));
-    int ireg;
-    /* 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)
-       {
-         if (mips_abi_regsize (gdbarch) == 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))
-               cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg]
-                 .addr = reg_position - mips_abi_regsize (gdbarch);
-             else
-               cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg]
-                 .addr = reg_position + mips_abi_regsize (gdbarch);
-           }
-         else
-           cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg]
-             .addr = reg_position;
-         reg_position -= mips_abi_regsize (gdbarch);
-       }
-
-    cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
-      = cache->saved_regs[NUM_REGS + RA_REGNUM];
-  }
-
-  /* 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);
+      offset = inst & mask;
+      if (is_signed && (offset & sign_bit))
+       offset = 0 - (max_imm - offset);
+      return offset * scale;
+    }
 }
 
-static void
-mips_mdebug_frame_this_id (struct frame_info *next_frame, void **this_cache,
-                          struct frame_id *this_id)
-{
-  struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame,
-                                                          this_cache);
-  (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
-}
 
-static void
-mips_mdebug_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_mdebug_frame_cache (next_frame,
-                                                          this_cache);
-  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
-                               optimizedp, lvalp, addrp, realnump, valuep);
-}
+/* 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 const struct frame_unwind mips_mdebug_frame_unwind =
+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)
 {
-  NORMAL_FRAME,
-  mips_mdebug_frame_this_id,
-  mips_mdebug_frame_prev_register
-};
+  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;
 
-static const struct frame_unwind *
-mips_mdebug_frame_sniffer (struct frame_info *next_frame)
-{
-  CORE_ADDR pc = frame_pc_unwind (next_frame);
-  CORE_ADDR startaddr = 0;
-  mips_extra_func_info_t proc_desc;
-  int kernel_trap;
+  int extend_bytes = 0;
+  int prev_extend_bytes;
+  CORE_ADDR end_prologue_addr = 0;
 
-  /* Only use the mdebug frame unwinder on mdebug frames where all the
-     registers have been saved.  Leave hard cases such as no mdebug or
-     in prologue for the heuristic unwinders.  */
+  /* 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, gdbarch_num_regs (current_gdbarch)
+                                          + MIPS_SP_REGNUM);
+  else
+    sp = 0;
 
-  proc_desc = non_heuristic_proc_desc (pc, &startaddr);
-  if (proc_desc == NULL)
-    return NULL;
+  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 = PROC_REG_MASK (proc_desc) & 1;
-  if (kernel_trap)
-    return &mips_mdebug_frame_unwind;
-
-  /* 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.  */
-  if (!in_prologue (pc, PROC_LOW_ADDR (proc_desc)))
-    return &mips_mdebug_frame_unwind;
+  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSN16_SIZE)
+    {
+      /* 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;
 
-  return NULL;
-}
+      /* Fetch and decode the instruction.   */
+      inst = (unsigned short) mips_fetch_instruction (cur_pc);
 
-static CORE_ADDR
-mips_mdebug_frame_base_address (struct frame_info *next_frame,
-                               void **this_cache)
-{
-  struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame,
-                                                          this_cache);
-  return info->base;
-}
+      /* 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;
+        }
 
-static const struct frame_base mips_mdebug_frame_base = {
-  &mips_mdebug_frame_unwind,
-  mips_mdebug_frame_base_address,
-  mips_mdebug_frame_base_address,
-  mips_mdebug_frame_base_address
-};
+      prev_extend_bytes = extend_bytes;
+      extend_bytes = 0;
 
-static const struct frame_base *
-mips_mdebug_frame_base_sniffer (struct frame_info *next_frame)
-{
-  if (mips_mdebug_frame_sniffer (next_frame) != NULL)
-    return &mips_mdebug_frame_base;
-  else
-    return NULL;
+      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? */
+           frame_offset -= 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];
+         set_reg_offset (this_cache, 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];
+         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;
+        }
+    }
+
+  /* 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;
+
+      /* Check if a0-a3 were saved in the caller's argument save area.  */
+      for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
+       {
+         set_reg_offset (this_cache, reg, sp + offset);
+         offset += mips_abi_regsize (current_gdbarch);
+       }
+
+      /* 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,
+                                      gdbarch_num_regs (current_gdbarch)
+                                      + 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[gdbarch_num_regs (current_gdbarch)
+                            + mips_regnum (current_gdbarch)->pc]
+        = this_cache->saved_regs[gdbarch_num_regs (current_gdbarch)
+                                + 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).
@@ -1727,7 +1763,8 @@ mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
 
   /* Analyze the function prologue.  */
   {
-    const CORE_ADDR pc = frame_pc_unwind (next_frame);
+    const CORE_ADDR pc =
+      frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
     CORE_ADDR start_addr;
 
     find_pc_partial_function (pc, NULL, &start_addr, NULL);
@@ -1738,11 +1775,12 @@ mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
     if (start_addr == 0)
       return cache;
 
-    heuristic_proc_desc (start_addr, pc, next_frame, *this_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);
+  trad_frame_set_value (cache->saved_regs, gdbarch_num_regs (current_gdbarch)
+                                          + MIPS_SP_REGNUM, cache->base);
 
   return (*this_cache);
 }
@@ -1753,7 +1791,8 @@ mips_insn16_frame_this_id (struct frame_info *next_frame, void **this_cache,
 {
   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));
+  (*this_id) = frame_id_build (info->base,
+                              frame_func_unwind (next_frame, NORMAL_FRAME));
 }
 
 static void
@@ -1761,7 +1800,7 @@ 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)
+                                int *realnump, gdb_byte *valuep)
 {
   struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
                                                           this_cache);
@@ -1780,7 +1819,7 @@ static const struct frame_unwind *
 mips_insn16_frame_sniffer (struct frame_info *next_frame)
 {
   CORE_ADDR pc = frame_pc_unwind (next_frame);
-  if (pc_is_mips16 (pc))
+  if (mips_pc_is_mips16 (pc))
     return &mips_insn16_frame_unwind;
   return NULL;
 }
@@ -1811,638 +1850,63 @@ mips_insn16_frame_base_sniffer (struct frame_info *next_frame)
     return NULL;
 }
 
-/* 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.  */
+/* Mark all the registers as unset in the saved_regs array
+   of THIS_CACHE.  Do nothing if THIS_CACHE is null.  */
 
-static struct mips_frame_cache *
-mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
+void
+reset_saved_regs (struct mips_frame_cache *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);
+  if (this_cache == NULL || this_cache->saved_regs == NULL)
+    return;
 
-  /* 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;
+    const int num_regs = gdbarch_num_regs (current_gdbarch);
+    int i;
 
-    heuristic_proc_desc (start_addr, pc, next_frame, *this_cache);
+    for (i = 0; i < num_regs; i++)
+      {
+        this_cache->saved_regs[i].addr = -1;
+      }
   }
-  
-  /* 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 (! pc_is_mips16 (pc))
-    return &mips_insn32_frame_unwind;
-  return NULL;
-}
+/* 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
-mips_insn32_frame_base_address (struct frame_info *next_frame,
-                               void **this_cache)
+mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+                      struct frame_info *next_frame,
+                      struct mips_frame_cache *this_cache)
 {
-  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
-                                                          this_cache);
-  return info->base;
-}
+  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;
 
-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
-};
+  CORE_ADDR end_prologue_addr = 0;
+  int seen_sp_adjust = 0;
+  int load_immediate_bytes = 0;
 
-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;
+  /* 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, gdbarch_num_regs (current_gdbarch)
+                                         + MIPS_SP_REGNUM);
   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;
+    sp = 0;
 
-  if ((*this_cache) != NULL)
-    return (*this_cache);
-  this_trad_cache = trad_frame_cache_zalloc (next_frame);
-  (*this_cache) = this_trad_cache;
+  if (limit_pc > start_pc + 200)
+    limit_pc = start_pc + 200;
 
-  /* The return address is in the link register.  */
-  trad_frame_set_reg_realreg (this_trad_cache, PC_REGNUM, RA_REGNUM);
+restart:
 
-  /* 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, 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)
-{
-  /* Always a pseudo.  */
-  gdb_assert (regno >= NUM_REGS);
-  if (fi == NULL)
-    {
-      LONGEST val;
-      regcache_cooked_read_signed (current_regcache, regno, &val);
-      return val;
-    }
-  else
-    return frame_unwind_register_signed (fi, regno);
-
-}
-
-/* mips_addr_bits_remove - remove useless address bits  */
-
-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))
-    /* 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
-       addresses are ignored by the hardware.  Thus, the PC or SP are
-       likely to have been sign extended to all 1s by instruction
-       sequences that load 32-bit addresses.  For example, a typical
-       piece of code that loads an address is this:
-
-       lui $r2, <upper 16 bits>
-       ori $r2, <lower 16 bits>
-
-       But the lui sign-extends the value such that the upper 32 bits
-       may be all 1s.  The workaround is simply to mask off these
-       bits.  In the future, gcc may be changed to support true 64-bit
-       addressing, and this masking will have to be disabled.  */
-    return addr &= 0xffffffffUL;
-  else
-    return addr;
-}
-
-/* mips_software_single_step() is called just before we want to resume
-   the inferior, if we want to single-step it but there is no hardware
-   or kernel single-step support (MIPS on GNU/Linux for example).  We find
-   the target of the coming instruction and breakpoint it.
-
-   single_step is also called just after the inferior stops.  If we had
-   set up a simulated single-step, we undo our damage.  */
-
-void
-mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
-{
-  static CORE_ADDR next_pc;
-  typedef char binsn_quantum[BREAKPOINT_MAX];
-  static binsn_quantum break_mem;
-  CORE_ADDR pc;
-
-  if (insert_breakpoints_p)
-    {
-      pc = read_register (mips_regnum (current_gdbarch)->pc);
-      next_pc = mips_next_pc (pc);
-
-      target_insert_breakpoint (next_pc, break_mem);
-    }
-  else
-    target_remove_breakpoint (next_pc, break_mem);
-}
-
-static struct mips_extra_func_info temp_proc_desc;
-
-/* 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 (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;
-    }
-}
-
-
-/* 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;
-
-  pc = ADDR_BITS_REMOVE (pc);
-  start_pc = pc;
-  fence = start_pc - heuristic_fence_post;
-  if (start_pc == 0)
-    return 0;
-
-  if (heuristic_fence_post == UINT_MAX || fence < VM_MIN_ADDRESS)
-    fence = VM_MIN_ADDRESS;
-
-  instlen = pc_is_mips16 (pc) ? MIPS16_INSTLEN : MIPS_INSTLEN;
-
-  /* search back for previous return */
-  for (start_pc -= instlen;; start_pc -= instlen)
-    if (start_pc < fence)
-      {
-       /* It's not clear to me why we reach this point when
-          stop_soon, but with this test, at least we
-          don't print out warnings for every child forked (eg, on
-          decstation).  22apr93 rich@cygnus.com.  */
-       if (stop_soon == NO_STOP_QUIETLY)
-         {
-           static int blurb_printed = 0;
-
-           warning ("GDB can't find the start of the function at 0x%s.",
-                    paddr_nz (pc));
-
-           if (!blurb_printed)
-             {
-               /* This actually happens frequently in embedded
-                  development, when you first connect to a board
-                  and your stack pointer and pc are nowhere in
-                  particular.  This message needs to give people
-                  in that situation enough information to
-                  determine that it's no big deal.  */
-               printf_filtered ("\n\
-    GDB is unable to find the start of the function at 0x%s\n\
-and thus can't determine the size of that function's stack frame.\n\
-This means that GDB may be unable to access that stack frame, or\n\
-the frames below it.\n\
-    This problem is most likely caused by an invalid program counter or\n\
-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));
-               blurb_printed = 1;
-             }
-         }
-
-       return 0;
-      }
-    else if (pc_is_mips16 (start_pc))
-      {
-       unsigned short inst;
-
-       /* On MIPS16, any one of the following is likely to be the
-          start of a function:
-          entry
-          addiu sp,-n
-          daddiu sp,-n
-          extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'  */
-       inst = mips_fetch_instruction (start_pc);
-       if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)      /* entry */
-           || (inst & 0xff80) == 0x6380        /* addiu sp,-n */
-           || (inst & 0xff80) == 0xfb80        /* daddiu sp,-n */
-           || ((inst & 0xf810) == 0xf010 && seen_adjsp))       /* extend -n */
-         break;
-       else if ((inst & 0xff00) == 0x6300      /* addiu sp */
-                || (inst & 0xff00) == 0xfb00)  /* daddiu sp */
-         seen_adjsp = 1;
-       else
-         seen_adjsp = 0;
-      }
-    else if (mips_about_to_return (start_pc))
-      {
-       start_pc += 2 * MIPS_INSTLEN;   /* skip return, and its delay slot */
-       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_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? */
-    {
-      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;
-
-      offset = inst & mask;
-      if (is_signed && (offset & sign_bit))
-       offset = 0 - (max_imm - offset);
-      return offset * scale;
-    }
-}
-
-
-/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
-   the associated FRAME_CACHE if not null.  */
-
-static void
-mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc, CORE_ADDR sp,
-                      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 */
-  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;
-
-  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;
-
-      /* 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? */
-           frame_offset -= 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];
-         set_reg_offset (this_cache, 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];
-         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, 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, 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 += MIPS16_INSTLEN;       /* 32-bit instruction */
-    }
-
-  /* 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;
-
-      /* Check if a0-a3 were saved in the caller's argument save area.  */
-      for (reg = 4, offset = 0; reg < areg_count + 4; reg++)
-       {
-         set_reg_offset (this_cache, reg, sp + offset);
-         offset += mips_abi_regsize (current_gdbarch);
-       }
-
-      /* Check if the ra register was pushed on the stack.  */
-      offset = -4;
-      if (entry_inst & 0x20)
-       {
-         set_reg_offset (this_cache, 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 + RA_REGNUM];
-    }
-}
-
-/* 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, CORE_ADDR sp,
-                      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 */
-  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;
-
-restart:
-
-  frame_offset = 0;
-  for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSTLEN)
-    {
-      unsigned long inst, high_word, low_word;
-      int reg;
+  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);
@@ -2484,7 +1948,9 @@ restart:
              unsigned alloca_adjust;
 
              frame_reg = 30;
-             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
+             frame_addr = read_next_frame_reg (next_frame,
+                                               gdbarch_num_regs
+                                                 (current_gdbarch) + 30);
              alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
              if (alloca_adjust > 0)
                {
@@ -2512,7 +1978,9 @@ restart:
              unsigned alloca_adjust;
 
              frame_reg = 30;
-             frame_addr = read_next_frame_reg (next_frame, NUM_REGS + 30);
+             frame_addr = read_next_frame_reg (next_frame,
+                                               gdbarch_num_regs 
+                                                 (current_gdbarch) + 30);
              alloca_adjust = (unsigned) (frame_addr - sp);
              if (alloca_adjust > 0)
                {
@@ -2559,7 +2027,7 @@ restart:
                    || high_word == 0x3408 /* ori $t0,$zero,n */
                   ))
        {
-          load_immediate_bytes += MIPS_INSTLEN;     /* FIXME!! */
+          load_immediate_bytes += MIPS_INSN32_SIZE;            /* FIXME!  */
        }
       else
        {
@@ -2577,304 +2045,432 @@ restart:
   if (this_cache != NULL)
     {
       this_cache->base = 
-        (frame_unwind_register_signed (next_frame, NUM_REGS + frame_reg)
+        (frame_unwind_register_signed (next_frame,
+                                      gdbarch_num_regs (current_gdbarch)
+                                      + 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 + RA_REGNUM];
+      this_cache->saved_regs[gdbarch_num_regs (current_gdbarch)
+                            + mips_regnum (current_gdbarch)->pc]
+        = this_cache->saved_regs[gdbarch_num_regs (current_gdbarch)
+                                + 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;
+  /* 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_unwind_address_in_block (next_frame, NORMAL_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,
+                       gdbarch_num_regs (current_gdbarch) + 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, NORMAL_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, gdb_byte *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;
+}
 
-  return end_prologue_addr;
+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 mips_extra_func_info_t
-heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                    struct frame_info *next_frame,
-                    struct mips_frame_cache *this_cache)
+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, gdb_byte *valuep)
 {
-  CORE_ADDR sp;
+  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);
+}
 
-  /* 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;
+static const struct frame_unwind mips_stub_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_stub_frame_this_id,
+  mips_stub_frame_prev_register
+};
 
-  if (start_pc == 0)
-    return NULL;
-  memset (&temp_proc_desc, '\0', sizeof (temp_proc_desc));
-  PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
-  PROC_FRAME_REG (&temp_proc_desc) = MIPS_SP_REGNUM;
-  PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
+static const struct frame_unwind *
+mips_stub_frame_sniffer (struct frame_info *next_frame)
+{
+  struct obj_section *s;
+  CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME);
 
-  if (start_pc + 200 < limit_pc)
-    limit_pc = start_pc + 200;
-  if (pc_is_mips16 (start_pc))
-    mips16_scan_prologue (start_pc, limit_pc, sp, next_frame, this_cache);
-  else
-    mips32_scan_prologue (start_pc, limit_pc, sp, next_frame, this_cache);
-  return &temp_proc_desc;
+  if (in_plt_section (pc, NULL))
+    return &mips_stub_frame_unwind;
+
+  /* Binutils for MIPS puts lazy resolution stubs into .MIPS.stubs.  */
+  s = find_pc_section (pc);
+
+  if (s != NULL
+      && strcmp (bfd_get_section_name (s->objfile->obfd, s->the_bfd_section),
+                ".MIPS.stubs") == 0)
+    return &mips_stub_frame_unwind;
+
+  return NULL;
 }
 
-struct mips_objfile_private
+static CORE_ADDR
+mips_stub_frame_base_address (struct frame_info *next_frame,
+                             void **this_cache)
 {
-  bfd_size_type size;
-  char *contents;
-};
+  struct trad_frame_cache *this_trad_cache
+    = mips_stub_frame_cache (next_frame, this_cache);
+  return trad_frame_get_this_base (this_trad_cache);
+}
 
-/* Global used to communicate between non_heuristic_proc_desc and
-   compare_pdr_entries within qsort ().  */
-static bfd *the_bfd;
+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 int
-compare_pdr_entries (const void *a, const void *b)
+static const struct frame_base *
+mips_stub_frame_base_sniffer (struct frame_info *next_frame)
 {
-  CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
-  CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
+  if (mips_stub_frame_sniffer (next_frame) != NULL)
+    return &mips_stub_frame_base;
+  else
+    return NULL;
+}
 
-  if (lhs < rhs)
-    return -1;
-  else if (lhs == rhs)
-    return 0;
+static CORE_ADDR
+read_next_frame_reg (struct frame_info *fi, int regno)
+{
+  /* Always a pseudo.  */
+  gdb_assert (regno >= gdbarch_num_regs (current_gdbarch));
+  if (fi == NULL)
+    {
+      LONGEST val;
+      regcache_cooked_read_signed (current_regcache, regno, &val);
+      return val;
+    }
   else
-    return 1;
+    return frame_unwind_register_signed (fi, regno);
+
 }
 
-static mips_extra_func_info_t
-non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
+/* mips_addr_bits_remove - remove useless address bits  */
+
+static CORE_ADDR
+mips_addr_bits_remove (CORE_ADDR addr)
 {
-  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;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  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
+       addresses are ignored by the hardware.  Thus, the PC or SP are
+       likely to have been sign extended to all 1s by instruction
+       sequences that load 32-bit addresses.  For example, a typical
+       piece of code that loads an address is this:
 
-  find_pc_partial_function (pc, NULL, &startaddr, NULL);
-  if (addrptr)
-    *addrptr = startaddr;
+       lui $r2, <upper 16 bits>
+       ori $r2, <lower 16 bits>
 
-  priv = NULL;
+       But the lui sign-extends the value such that the upper 32 bits
+       may be all 1s.  The workaround is simply to mask off these
+       bits.  In the future, gcc may be changed to support true 64-bit
+       addressing, and this masking will have to be disabled.  */
+    return addr &= 0xffffffffUL;
+  else
+    return addr;
+}
 
-  sec = find_pc_section (pc);
-  if (sec != NULL)
-    {
-      priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data);
+/* mips_software_single_step() is called just before we want to resume
+   the inferior, if we want to single-step it but there is no hardware
+   or kernel single-step support (MIPS on GNU/Linux for example).  We find
+   the target of the coming instruction and breakpoint it.  */
 
-      /* Search the ".pdr" section generated by GAS.  This includes most of
-         the information normally found in ECOFF PDRs.  */
+int
+mips_software_single_step (struct regcache *regcache)
+{
+  CORE_ADDR pc, next_pc;
 
-      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->objfile_obstack,
-                               sizeof (struct mips_objfile_private));
-         priv->size = 0;
-         set_objfile_data (sec->objfile, mips_pdr_data, priv);
-       }
-      else if (priv == NULL)
-       {
-         asection *bfdsec;
+  pc = read_register (mips_regnum (current_gdbarch)->pc);
+  next_pc = mips_next_pc (pc);
 
-         priv = obstack_alloc (&sec->objfile->objfile_obstack,
-                               sizeof (struct mips_objfile_private));
+  insert_single_step_breakpoint (next_pc);
+  return 1;
+}
 
-         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->objfile_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);
-           }
-         else
-           priv->size = 0;
+/* Test whether the PC points to the return instruction at the
+   end of a function. */
 
-         set_objfile_data (sec->objfile, mips_pdr_data, priv);
-       }
-      the_bfd = NULL;
+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 */
+}
 
-      if (priv->size != 0)
-       {
-         int low, mid, high;
-         char *ptr;
-         CORE_ADDR pdr_pc;
-
-         low = 0;
-         high = priv->size / 32;
-
-         /* We've found a .pdr section describing this objfile.  We want to
-            find the entry which describes this code address.  The .pdr
-            information is not very descriptive; we have only a function
-            start address.  We have to look for the closest entry, because
-            the local symbol at the beginning of this function may have
-            been stripped - so if we ask the symbol table for the start
-            address we may get a preceding global function.  */
-
-         /* First, find the last .pdr entry starting at or before PC.  */
-         do
-           {
-             mid = (low + high) / 2;
 
-             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));
+/* This fencepost looks highly suspicious to me.  Removing it also
+   seems suspicious as it could affect remote debugging across serial
+   lines.  */
 
-             if (pdr_pc > pc)
-               high = mid;
-             else
-               low = mid + 1;
-           }
-         while (low != high);
+static CORE_ADDR
+heuristic_proc_start (CORE_ADDR pc)
+{
+  CORE_ADDR start_pc;
+  CORE_ADDR fence;
+  int instlen;
+  int seen_adjsp = 0;
 
-         /* Both low and high point one past the PDR of interest.  If
-            both are zero, that means this PC is before any region
-            covered by a PDR, i.e. pdr_pc for the first PDR entry is
-            greater than PC.  */
-         if (low > 0)
-           {
-             ptr = priv->contents + (low - 1) * 32;
-             pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
-             pdr_pc += ANOFFSET (sec->objfile->section_offsets,
-                                 SECT_OFF_TEXT (sec->objfile));
-           }
+  pc = gdbarch_addr_bits_remove (current_gdbarch, pc);
+  start_pc = pc;
+  fence = start_pc - heuristic_fence_post;
+  if (start_pc == 0)
+    return 0;
 
-         /* We don't have a range, so we have no way to know for sure
-            whether we're in the correct PDR or a PDR for a preceding
-            function and the current function was a stripped local
-            symbol.  But if the PDR's PC is at least as great as the
-            best guess from the symbol table, assume that it does cover
-            the right area; if a .pdr section is present at all then
-            nearly every function will have an entry.  The biggest exception
-            will be the dynamic linker stubs; conveniently these are
-            placed before .text instead of after.  */
-
-         if (pc >= pdr_pc && pdr_pc >= startaddr)
-           {
-             struct symbol *sym = find_pc_function (pc);
-
-             if (addrptr)
-               *addrptr = pdr_pc;
-
-             /* Fill in what we need of the proc_desc.  */
-             proc_desc = (mips_extra_func_info_t)
-               obstack_alloc (&sec->objfile->objfile_obstack,
-                              sizeof (struct mips_extra_func_info));
-             PROC_LOW_ADDR (proc_desc) = pdr_pc;
-
-             /* 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;
-           }
-       }
-    }
+  if (heuristic_fence_post == UINT_MAX || fence < VM_MIN_ADDRESS)
+    fence = VM_MIN_ADDRESS;
 
-  if (b == NULL)
-    return NULL;
+  instlen = mips_pc_is_mips16 (pc) ? MIPS_INSN16_SIZE : MIPS_INSN32_SIZE;
 
-  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;
-    }
+  /* search back for previous return */
+  for (start_pc -= instlen;; start_pc -= instlen)
+    if (start_pc < fence)
+      {
+       /* It's not clear to me why we reach this point when
+          stop_soon, but with this test, at least we
+          don't print out warnings for every child forked (eg, on
+          decstation).  22apr93 rich@cygnus.com.  */
+       if (stop_soon == NO_STOP_QUIETLY)
+         {
+           static int blurb_printed = 0;
 
-  sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
+           warning (_("GDB can't find the start of the function at 0x%s."),
+                    paddr_nz (pc));
 
-  /* 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;
-}
+           if (!blurb_printed)
+             {
+               /* This actually happens frequently in embedded
+                  development, when you first connect to a board
+                  and your stack pointer and pc are nowhere in
+                  particular.  This message needs to give people
+                  in that situation enough information to
+                  determine that it's no big deal.  */
+               printf_filtered ("\n\
+    GDB is unable to find the start of the function at 0x%s\n\
+and thus can't determine the size of that function's stack frame.\n\
+This means that GDB may be unable to access that stack frame, or\n\
+the frames below it.\n\
+    This problem is most likely caused by an invalid program counter or\n\
+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));
+               blurb_printed = 1;
+             }
+         }
 
-/* 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.
+       return 0;
+      }
+    else if (mips_pc_is_mips16 (start_pc))
+      {
+       unsigned short inst;
 
-   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.
+       /* On MIPS16, any one of the following is likely to be the
+          start of a function:
+          entry
+          addiu sp,-n
+          daddiu sp,-n
+          extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'  */
+       inst = mips_fetch_instruction (start_pc);
+       if (((inst & 0xf81f) == 0xe809 && (inst & 0x700) != 0x700)      /* entry */
+           || (inst & 0xff80) == 0x6380        /* addiu sp,-n */
+           || (inst & 0xff80) == 0xfb80        /* daddiu sp,-n */
+           || ((inst & 0xf810) == 0xf010 && seen_adjsp))       /* extend -n */
+         break;
+       else if ((inst & 0xff00) == 0x6300      /* addiu sp */
+                || (inst & 0xff00) == 0xfb00)  /* daddiu sp */
+         seen_adjsp = 1;
+       else
+         seen_adjsp = 0;
+      }
+    else if (mips_about_to_return (start_pc))
+      {
+       /* Skip return and its delay slot.  */
+       start_pc += 2 * MIPS_INSN32_SIZE;
+       break;
+      }
 
-   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.  */
+  return start_pc;
+}
 
-struct frame_info *
-setup_arbitrary_frame (int argc, CORE_ADDR *argv)
+struct mips_objfile_private
 {
-  if (argc != 2)
-    error ("MIPS frame specifications require two arguments: sp and pc");
-
-  return create_new_frame (argv[0], argv[1]);
-}
+  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
+   is no FPU, FP are not even considered as possible candidates for
    FP registers and, consequently this returns false - forces FP
    arguments into integer registers. */
 
@@ -2886,7 +2482,8 @@ fp_register_arg_p (enum type_code typecode, struct type *arg_type)
               && (typecode == TYPE_CODE_STRUCT
                   || typecode == TYPE_CODE_UNION)
               && TYPE_NFIELDS (arg_type) == 1
-              && TYPE_CODE (TYPE_FIELD_TYPE (arg_type, 0)) == TYPE_CODE_FLT))
+              && TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (arg_type, 0))) 
+              == TYPE_CODE_FLT))
          && MIPS_FPU_TYPE != MIPS_FPU_NONE);
 }
 
@@ -2927,145 +2524,6 @@ mips_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
   return align_down (addr, 16);
 }
 
-/* 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 (mips_abi_regsize (current_gdbarch) < 8 && 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_abi_regsize (current_gdbarch))
-       {
-         /* "un-left-justify" the value in the low register */
-         lo->reg_offset = mips_abi_regsize (current_gdbarch) - len;
-         lo->len = len;
-         hi->reg_offset = 0;
-         hi->len = 0;
-       }
-      else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG && len > mips_abi_regsize (current_gdbarch) /* odd-size structs */
-              && len < mips_abi_regsize (current_gdbarch) * 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_abi_regsize (current_gdbarch) - len;
-         lo->len = mips_abi_regsize (current_gdbarch) - 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_abi_regsize (current_gdbarch))
-           {
-             lo->len = mips_abi_regsize (current_gdbarch);
-             hi->len = len - mips_abi_regsize (current_gdbarch);
-           }
-         else
-           {
-             lo->len = len;
-             hi->len = 0;
-           }
-       }
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-         && register_size (current_gdbarch, regnum) == 8
-         && mips_abi_regsize (current_gdbarch) == 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;
-    }
-}
-
-/* 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_abi_regsize (current_gdbarch));
-}
-
-/* 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_abi_regsize (current_gdbarch));
-
-  return 0;
-}
-
 static CORE_ADDR
 mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                           struct regcache *regcache, CORE_ADDR bp_addr,
@@ -3079,14 +2537,15 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   CORE_ADDR func_addr = find_function_addr (function, NULL);
+  int regsize = mips_abi_regsize (gdbarch);
 
   /* 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
@@ -3101,8 +2560,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      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));
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])), regsize);
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3111,7 +2569,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        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.  */
@@ -3129,10 +2587,10 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      char *val;
-      char valbuf[MAX_REGISTER_SIZE];
+      const gdb_byte *val;
+      gdb_byte 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);
 
@@ -3143,27 +2601,25 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       /* The EABI passes structures that do not fit in a register by
          reference.  */
-      if (len > mips_abi_regsize (gdbarch)
+      if (len > regsize
          && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
-         store_unsigned_integer (valbuf, mips_abi_regsize (gdbarch),
-                                 VALUE_ADDRESS (arg));
+         store_unsigned_integer (valbuf, regsize, VALUE_ADDRESS (arg));
          typecode = TYPE_CODE_PTR;
-         len = mips_abi_regsize (gdbarch);
+         len = regsize;
          val = valbuf;
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " push");
        }
       else
-       val = (char *) VALUE_CONTENTS (arg);
+       val = 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))
+      if (regsize < 8 && fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
            float_argreg++;
@@ -3184,9 +2640,15 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
+         /* EABI32 will pass doubles in consecutive registers, even on
+            64-bit cores.  At one time, we used to check the size of
+            `float_argreg' to determine whether or not to pass doubles
+            in consecutive registers, but this is not sufficient for
+            making the ABI determination.  */
+         if (len == 8 && mips_abi (gdbarch) == MIPS_ABI_EABI32)
            {
-             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+             int low_offset = gdbarch_byte_order (current_gdbarch)
+                              == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
@@ -3221,13 +2683,12 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          /* 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
+         /* Note: structs whose size is not a multiple of 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));
+         int odd_sized_struct = (len > regsize && len % regsize != 0);
 
          /* Note: Floating-point values that didn't fit into an FP
             register are only written to memory.  */
@@ -3235,8 +2696,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            {
              /* 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));
+             int partial_len = (len < regsize ? len : regsize);
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3252,18 +2712,17 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
-                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+                 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (gdbarch) == 8
+                     if (regsize == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
                              || typecode == TYPE_CODE_FLT) && len <= 4)
-                       longword_offset = mips_stack_argsize (gdbarch) - len;
+                       longword_offset = regsize - 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;
+                              && TYPE_LENGTH (arg_type) < regsize)
+                       longword_offset = regsize - len;
                    }
 
                  if (mips_debug)
@@ -3304,8 +2763,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval,
-                                           mips_abi_regsize (gdbarch)));
+                                     phex (regval, regsize));
                  write_register (argreg, regval);
                  argreg++;
                }
@@ -3320,8 +2778,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 only needs to be adjusted when it has been used.  */
 
              if (stack_used_p)
-               stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (gdbarch));
+               stack_offset += align_up (partial_len, regsize);
            }
        }
       if (mips_debug)
@@ -3334,54 +2791,20 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   return sp;
 }
 
-/* Given a return value in `regbuf' with a type `valtype', extract and
-   copy its value into `valbuf'. */
+/* Determine the return value convention being used.  */
 
-static void
-mips_eabi_extract_return_value (struct type *valtype,
-                               char regbuf[], char *valbuf)
+static enum return_value_convention
+mips_eabi_return_value (struct gdbarch *gdbarch,
+                       struct type *type, struct regcache *regcache,
+                       gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  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);
+  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;
 }
 
-/* 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));
-    }
-}
 
 /* N32/N64 ABI stuff.  */
 
@@ -3401,11 +2824,11 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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
@@ -3418,8 +2841,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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 (gdbarch));
+    len += align_up (TYPE_LENGTH (value_type (args[argnum])), MIPS64_REGSIZE);
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3428,7 +2850,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        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.  */
@@ -3446,9 +2868,9 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      char *val;
+      const gdb_byte *val;
       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);
 
@@ -3457,7 +2879,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "mips_n32n64_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
-      val = (char *) VALUE_CONTENTS (arg);
+      val = value_contents (arg);
 
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
@@ -3483,21 +2905,19 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          /* 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));
+         /* Note: structs whose size is not a multiple of MIPS64_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 > MIPS64_REGSIZE
+                                 && len % MIPS64_REGSIZE != 0);
          /* Note: Floating-point values that didn't fit into an FP
             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_abi_regsize (gdbarch)
-                                ? len : mips_abi_regsize (gdbarch));
+             int partial_len = (len < MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3513,13 +2933,13 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
-                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+                 if (gdbarch_byte_order (current_gdbarch) == 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;
+                     if ((typecode == TYPE_CODE_INT
+                          || typecode == TYPE_CODE_PTR
+                          || typecode == TYPE_CODE_FLT)
+                         && len <= 4)
+                       longword_offset = MIPS64_REGSIZE - len;
                    }
 
                  if (mips_debug)
@@ -3564,34 +2984,19 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     big endian targets.
 
                     It does not seem to be necessary to do the
-                    same for integral types.
-
-                    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.  */
+                    same for integral types.  */
 
-                 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 (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
+                     && partial_len < MIPS64_REGSIZE
+                     && (typecode == TYPE_CODE_STRUCT
+                         || typecode == TYPE_CODE_UNION))
+                   regval <<= ((MIPS64_REGSIZE - partial_len)
+                               TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval,
-                                           mips_abi_regsize (gdbarch)));
+                                     phex (regval, MIPS64_REGSIZE));
                  write_register (argreg, regval);
                  argreg++;
                }
@@ -3606,8 +3011,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 adjusted when it has been used.  */
 
              if (stack_used_p)
-               stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (gdbarch));
+               stack_offset += align_up (partial_len, MIPS64_REGSIZE);
            }
        }
       if (mips_debug)
@@ -3623,14 +3027,36 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 static enum return_value_convention
 mips_n32n64_return_value (struct gdbarch *gdbarch,
                          struct type *type, struct regcache *regcache,
-                         void *readbuf, const void *writebuf)
+                         gdb_byte *readbuf, const gdb_byte *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))
+      || TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
     return RETURN_VALUE_STRUCT_CONVENTION;
+  else if (TYPE_CODE (type) == TYPE_CODE_FLT
+          && TYPE_LENGTH (type) == 16
+          && tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      /* A 128-bit floating-point value fills both $f0 and $f2.  The
+        two registers are used in the same as memory order, so the
+        eight bytes with the lower memory address are in $f0.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $f0 and $f2\n");
+      mips_xfer_register (regcache,
+                         gdbarch_num_regs (current_gdbarch)
+                         + mips_regnum (current_gdbarch)->fp0,
+                         8, gdbarch_byte_order (current_gdbarch),
+                         readbuf, writebuf, 0);
+      mips_xfer_register (regcache,
+                         gdbarch_num_regs (current_gdbarch)
+                         + mips_regnum (current_gdbarch)->fp0 + 2,
+                         8, gdbarch_byte_order (current_gdbarch),
+                         readbuf ? readbuf + 8 : readbuf,
+                         writebuf ? writebuf + 8 : writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
           && tdep->mips_fpu_type != MIPS_FPU_NONE)
     {
@@ -3639,9 +3065,11 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
       if (mips_debug)
        fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
       mips_xfer_register (regcache,
-                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+                         gdbarch_num_regs (current_gdbarch)
+                         + mips_regnum (current_gdbarch)->fp0,
                          TYPE_LENGTH (type),
-                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+                         gdbarch_byte_order (current_gdbarch),
+                         readbuf, writebuf, 0);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -3670,9 +3098,11 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
          if (mips_debug)
            fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n",
                                offset);
-         mips_xfer_register (regcache, NUM_REGS + regnum,
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum,
                              TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+                             gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -3684,7 +3114,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
          mips_xfer_lower.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
           offset < TYPE_LENGTH (type);
           offset += register_size (current_gdbarch, regnum), regnum++)
        {
@@ -3694,7 +3124,8 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
          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,
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum, xfer,
                              BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
@@ -3705,7 +3136,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
          justified.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
           offset < TYPE_LENGTH (type);
           offset += register_size (current_gdbarch, regnum), regnum++)
        {
@@ -3715,8 +3146,10 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
          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);
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum, xfer,
+                             gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -3740,11 +3173,11 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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
@@ -3757,8 +3190,16 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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 (gdbarch));
+    {
+      struct type *arg_type = check_typedef (value_type (args[argnum]));
+      int arglen = TYPE_LENGTH (arg_type);
+
+      /* Align to double-word if necessary.  */
+      if (mips_type_needs_double_align (arg_type))
+       len = align_up (len, MIPS32_REGSIZE * 2);
+      /* Allocate space on the stack.  */
+      len += align_up (arglen, MIPS32_REGSIZE);
+    }
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3767,7 +3208,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        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.  */
@@ -3778,7 +3219,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "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);
+      stack_offset += MIPS32_REGSIZE;
     }
 
   /* Now load as many as possible of the first arguments into
@@ -3786,9 +3227,9 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      char *val;
+      const gdb_byte *val;
       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);
 
@@ -3797,15 +3238,14 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "mips_o32_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
-      val = (char *) VALUE_CONTENTS (arg);
+      val = 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 (fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
            float_argreg++;
@@ -3824,9 +3264,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
+         if (register_size (gdbarch, float_argreg) < 8 && len == 8)
            {
-             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+             int low_offset = gdbarch_byte_order (current_gdbarch)
+                              == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
@@ -3871,39 +3312,38 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                    argreg, phex (regval, len));
              write_register (argreg, regval);
-             argreg += (mips_abi_regsize (gdbarch) == 8) ? 1 : 2;
+             argreg += 2;
            }
          /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
+         stack_offset += align_up (len, MIPS32_REGSIZE);
        }
       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_abi_regsize() are treated specially: Irix cc passes
+         /* Note: structs whose size is not a multiple of MIPS32_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));
+         int odd_sized_struct = (len > MIPS32_REGSIZE
+                                 && len % MIPS32_REGSIZE != 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 (mips_type_needs_double_align (arg_type))
            {
              if ((argreg & 1))
-               argreg++;
+               {
+                 argreg++;
+                 stack_offset += MIPS32_REGSIZE;
+               }
            }
-         /* 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));
+             int partial_len = (len < MIPS32_REGSIZE ? len : MIPS32_REGSIZE);
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3911,22 +3351,13 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
              /* 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))
+                 || odd_sized_struct)
                {
                  /* 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;
-                   }
 
                  if (mips_debug)
                    {
@@ -3953,12 +3384,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                }
 
              /* Note!!! This is NOT an else clause.  Odd sized
-                structs may go thru BOTH paths.  Floating point
-                arguments will not.  */
+                structs may go thru BOTH paths.  */
              /* Write this portion of the argument to a general
                 purpose register.  */
-             if (argreg <= MIPS_LAST_ARG_REGNUM
-                 && !fp_register_arg_p (typecode, arg_type))
+             if (argreg <= MIPS_LAST_ARG_REGNUM)
                {
                  LONGEST regval = extract_signed_integer (val, partial_len);
                  /* Value may need to be sign extended, because
@@ -3977,9 +3406,9 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
                     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
+                    mips_abi_regsize(), generates a left shift
+                    as part of storing the argument in 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
@@ -3989,19 +3418,17 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     identified as such and GDB gets tweaked
                     accordingly.  */
 
-                 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_abi_regsize (gdbarch) - partial_len) *
-                               TARGET_CHAR_BIT);
+                 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
+                     && partial_len < MIPS32_REGSIZE
+                     && (typecode == TYPE_CODE_STRUCT
+                         || typecode == TYPE_CODE_UNION))
+                   regval <<= ((MIPS32_REGSIZE - partial_len)
+                               * TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval,
-                                           mips_abi_regsize (gdbarch)));
+                                     phex (regval, MIPS32_REGSIZE));
                  write_register (argreg, regval);
                  argreg++;
 
@@ -4021,8 +3448,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 refered to as their "home".  Consequently, space is
                 always allocated.  */
 
-             stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (gdbarch));
+             stack_offset += align_up (partial_len, MIPS32_REGSIZE);
            }
        }
       if (mips_debug)
@@ -4038,7 +3464,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 static enum return_value_convention
 mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
                       struct regcache *regcache,
-                      void *readbuf, const void *writebuf)
+                      gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
@@ -4054,9 +3480,11 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
       if (mips_debug)
        fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
       mips_xfer_register (regcache,
-                         NUM_REGS + mips_regnum (current_gdbarch)->fp0,
+                         gdbarch_num_regs (current_gdbarch)
+                           + mips_regnum (current_gdbarch)->fp0,
                          TYPE_LENGTH (type),
-                         TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+                         gdbarch_byte_order (current_gdbarch),
+                         readbuf, writebuf, 0);
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
@@ -4067,26 +3495,34 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
          FP0.  */
       if (mips_debug)
        fprintf_unfiltered (gdb_stderr, "Return float in $fp1/$fp0\n");
-      switch (TARGET_BYTE_ORDER)
+      switch (gdbarch_byte_order (current_gdbarch))
        {
        case BFD_ENDIAN_LITTLE:
          mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
-                             0, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 0);
+                             gdbarch_num_regs (current_gdbarch)
+                               + mips_regnum (current_gdbarch)->fp0 +
+                             0, 4, gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, 0);
          mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
-                             1, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
+                             gdbarch_num_regs (current_gdbarch)
+                               + mips_regnum (current_gdbarch)->fp0 + 1,
+                             4, gdbarch_byte_order (current_gdbarch),
+                             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);
+                             gdbarch_num_regs (current_gdbarch)
+                               + mips_regnum (current_gdbarch)->fp0 + 1,
+                             4, gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, 0);
          mips_xfer_register (regcache,
-                             NUM_REGS + mips_regnum (current_gdbarch)->fp0 +
-                             0, 4, TARGET_BYTE_ORDER, readbuf, writebuf, 4);
+                             gdbarch_num_regs (current_gdbarch)
+                               + mips_regnum (current_gdbarch)->fp0 + 0,
+                             4, gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, 4);
          break;
        default:
-         internal_error (__FILE__, __LINE__, "bad switch");
+         internal_error (__FILE__, __LINE__, _("bad switch"));
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -4107,7 +3543,7 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
       /* 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];
+      gdb_byte reg[MAX_REGISTER_SIZE];
       int regnum;
       int field;
       for (field = 0, regnum = mips_regnum (current_gdbarch)->fp0;
@@ -4118,9 +3554,11 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
          if (mips_debug)
            fprintf_unfiltered (gdb_stderr, "Return float struct+%d\n",
                                offset);
-         mips_xfer_register (regcache, NUM_REGS + regnum,
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum,
                              TYPE_LENGTH (TYPE_FIELD_TYPE (type, field)),
-                             TARGET_BYTE_ORDER, readbuf, writebuf, offset);
+                             gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -4134,7 +3572,7 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
          mips_xfer_lower.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
           offset < TYPE_LENGTH (type);
           offset += register_size (current_gdbarch, regnum), regnum++)
        {
@@ -4144,7 +3582,8 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
          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,
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum, xfer,
                              BFD_ENDIAN_UNKNOWN, readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
@@ -4154,21 +3593,23 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
     {
       /* 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.  */
+         the ISA.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = MIPS_V0_REGNUM;
           offset < TYPE_LENGTH (type);
-          offset += mips_stack_argsize (gdbarch), regnum++)
+          offset += MIPS32_REGSIZE, regnum++)
        {
-         int xfer = mips_stack_argsize (gdbarch);
+         int xfer = MIPS32_REGSIZE;
          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);
+         mips_xfer_register (regcache, gdbarch_num_regs (current_gdbarch)
+                                       + regnum, xfer,
+                             gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, offset);
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -4194,11 +3635,11 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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
@@ -4211,8 +3652,13 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* 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 (gdbarch));
+    {
+      struct type *arg_type = check_typedef (value_type (args[argnum]));
+      int arglen = TYPE_LENGTH (arg_type);
+
+      /* Allocate space on the stack.  */
+      len += align_up (arglen, MIPS64_REGSIZE);
+    }
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -4221,7 +3667,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                        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.  */
@@ -4232,7 +3678,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "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 (gdbarch);
+      stack_offset += MIPS64_REGSIZE;
     }
 
   /* Now load as many as possible of the first arguments into
@@ -4240,9 +3686,9 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
      from first to last.  */
   for (argnum = 0; argnum < nargs; argnum++)
     {
-      char *val;
+      const gdb_byte *val;
       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);
 
@@ -4251,19 +3697,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "mips_o64_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++;
-       }
+      val = value_contents (arg);
 
       /* Floating point arguments passed in registers have to be
          treated specially.  On 32-bit architectures, doubles
@@ -4278,86 +3712,35 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (mips_abi_regsize (gdbarch) < 8 && 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);
-             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;
-           }
+         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++;
          /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
+         stack_offset += align_up (len, MIPS64_REGSIZE);
        }
       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_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.  */
+         /* Note: structs whose size is not a multiple of MIPS64_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 > MIPS64_REGSIZE
+                                 && len % MIPS64_REGSIZE != 0);
          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));
+             int partial_len = (len < MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -4365,21 +3748,20 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
              /* 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))
+                 || odd_sized_struct)
                {
                  /* 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 (gdbarch_byte_order (current_gdbarch) == 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;
+                     if ((typecode == TYPE_CODE_INT
+                          || typecode == TYPE_CODE_PTR
+                          || typecode == TYPE_CODE_FLT)
+                         && len <= 4)
+                       longword_offset = MIPS64_REGSIZE - len;
                    }
 
                  if (mips_debug)
@@ -4407,12 +3789,10 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                }
 
              /* Note!!! This is NOT an else clause.  Odd sized
-                structs may go thru BOTH paths.  Floating point
-                arguments will not.  */
+                structs may go thru BOTH paths.  */
              /* Write this portion of the argument to a general
                 purpose register.  */
-             if (argreg <= MIPS_LAST_ARG_REGNUM
-                 && !fp_register_arg_p (typecode, arg_type))
+             if (argreg <= MIPS_LAST_ARG_REGNUM)
                {
                  LONGEST regval = extract_signed_integer (val, partial_len);
                  /* Value may need to be sign extended, because
@@ -4425,37 +3805,19 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     big endian targets.
 
                     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_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.  */
+                    same for integral types. */
 
-                 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_abi_regsize (gdbarch) - partial_len) *
-                               TARGET_CHAR_BIT);
+                 if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG
+                     && partial_len < MIPS64_REGSIZE
+                     && (typecode == TYPE_CODE_STRUCT
+                         || typecode == TYPE_CODE_UNION))
+                   regval <<= ((MIPS64_REGSIZE - partial_len)
+                               * TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
-                                     phex (regval,
-                                           mips_abi_regsize (gdbarch)));
+                                     phex (regval, MIPS64_REGSIZE));
                  write_register (argreg, regval);
                  argreg++;
 
@@ -4475,8 +3837,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 refered to as their "home".  Consequently, space is
                 always allocated.  */
 
-             stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (gdbarch));
+             stack_offset += align_up (partial_len, MIPS64_REGSIZE);
            }
        }
       if (mips_debug)
@@ -4489,46 +3850,53 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   return sp;
 }
 
-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);
-}
-
-static void
-mips_o64_store_return_value (struct type *valtype, char *valbuf)
+static enum return_value_convention
+mips_o64_return_value (struct gdbarch *gdbarch,
+                      struct type *type, struct regcache *regcache,
+                      gdb_byte *readbuf, const gdb_byte *writebuf)
 {
-  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));
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
-  if (hi.len > 0)
+  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 (fp_register_arg_p (TYPE_CODE (type), type))
+    {
+      /* A 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,
+                         gdbarch_num_regs (current_gdbarch)
+                           + mips_regnum (current_gdbarch)->fp0,
+                         TYPE_LENGTH (type),
+                         gdbarch_byte_order (current_gdbarch),
+                         readbuf, writebuf, 0);
+      return RETURN_VALUE_REGISTER_CONVENTION;
+    }
+  else
     {
-      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));
+      /* 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 += MIPS64_REGSIZE, regnum++)
+       {
+         int xfer = MIPS64_REGSIZE;
+         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, gdbarch_num_regs (current_gdbarch)
+                                       + regnum, xfer,
+                             gdbarch_byte_order (current_gdbarch),
+                             readbuf, writebuf, offset);
+       }
+      return RETURN_VALUE_REGISTER_CONVENTION;
     }
 }
 
@@ -4565,19 +3933,13 @@ mips_o64_store_return_value (struct type *valtype, char *valbuf)
 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;
+  return builtin_type_ieee_single;
 }
 
 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;
+  return builtin_type_ieee_double;
 }
 
 /* Copy a 32-bit single-precision value from the current frame
@@ -4585,20 +3947,21 @@ mips_double_register_type (void)
 
 static void
 mips_read_fp_register_single (struct frame_info *frame, int regno,
-                             char *rare_buffer)
+                             gdb_byte *rare_buffer)
 {
   int raw_size = register_size (current_gdbarch, regno);
-  char *raw_buffer = alloca (raw_size);
+  gdb_byte *raw_buffer = alloca (raw_size);
 
   if (!frame_register_read (frame, regno, raw_buffer))
-    error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
+    error (_("can't read register %d (%s)"),
+          regno, gdbarch_register_name (current_gdbarch, 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)
+      if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
        offset = 4;
       else
        offset = 0;
@@ -4617,7 +3980,7 @@ mips_read_fp_register_single (struct frame_info *frame, int regno,
 
 static void
 mips_read_fp_register_double (struct frame_info *frame, int regno,
-                             char *rare_buffer)
+                             gdb_byte *rare_buffer)
 {
   int raw_size = register_size (current_gdbarch, regno);
 
@@ -4626,18 +3989,19 @@ mips_read_fp_register_double (struct frame_info *frame, int regno,
       /* 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));
+       error (_("can't read register %d (%s)"),
+              regno, gdbarch_register_name (current_gdbarch, 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_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)
+      if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
        {
          mips_read_fp_register_single (frame, regno, rare_buffer + 4);
          mips_read_fp_register_single (frame, regno + 1, rare_buffer);
@@ -4654,17 +4018,18 @@ 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;
+  gdb_byte *raw_buffer;
   double doub, flt1;   /* doubles extracted from raw hex data */
   int inv1, inv2;
 
-  raw_buffer =
-    (char *) alloca (2 *
-                    register_size (current_gdbarch,
-                                   mips_regnum (current_gdbarch)->fp0));
+  raw_buffer = 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)),
+  fprintf_filtered (file, "%s:",
+                   gdbarch_register_name (current_gdbarch, regnum));
+  fprintf_filtered (file, "%*s",
+                   4 - (int) strlen (gdbarch_register_name
+                                       (current_gdbarch, regnum)),
                    "");
 
   if (register_size (current_gdbarch, regnum) == 4 || mips2_fp_compat ())
@@ -4725,13 +4090,13 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
 
 static void
 mips_print_register (struct ui_file *file, struct frame_info *frame,
-                    int regnum, int all)
+                    int regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  char raw_buffer[MAX_REGISTER_SIZE];
+  gdb_byte raw_buffer[MAX_REGISTER_SIZE];
   int offset;
 
-  if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
+  if (TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
     {
       mips_print_fp_register (file, frame, regnum);
       return;
@@ -4740,11 +4105,12 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
   /* Get the data in raw format.  */
   if (!frame_register_read (frame, regnum, raw_buffer))
     {
-      fprintf_filtered (file, "%s: [Invalid]", REGISTER_NAME (regnum));
+      fprintf_filtered (file, "%s: [Invalid]",
+                       gdbarch_register_name (current_gdbarch, regnum));
       return;
     }
 
-  fputs_filtered (REGISTER_NAME (regnum), file);
+  fputs_filtered (gdbarch_register_name (current_gdbarch, regnum), file);
 
   /* The problem with printing numeric register names (r26, etc.) is that
      the user can't use them on input.  Probably the best solution is to
@@ -4755,7 +4121,7 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
   else
     fprintf_filtered (file, ": ");
 
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     offset =
       register_size (current_gdbarch,
                     regnum) - register_size (current_gdbarch, regnum);
@@ -4763,7 +4129,7 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
     offset = 0;
 
   print_scalar_formatted (raw_buffer + offset,
-                         gdbarch_register_type (gdbarch, regnum), 'x', 0,
+                         register_type (gdbarch, regnum), 'x', 0,
                          file);
 }
 
@@ -4789,60 +4155,87 @@ 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];
+  gdb_byte raw_buffer[MAX_REGISTER_SIZE];
   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 < gdbarch_num_regs (current_gdbarch)
+                              + gdbarch_num_pseudo_regs (current_gdbarch);
+       regnum++)
     {
-      if (*REGISTER_NAME (regnum) == '\0')
+      if (*gdbarch_register_name (current_gdbarch, regnum) == '\0')
        continue;               /* unused register */
-      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+      if (TYPE_CODE (register_type (gdbarch, regnum)) ==
          TYPE_CODE_FLT)
        break;                  /* end the row: reached FP register */
+      /* Large registers are handled separately.  */
+      if (register_size (current_gdbarch, regnum)
+         > mips_abi_regsize (current_gdbarch))
+       {
+         if (col > 0)
+           break;              /* End the row before this register.  */
+
+         /* Print this register on a row by itself.  */
+         mips_print_register (file, frame, regnum);
+         fprintf_filtered (file, "\n");
+         return regnum + 1;
+       }
+      if (col == 0)
+       fprintf_filtered (file, "     ");
       fprintf_filtered (file,
                        mips_abi_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
-                       REGISTER_NAME (regnum));
+                       gdbarch_register_name (current_gdbarch, regnum));
       col++;
     }
+
+  if (col == 0)
+    return regnum;
+
   /* print the R0 to R31 names */
-  if ((start_regnum % NUM_REGS) < MIPS_NUMREGS)
-    fprintf_filtered (file, "\n R%-4d", start_regnum % NUM_REGS);
+  if ((start_regnum % gdbarch_num_regs (current_gdbarch)) < MIPS_NUMREGS)
+    fprintf_filtered (file, "\n R%-4d",
+                     start_regnum % gdbarch_num_regs (current_gdbarch));
   else
     fprintf_filtered (file, "\n      ");
 
   /* 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 < gdbarch_num_regs (current_gdbarch)
+                              + gdbarch_num_pseudo_regs (current_gdbarch);
+       regnum++)
     {
-      if (*REGISTER_NAME (regnum) == '\0')
+      if (*gdbarch_register_name (current_gdbarch, regnum) == '\0')
        continue;               /* unused register */
-      if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+      if (TYPE_CODE (register_type (gdbarch, regnum)) ==
          TYPE_CODE_FLT)
        break;                  /* end row: reached FP register */
+      if (register_size (current_gdbarch, regnum)
+         > mips_abi_regsize (current_gdbarch))
+       break;                  /* End row: large 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));
+       error (_("can't read register %d (%s)"),
+              regnum, gdbarch_register_name (current_gdbarch, regnum));
       /* pad small registers */
       for (byte = 0;
           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)
+      if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
        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]);
+         fprintf_filtered (file, "%02x", raw_buffer[byte]);
       else
        for (byte = register_size (current_gdbarch, regnum) - 1;
             byte >= 0; byte--)
-         fprintf_filtered (file, "%02x", (unsigned char) raw_buffer[byte]);
+         fprintf_filtered (file, "%02x", raw_buffer[byte]);
       fprintf_filtered (file, " ");
       col++;
     }
@@ -4860,20 +4253,21 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
 {
   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");
+      gdb_assert (regnum >= gdbarch_num_regs (current_gdbarch));
+      if (*(gdbarch_register_name (current_gdbarch, regnum)) == '\0')
+       error (_("Not a valid register for the current processor type"));
 
-      mips_print_register (file, frame, regnum, 0);
+      mips_print_register (file, frame, regnum);
       fprintf_filtered (file, "\n");
     }
   else
     /* do all (or most) registers */
     {
-      regnum = NUM_REGS;
-      while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
+      regnum = gdbarch_num_regs (current_gdbarch);
+      while (regnum < gdbarch_num_regs (current_gdbarch)
+                     + gdbarch_num_pseudo_regs (current_gdbarch))
        {
-         if (TYPE_CODE (gdbarch_register_type (gdbarch, regnum)) ==
+         if (TYPE_CODE (register_type (gdbarch, regnum)) ==
              TYPE_CODE_FLT)
            {
              if (all)          /* true for "INFO ALL-REGISTERS" command */
@@ -4889,8 +4283,6 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
 
 /* Is this a branch with a delay slot?  */
 
-static int is_delayed (unsigned long);
-
 static int
 is_delayed (unsigned long insn)
 {
@@ -4906,112 +4298,24 @@ is_delayed (unsigned long insn)
 }
 
 int
-mips_step_skips_delay (CORE_ADDR pc)
+mips_single_step_through_delay (struct gdbarch *gdbarch,
+                               struct frame_info *frame)
 {
-  char buf[MIPS_INSTLEN];
+  CORE_ADDR pc = get_frame_pc (frame);
+  gdb_byte buf[MIPS_INSN32_SIZE];
 
   /* There is no branch delay slot on MIPS16.  */
-  if (pc_is_mips16 (pc))
+  if (mips_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.  */
+  if (!breakpoint_here_p (pc + 4))
     return 0;
-  return is_delayed ((unsigned long)
-                    extract_unsigned_integer (buf, MIPS_INSTLEN));
-}
-
-/* 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 */
-  };
-
-  /* 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;
+  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
@@ -5026,15 +4330,18 @@ mips16_skip_prologue (CORE_ADDR pc, CORE_ADDR end_pc)
 static CORE_ADDR
 mips_skip_prologue (CORE_ADDR pc)
 {
+  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.  */
-
-  CORE_ADDR post_prologue_pc = after_prologue (pc);
-  CORE_ADDR limit_pc;
-
-  if (post_prologue_pc != 0)
-    return max (pc, post_prologue_pc);
+  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.  */
@@ -5046,10 +4353,10 @@ mips_skip_prologue (CORE_ADDR pc)
   if (limit_pc == 0)
     limit_pc = pc + 100;          /* Magic.  */
 
-  if (pc_is_mips16 (pc))
-    return mips16_skip_prologue (pc, limit_pc);
+  if (mips_pc_is_mips16 (pc))
+    return mips16_scan_prologue (pc, limit_pc, NULL, NULL);
   else
-    return mips32_scan_prologue (pc, limit_pc, 0, NULL, NULL);
+    return mips32_scan_prologue (pc, limit_pc, NULL, NULL);
 }
 
 /* Root of all "set mips "/"show mips " commands. This will eventually be
@@ -5087,7 +4394,7 @@ show_mipsfpu_command (char *args, int from_tty)
       fpu = "absent (none)";
       break;
     default:
-      internal_error (__FILE__, __LINE__, "bad switch");
+      internal_error (__FILE__, __LINE__, _("bad switch"));
     }
   if (mips_fpu_type_auto)
     printf_unfiltered
@@ -5118,7 +4425,7 @@ set_mipsfpu_single_command (char *args, int from_tty)
      instead of relying on globals.  Doing that would let generic code
      handle the search for this specific architecture.  */
   if (!gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__, "set mipsfpu failed");
+    internal_error (__FILE__, __LINE__, _("set mipsfpu failed"));
 }
 
 static void
@@ -5132,7 +4439,7 @@ set_mipsfpu_double_command (char *args, int from_tty)
      instead of relying on globals.  Doing that would let generic code
      handle the search for this specific architecture.  */
   if (!gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__, "set mipsfpu failed");
+    internal_error (__FILE__, __LINE__, _("set mipsfpu failed"));
 }
 
 static void
@@ -5146,7 +4453,7 @@ set_mipsfpu_none_command (char *args, int from_tty)
      instead of relying on globals.  Doing that would let generic code
      handle the search for this specific architecture.  */
   if (!gdbarch_update_p (info))
-    internal_error (__FILE__, __LINE__, "set mipsfpu failed");
+    internal_error (__FILE__, __LINE__, _("set mipsfpu failed"));
 }
 
 static void
@@ -5167,7 +4474,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;
@@ -5187,34 +4494,13 @@ 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);
@@ -5239,27 +4525,27 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info)
     info->disassembler_options = "gpr-names=32";
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     return print_insn_big_mips (memaddr, info);
   else
     return print_insn_little_mips (memaddr, info);
 }
 
-/* This function implements the BREAKPOINT_FROM_PC macro.  It uses the program
-   counter value to determine whether a 16- or 32-bit breakpoint should be
-   used.  It returns a pointer to a string of bytes that encode a breakpoint
-   instruction, stores the length of the string to *lenptr, and adjusts pc
-   (if necessary) to point to the actual memory location where the
-   breakpoint should be inserted.  */
+/* This function implements gdbarch_breakpoint_from_pc.  It uses the program
+   counter value to determine whether a 16- or 32-bit breakpoint should be used.
+   It returns a pointer to a string of bytes that encode a breakpoint
+   instruction, stores the length of the string to *lenptr, and adjusts pc (if
+   necessary) to point to the actual memory location where the breakpoint
+   should be inserted.  */
 
-static const unsigned char *
+static const gdb_byte *
 mips_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
 {
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+  if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
     {
-      if (pc_is_mips16 (*pcptr))
+      if (mips_pc_is_mips16 (*pcptr))
        {
-         static unsigned char mips16_big_breakpoint[] = { 0xe8, 0xa5 };
+         static gdb_byte mips16_big_breakpoint[] = { 0xe8, 0xa5 };
          *pcptr = unmake_mips16_addr (*pcptr);
          *lenptr = sizeof (mips16_big_breakpoint);
          return mips16_big_breakpoint;
@@ -5269,9 +4555,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 gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
+         static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
+         static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
 
          *lenptr = sizeof (big_breakpoint);
 
@@ -5287,18 +4573,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 gdb_byte 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 gdb_byte little_breakpoint[] = { 0xd, 0, 0x5, 0 };
+         static gdb_byte pmon_little_breakpoint[] = { 0xd, 0, 0, 0 };
+         static gdb_byte idt_little_breakpoint[] = { 0xd, 0x0a, 0, 0 };
 
          *lenptr = sizeof (little_breakpoint);
 
@@ -5328,13 +4614,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;
@@ -5347,7 +4630,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)
     {
@@ -5377,7 +4660,7 @@ 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_*.  */
@@ -5392,7 +4675,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 */
@@ -5413,85 +4696,8 @@ 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
-   DEPRECATED_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);
-}
-
-
 /* Convert a dbx stab register number (from `r' declaration) to a GDB
-   [1 * NUM_REGS .. 2 * NUM_REGS) REGNUM.  */
+   [1 * gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
 
 static int
 mips_stab_reg_to_regnum (int num)
@@ -5508,13 +4714,14 @@ mips_stab_reg_to_regnum (int num)
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
-    return NUM_REGS + NUM_PSEUDO_REGS;
-  return NUM_REGS + regnum;
+    return gdbarch_num_regs (current_gdbarch)
+          + gdbarch_num_pseudo_regs (current_gdbarch);
+  return gdbarch_num_regs (current_gdbarch) + regnum;
 }
 
 
 /* Convert a dwarf, dwarf2, or ecoff register number to a GDB [1 *
-   NUM_REGS .. 2 * NUM_REGS) REGNUM.  */
+   gdbarch_num_regs .. 2 * gdbarch_num_regs) REGNUM.  */
 
 static int
 mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
@@ -5531,38 +4738,39 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
-    return NUM_REGS + NUM_PSEUDO_REGS;
-  return NUM_REGS + regnum;
+    return gdbarch_num_regs (current_gdbarch)
+          + gdbarch_num_pseudo_regs (current_gdbarch);
+  return gdbarch_num_regs (current_gdbarch) + regnum;
 }
 
 static int
 mips_register_sim_regno (int regnum)
 {
   /* Only makes sense to supply raw registers.  */
-  gdb_assert (regnum >= 0 && regnum < NUM_REGS);
+  gdb_assert (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch));
   /* FIXME: cagney/2002-05-13: Need to look at the pseudo register to
      decide if it is valid.  Should instead define a standard sim/gdb
      register numbering scheme.  */
-  if (REGISTER_NAME (NUM_REGS + regnum) != NULL
-      && REGISTER_NAME (NUM_REGS + regnum)[0] != '\0')
+  if (gdbarch_register_name (current_gdbarch,
+                            gdbarch_num_regs
+                              (current_gdbarch) + regnum) != NULL
+      && gdbarch_register_name (current_gdbarch,
+                               gdbarch_num_regs
+                                 (current_gdbarch) + regnum)[0] != '\0')
     return regnum;
   else
     return LEGACY_SIM_REGNO_IGNORE;
 }
 
 
-/* Convert an integer into an address.  By first converting the value
-   into a pointer and then extracting it signed, the address is
-   guarenteed to be correctly sign extended.  */
+/* Convert an integer into an address.  Extracting the value signed
+   guarantees a correctly sign extended address.  */
 
 static CORE_ADDR
-mips_integer_to_address (struct type *type, void *buf)
+mips_integer_to_address (struct gdbarch *gdbarch,
+                        struct type *type, const gdb_byte *buf)
 {
-  char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
-  LONGEST val = unpack_long (type, buf);
-  store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
-  return extract_signed_integer (tmp,
-                                TYPE_LENGTH (builtin_type_void_data_ptr));
+  return (CORE_ADDR) extract_signed_integer (buf, TYPE_LENGTH (type));
 }
 
 static void
@@ -5590,7 +4798,21 @@ mips_find_abi_section (bfd *abfd, asection *sect, void *obj)
   else if (strcmp (name, ".mdebug.eabi64") == 0)
     *abip = MIPS_ABI_EABI64;
   else
-    warning ("unsupported ABI %s.", name + 8);
+    warning (_("unsupported ABI %s."), name + 8);
+}
+
+static void
+mips_find_long_section (bfd *abfd, asection *sect, void *obj)
+{
+  int *lbp = (int *) obj;
+  const char *name = bfd_get_section_name (abfd, sect);
+
+  if (strncmp (name, ".gcc_compiled_long32", 20) == 0)
+    *lbp = 32;
+  else if (strncmp (name, ".gcc_compiled_long64", 20) == 0)
+    *lbp = 64;
+  else if (strncmp (name, ".gcc_compiled_long", 18) == 0)
+    warning (_("unrecognized .gcc_compiled_longXX"));
 }
 
 static enum mips_abi
@@ -5602,7 +4824,45 @@ 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 void
+mips_register_g_packet_guesses (struct gdbarch *gdbarch)
+{
+  static struct target_desc *tdesc_gp32, *tdesc_gp64;
+
+  if (tdesc_gp32 == NULL)
+    {
+      /* Create feature sets with the appropriate properties.  The values
+        are not important.  */
+
+      tdesc_gp32 = allocate_target_description ();
+      set_tdesc_property (tdesc_gp32, PROPERTY_GP32, "");
+
+      tdesc_gp64 = allocate_target_description ();
+      set_tdesc_property (tdesc_gp64, PROPERTY_GP64, "");
+    }
+
+  /* If the size matches the set of 32-bit or 64-bit integer registers,
+     assume that's what we've got.  */
+  register_remote_g_packet_guess (gdbarch, 38 * 4, tdesc_gp32);
+  register_remote_g_packet_guess (gdbarch, 38 * 8, tdesc_gp64);
+
+  /* If the size matches the full set of registers GDB traditionally
+     knows about, including floating point, for either 32-bit or
+     64-bit, assume that's what we've got.  */
+  register_remote_g_packet_guess (gdbarch, 90 * 4, tdesc_gp32);
+  register_remote_g_packet_guess (gdbarch, 90 * 8, tdesc_gp64);
+
+  /* Otherwise we don't have a useful guess.  */
+}
+
+static struct value *
+value_of_mips_user_reg (struct frame_info *frame, const void *baton)
+{
+  const int *reg_p = baton;
+  return value_of_register (*reg_p, frame);
 }
 
 static struct gdbarch *
@@ -5612,8 +4872,108 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   struct gdbarch_tdep *tdep;
   int elf_flags;
   enum mips_abi mips_abi, found_abi, wanted_abi;
-  int num_regs;
+  int i, num_regs;
   enum mips_fpu_type fpu_type;
+  struct tdesc_arch_data *tdesc_data = NULL;
+
+  /* Check any target description for validity.  */
+  if (tdesc_has_registers (info.target_desc))
+    {
+      static const char *const mips_gprs[] = {
+       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+       "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+       "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+       "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
+      };
+      static const char *const mips_fprs[] = {
+       "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",
+      };
+
+      const struct tdesc_feature *feature;
+      int valid_p;
+
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.mips.cpu");
+      if (feature == NULL)
+       return NULL;
+
+      tdesc_data = tdesc_data_alloc ();
+
+      valid_p = 1;
+      for (i = MIPS_ZERO_REGNUM; i <= MIPS_RA_REGNUM; i++)
+       valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
+                                           mips_gprs[i]);
+
+
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_LO_REGNUM, "lo");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_HI_REGNUM, "hi");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_PC_REGNUM, "pc");
+
+      if (!valid_p)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.mips.cp0");
+      if (feature == NULL)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      valid_p = 1;
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_BADVADDR_REGNUM,
+                                         "badvaddr");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_PS_REGNUM, "status");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_CAUSE_REGNUM, "cause");
+
+      if (!valid_p)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      /* FIXME drow/2007-05-17: The FPU should be optional.  The MIPS
+        backend is not prepared for that, though.  */
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.mips.fpu");
+      if (feature == NULL)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      valid_p = 1;
+      for (i = 0; i < 32; i++)
+       valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                           i + MIPS_EMBED_FP0_REGNUM,
+                                           mips_fprs[i]);
+
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_FP0_REGNUM + 32, "fcsr");
+      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                         MIPS_EMBED_FP0_REGNUM + 33, "fir");
+
+      if (!valid_p)
+       {
+         tdesc_data_cleanup (tdesc_data);
+         return NULL;
+       }
+
+      /* It would be nice to detect an attempt to use a 64-bit ABI
+        when only 32-bit registers are provided.  */
+    }
 
   /* First of all, extract the elf_flags, if available.  */
   if (info.abfd && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
@@ -5686,6 +5046,13 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
+  /* Default 64-bit objects to N64 instead of O32.  */
+  if (found_abi == MIPS_ABI_UNKNOWN
+      && info.abfd != NULL
+      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour
+      && elf_elfheader (info.abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+    found_abi = MIPS_ABI_N64;
+
   if (gdbarch_debug)
     fprintf_unfiltered (gdb_stdlog, "mips_gdbarch_init: found_abi = %d\n",
                        found_abi);
@@ -5742,6 +5109,20 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     fprintf_unfiltered (gdb_stdlog,
                        "mips_gdbarch_init: fpu_type = %d\n", fpu_type);
 
+  /* Check for blatant incompatibilities.  */
+
+  /* If we have only 32-bit registers, then we can't debug a 64-bit
+     ABI.  */
+  if (info.target_desc
+      && tdesc_property (info.target_desc, PROPERTY_GP32) != NULL
+      && mips_abi != MIPS_ABI_EABI32
+      && mips_abi != MIPS_ABI_O32)
+    {
+      if (tdesc_data != NULL)
+       tdesc_data_cleanup (tdesc_data);
+      return NULL;
+    }
+
   /* try to find a pre-existing architecture */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
@@ -5761,6 +5142,9 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* Be pedantic about which FPU is selected.  */
       if (gdbarch_tdep (arches->gdbarch)->mips_fpu_type != fpu_type)
        continue;
+
+      if (tdesc_data != NULL)
+       tdesc_data_cleanup (tdesc_data);
       return arches->gdbarch;
     }
 
@@ -5772,6 +5156,23 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->found_abi = found_abi;
   tdep->mips_abi = mips_abi;
   tdep->mips_fpu_type = fpu_type;
+  tdep->register_size_valid_p = 0;
+  tdep->register_size = 0;
+
+  if (info.target_desc)
+    {
+      /* Some useful properties can be inferred from the target.  */
+      if (tdesc_property (info.target_desc, PROPERTY_GP32) != NULL)
+       {
+         tdep->register_size_valid_p = 1;
+         tdep->register_size = 4;
+       }
+      else if (tdesc_property (info.target_desc, PROPERTY_GP64) != NULL)
+       {
+         tdep->register_size_valid_p = 1;
+         tdep->register_size = 8;
+       }
+    }
 
   /* Initially set everything according to the default ABI/ISA.  */
   set_gdbarch_short_bit (gdbarch, 16);
@@ -5791,7 +5192,20 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     const char **reg_names;
     struct mips_regnum *regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch,
                                                         struct mips_regnum);
-    if (info.osabi == GDB_OSABI_IRIX)
+    if (tdesc_has_registers (info.target_desc))
+      {
+       regnum->lo = MIPS_EMBED_LO_REGNUM;
+       regnum->hi = MIPS_EMBED_HI_REGNUM;
+       regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
+       regnum->cause = MIPS_EMBED_CAUSE_REGNUM;
+       regnum->pc = MIPS_EMBED_PC_REGNUM;
+       regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
+       regnum->fp_control_status = 70;
+       regnum->fp_implementation_revision = 71;
+       num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+       reg_names = NULL;
+      }
+    else if (info.osabi == GDB_OSABI_IRIX)
       {
        regnum->fp0 = 32;
        regnum->pc = 64;
@@ -5838,7 +5252,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     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_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);
@@ -5847,78 +5261,112 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       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_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_deprecated_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_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_deprecated_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_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_deprecated_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_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);
+      set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
       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_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);
+      set_gdbarch_long_double_format (gdbarch, floatformats_n32n64_long);
       break;
     default:
-      internal_error (__FILE__, __LINE__, "unknown ABI in switch");
+      internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
+    }
+
+  /* GCC creates a pseudo-section whose name specifies the size of
+     longs, since -mlong32 or -mlong64 may be used independent of
+     other options.  How those options affect pointer sizes is ABI and
+     architecture dependent, so use them to override the default sizes
+     set by the ABI.  This table shows the relationship between ABI,
+     -mlongXX, and size of pointers:
+
+     ABI               -mlongXX        ptr bits
+     ---               --------        --------
+     o32               32              32
+     o32               64              32
+     n32               32              32
+     n32               64              64
+     o64               32              32
+     o64               64              64
+     n64               32              32
+     n64               64              64
+     eabi32            32              32
+     eabi32            64              32
+     eabi64            32              32
+     eabi64            64              64
+
+    Note that for o32 and eabi32, pointers are always 32 bits
+    regardless of any -mlongXX option.  For all others, pointers and
+    longs are the same, as set by -mlongXX or set by defaults.
+ */
+
+  if (info.abfd != NULL)
+    {
+      int long_bit = 0;
+
+      bfd_map_over_sections (info.abfd, mips_find_long_section, &long_bit);
+      if (long_bit)
+       {
+         set_gdbarch_long_bit (gdbarch, long_bit);
+         switch (mips_abi)
+           {
+           case MIPS_ABI_O32:
+           case MIPS_ABI_EABI32:
+             break;
+           case MIPS_ABI_N32:
+           case MIPS_ABI_O64:
+           case MIPS_ABI_N64:
+           case MIPS_ABI_EABI64:
+             set_gdbarch_ptr_bit (gdbarch, long_bit);
+             break;
+           default:
+             internal_error (__FILE__, __LINE__, _("unknown ABI in switch"));
+           }
+       }
     }
 
   /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE
@@ -5944,7 +5392,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_read_pc (gdbarch, mips_read_pc);
   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.  */
@@ -5952,6 +5399,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Unwind the frame.  */
   set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc);
+  set_gdbarch_unwind_sp (gdbarch, mips_unwind_sp);
   set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id);
 
   /* Map debug register numbers onto internal register numbers.  */
@@ -5999,33 +5447,60 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
      is sitting on?  */
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
 
-  set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_stub);
+  set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_trampoline_code);
 
-  /* NOTE drow/2004-02-11: We overload the core solib trampoline code
-     to support MIPS16.  This is a bad thing.  Make sure not to do it
-     if we have an OS ABI that actually supports shared libraries, since
-     shared library support is more important.  If we have an OS someday
-     that supports both shared libraries and MIPS16, we'll have to find
-     a better place for these.  */
-  if (info.osabi == GDB_OSABI_UNKNOWN)
-    {
-      set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub);
-      set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
-    }
+  set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+
+  /* Virtual tables.  */
+  set_gdbarch_vbit_in_delta (gdbarch, 1);
+
+  mips_register_g_packet_guesses (gdbarch);
 
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  info.tdep_info = (void *) tdesc_data;
   gdbarch_init_osabi (info, gdbarch);
 
   /* Unwind the frame.  */
+  frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
   frame_unwind_append_sniffer (gdbarch, mips_stub_frame_sniffer);
-  frame_unwind_append_sniffer (gdbarch, mips_mdebug_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, dwarf2_frame_base_sniffer);
   frame_base_append_sniffer (gdbarch, mips_stub_frame_base_sniffer);
-  frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer);
   frame_base_append_sniffer (gdbarch, mips_insn16_frame_base_sniffer);
   frame_base_append_sniffer (gdbarch, mips_insn32_frame_base_sniffer);
 
+  if (tdesc_data)
+    {
+      set_tdesc_pseudo_register_type (gdbarch, mips_pseudo_register_type);
+      tdesc_use_registers (gdbarch, tdesc_data);
+
+      /* Override the normal target description methods to handle our
+        dual real and pseudo registers.  */
+      set_gdbarch_register_name (gdbarch, mips_register_name);
+      set_gdbarch_register_reggroup_p (gdbarch, mips_tdesc_register_reggroup_p);
+
+      num_regs = gdbarch_num_regs (gdbarch);
+      set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
+      set_gdbarch_pc_regnum (gdbarch, tdep->regnum->pc + num_regs);
+      set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
+    }
+
+  /* Add ABI-specific aliases for the registers.  */
+  if (mips_abi == MIPS_ABI_N32 || mips_abi == MIPS_ABI_N64)
+    for (i = 0; i < ARRAY_SIZE (mips_n32_n64_aliases); i++)
+      user_reg_add (gdbarch, mips_n32_n64_aliases[i].name,
+                   value_of_mips_user_reg, &mips_n32_n64_aliases[i].regnum);
+  else
+    for (i = 0; i < ARRAY_SIZE (mips_o32_aliases); i++)
+      user_reg_add (gdbarch, mips_o32_aliases[i].name,
+                   value_of_mips_user_reg, &mips_o32_aliases[i].regnum);
+
+  /* Add some other standard aliases.  */
+  for (i = 0; i < ARRAY_SIZE (mips_register_aliases); i++)
+    user_reg_add (gdbarch, mips_register_aliases[i].name,
+                 value_of_mips_user_reg, &mips_register_aliases[i].regnum);
+
   return gdbarch;
 }
 
@@ -6043,11 +5518,16 @@ mips_abi_update (char *ignore_args, int from_tty, struct cmd_list_element *c)
 /* Print out which MIPS ABI is in use.  */
 
 static void
-show_mips_abi (char *ignore_args, int from_tty)
+show_mips_abi (struct ui_file *file,
+              int from_tty,
+              struct cmd_list_element *ignored_cmd,
+              const char *ignored_value)
 {
   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");
+    fprintf_filtered
+      (file, 
+       "The MIPS ABI is unknown because the current architecture "
+       "is not MIPS.\n");
   else
     {
       enum mips_abi global_abi = global_mips_abi ();
@@ -6055,18 +5535,21 @@ 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",
+       fprintf_filtered
+         (file, 
+          "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",
+       fprintf_filtered
+         (file,
+          "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",
+         fprintf_filtered
+           (file,
+            "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]);
        }
     }
@@ -6080,7 +5563,7 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
     {
       int ef_mips_arch;
       int ef_mips_32bitmode;
-      /* determine the ISA */
+      /* Determine the ISA.  */
       switch (tdep->elf_flags & EF_MIPS_ARCH)
        {
        case E_MIPS_ARCH_1:
@@ -6099,7 +5582,7 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
          ef_mips_arch = 0;
          break;
        }
-      /* determine the size of a pointer */
+      /* Determine the size of a pointer.  */
       ef_mips_32bitmode = (tdep->elf_flags & EF_MIPS_32BITMODE);
       fprintf_unfiltered (file,
                          "mips_dump_tdep: tdep->elf_flags = 0x%x\n",
@@ -6133,161 +5616,6 @@ 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: mips_stack_argsize() = %d\n",
-                     mips_stack_argsize (current_gdbarch));
-  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: DEPRECATED_IGNORE_HELPER_CALL # %s\n",
-                     XSTRING (DEPRECATED_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_abi_regsize() = %d\n",
-                     mips_abi_regsize (current_gdbarch));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: PRID_REGNUM = %d\n", PRID_REGNUM);
-  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: 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)));
-#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);
 }
 
 extern initialize_file_ftype _initialize_mips_tdep;    /* -Wmissing-prototypes */
@@ -6301,7 +5629,7 @@ _initialize_mips_tdep (void)
   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");
+    internal_error (__FILE__, __LINE__, _("mips_abi_strings out of sync"));
 
   gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
 
@@ -6309,119 +5637,104 @@ _initialize_mips_tdep (void)
 
   /* Add root prefix command for all "set mips"/"show mips" commands */
   add_prefix_cmd ("mips", no_class, set_mips_command,
-                 "Various MIPS specific commands.",
+                 _("Various MIPS specific commands."),
                  &setmipscmdlist, "set mips ", 0, &setlist);
 
   add_prefix_cmd ("mips", no_class, show_mips_command,
-                 "Various MIPS specific commands.",
+                 _("Various MIPS specific commands."),
                  &showmipscmdlist, "show mips ", 0, &showlist);
 
-  /* Allow the user to override the saved register size. */
-  deprecated_add_show_from_set (add_set_enum_cmd ("saved-gpreg-size",
-                                                 class_obscure,
-                                                 size_enums,
-                                                 &mips_abi_regsize_string, "\
-Set 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);
-
-  /* Allow the user to override the argument stack size. */
-  deprecated_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\
-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);
-
   /* Allow the user to override the ABI. */
-  c = add_set_enum_cmd
-    ("abi", class_obscure, mips_abi_strings, &mips_abi_string,
-     "Set the ABI used by this program.\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);
-  set_cmd_sfunc (c, mips_abi_update);
-  add_cmd ("abi", class_obscure, show_mips_abi,
-          "Show ABI in use by MIPS target", &showmipscmdlist);
+  add_setshow_enum_cmd ("abi", class_obscure, mips_abi_strings,
+                       &mips_abi_string, _("\
+Set the MIPS ABI used by this program."), _("\
+Show the MIPS ABI used by this program."), _("\
+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"),
+                       mips_abi_update,
+                       show_mips_abi,
+                       &setmipscmdlist, &showmipscmdlist);
 
   /* Let the user turn off floating point and set the fence post for
      heuristic_proc_start.  */
 
   add_prefix_cmd ("mipsfpu", class_support, set_mipsfpu_command,
-                 "Set use of MIPS floating-point coprocessor.",
+                 _("Set use of MIPS floating-point coprocessor."),
                  &mipsfpulist, "set mipsfpu ", 0, &setlist);
   add_cmd ("single", class_support, set_mipsfpu_single_command,
-          "Select single-precision MIPS floating-point coprocessor.",
+          _("Select single-precision MIPS floating-point coprocessor."),
           &mipsfpulist);
   add_cmd ("double", class_support, set_mipsfpu_double_command,
-          "Select double-precision MIPS floating-point coprocessor.",
+          _("Select double-precision MIPS floating-point coprocessor."),
           &mipsfpulist);
   add_alias_cmd ("on", "double", class_support, 1, &mipsfpulist);
   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);
   add_cmd ("auto", class_support, set_mipsfpu_auto_command,
-          "Select MIPS floating-point coprocessor automatically.",
+          _("Select MIPS floating-point coprocessor automatically."),
           &mipsfpulist);
   add_cmd ("mipsfpu", class_support, show_mipsfpu_command,
-          "Show current use of MIPS floating-point coprocessor target.",
+          _("Show current use of MIPS floating-point coprocessor target."),
           &showlist);
 
   /* 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."), _("\
+Show the distance searched for the start of a function."), _("\
 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);
-  deprecated_add_show_from_set (c, &showlist);
+search.  The only need to set it is when debugging a stripped executable."),
+                           reinit_frame_cache_sfunc,
+                           NULL, /* FIXME: i18n: The distance searched for the start of a function is %s.  */
+                           &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.", "\
-Show zeroing of upper 32 bits of 64-bit addresses.", "\
+  add_setshow_auto_boolean_cmd ("mask-address", no_class,
+                               &mask_address_var, _("\
+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", "\
-Zerroing of upper 32 bits of 64-bit address is %s.",
-                               NULL, show_mask_address, &setmipscmdlist, &showmipscmdlist);
+allow GDB to determine the correct value."),
+                               NULL, show_mask_address,
+                               &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to control the size of 32 bit registers within the
      raw remote packet.  */
   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.", "\
+                          &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", "\
-Compatibility with 64-bit MIPS target that transfers 32-bit quantities is %s.",
- set_mips64_transfers_32bit_regs, NULL, &setlist, &showlist);
+64 bits for others.  Use \"off\" to disable compatibility mode"),
+                          set_mips64_transfers_32bit_regs,
+                          NULL, /* FIXME: i18n: Compatibility with 64-bit MIPS target that transfers 32-bit quantities is %s.  */
+                          &setlist, &showlist);
 
   /* Debug this files internals. */
-  deprecated_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."), _("\
+Show mips debugging."), _("\
+When non-zero, mips specific debugging is enabled."),
+                           NULL,
+                           NULL, /* FIXME: i18n: Mips debugging is currently %s.  */
+                           &setdebuglist, &showdebuglist);
 }
This page took 0.12906 seconds and 4 git commands to generate.