* rs6000-tdep.c (set_sim_regno, init_sim_regno_table,
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 3a80c06d5b0f2c8ee7840452d33f48523fa3ffaf..e02202cc93750c769305a83d196208c98cdbd0bb 100644 (file)
 #include "frame-unwind.h"
 #include "frame-base.h"
 #include "trad-frame.h"
+#include "infcall.h"
+#include "floatformat.h"
+
+static const struct objfile_data *mips_pdr_data;
 
 static void set_reg_offset (CORE_ADDR *saved_regs, int regnum, CORE_ADDR off);
 static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
@@ -105,8 +109,7 @@ static const char *size_enums[] = {
 };
 
 /* Some MIPS boards don't support floating point while others only
-   support single-precision floating-point operations.  See also
-   FP_REGISTER_DOUBLE. */
+   support single-precision floating-point operations.  */
 
 enum mips_fpu_type
 {
@@ -135,9 +138,6 @@ struct gdbarch_tdep
   enum mips_fpu_type mips_fpu_type;
   int mips_last_arg_regnum;
   int mips_last_fp_arg_regnum;
-  int mips_default_saved_regsize;
-  int mips_fp_register_double;
-  int mips_default_stack_argsize;
   int default_mask_address_p;
   /* Is the target using 64-bit raw integer registers but only
      storing a left-aligned 32-bit value in each?  */
@@ -150,6 +150,32 @@ struct gdbarch_tdep
   const char **mips_processor_reg_names;
 };
 
+static int
+n32n64_floatformat_always_valid (const struct floatformat *fmt,
+                                 const char *from)
+{
+  return 1;
+}
+
+/* FIXME: brobecker/2004-08-08: Long Double values are 128 bit long.
+   They are implemented as a pair of 64bit doubles where the high
+   part holds the result of the operation rounded to double, and
+   the low double holds the difference between the exact result and
+   the rounded result.  So "high" + "low" contains the result with
+   added precision.  Unfortunately, the floatformat structure used
+   by GDB is not powerful enough to describe this format.  As a temporary
+   measure, we define a 128bit floatformat that only uses the high part.
+   We lose a bit of precision but that's probably the best we can do
+   for now with the current infrastructure.  */
+
+static const struct floatformat floatformat_n32n64_long_double_big =
+{
+  floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
+  floatformat_intbit_no,
+  "floatformat_ieee_double_big",
+  n32n64_floatformat_always_valid
+};
+
 const struct mips_regnum *
 mips_regnum (struct gdbarch *gdbarch)
 {
@@ -231,7 +257,7 @@ mips_abi (struct gdbarch *gdbarch)
 }
 
 int
-mips_regsize (struct gdbarch *gdbarch)
+mips_isa_regsize (struct gdbarch *gdbarch)
 {
   return (gdbarch_bfd_arch_info (gdbarch)->bits_per_word
          / gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
@@ -239,16 +265,30 @@ mips_regsize (struct gdbarch *gdbarch)
 
 /* Return the currently configured (or set) saved register size. */
 
-static const char *mips_saved_regsize_string = size_auto;
+static const char *mips_abi_regsize_string = size_auto;
 
 static unsigned int
-mips_saved_regsize (struct gdbarch_tdep *tdep)
+mips_abi_regsize (struct gdbarch *gdbarch)
 {
-  if (mips_saved_regsize_string == size_auto)
-    return tdep->mips_default_saved_regsize;
-  else if (mips_saved_regsize_string == size_64)
+  if (mips_abi_regsize_string == size_auto)
+    switch (mips_abi (gdbarch))
+      {
+      case MIPS_ABI_EABI32:
+      case MIPS_ABI_O32:
+       return 4;
+      case MIPS_ABI_N32:
+      case MIPS_ABI_N64:
+      case MIPS_ABI_O64:
+      case MIPS_ABI_EABI64:
+       return 8;
+      case MIPS_ABI_UNKNOWN:
+      case MIPS_ABI_LAST:
+      default:
+       internal_error (__FILE__, __LINE__, "bad switch");
+      }
+  else if (mips_abi_regsize_string == size_64)
     return 8;
-  else                         /* if (mips_saved_regsize_string == size_32) */
+  else                         /* if (mips_abi_regsize_string == size_32) */
     return 4;
 }
 
@@ -361,22 +401,17 @@ mips2_fp_compat (void)
   return 0;
 }
 
-/* Indicate that the ABI makes use of double-precision registers
-   provided by the FPU (rather than combining pairs of registers to
-   form double-precision values).  See also MIPS_FPU_TYPE.  */
-#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
-
 /* The amount of space reserved on the stack for registers. This is
-   different to MIPS_SAVED_REGSIZE as it determines the alignment of
+   different to MIPS_ABI_REGSIZE as it determines the alignment of
    data allocated after the registers have run out. */
 
 static const char *mips_stack_argsize_string = size_auto;
 
 static unsigned int
-mips_stack_argsize (struct gdbarch_tdep *tdep)
+mips_stack_argsize (struct gdbarch *gdbarch)
 {
   if (mips_stack_argsize_string == size_auto)
-    return tdep->mips_default_stack_argsize;
+    return mips_abi_regsize (gdbarch);
   else if (mips_stack_argsize_string == size_64)
     return 8;
   else                         /* if (mips_stack_argsize_string == size_32) */
@@ -387,6 +422,8 @@ mips_stack_argsize (struct gdbarch_tdep *tdep)
 
 static mips_extra_func_info_t heuristic_proc_desc (CORE_ADDR, CORE_ADDR,
                                                   struct frame_info *, int);
+static mips_extra_func_info_t non_heuristic_proc_desc (CORE_ADDR pc,
+                                                      CORE_ADDR *addrptr);
 
 static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
@@ -692,16 +729,16 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
       && (regnum % NUM_REGS) < mips_regnum (current_gdbarch)->fp0 + 32)
     {
       /* The floating-point registers raw, or cooked, always match
-         mips_regsize(), and also map 1:1, byte for byte.  */
+         mips_isa_regsize(), and also map 1:1, byte for byte.  */
       switch (gdbarch_byte_order (gdbarch))
        {
        case BFD_ENDIAN_BIG:
-         if (mips_regsize (gdbarch) == 4)
+         if (mips_isa_regsize (gdbarch) == 4)
            return builtin_type_ieee_single_big;
          else
            return builtin_type_ieee_double_big;
        case BFD_ENDIAN_LITTLE:
-         if (mips_regsize (gdbarch) == 4)
+         if (mips_isa_regsize (gdbarch) == 4)
            return builtin_type_ieee_single_little;
          else
            return builtin_type_ieee_double_little;
@@ -710,24 +747,38 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
          internal_error (__FILE__, __LINE__, "bad switch");
        }
     }
-  else if (regnum >=
-          (NUM_REGS + mips_regnum (current_gdbarch)->fp_control_status)
-          && regnum <= NUM_REGS + LAST_EMBED_REGNUM)
-    /* The pseudo/cooked view of the embedded registers is always
-       32-bit.  The raw view is handled below.  */
-    return builtin_type_int32;
-  else if (regnum >= NUM_REGS && mips_regsize (gdbarch)
-          && gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
-    /* The target, while using a 64-bit register buffer, is only
-       transfering 32-bits of each integer register.  Reflect this in
-       the cooked/pseudo register value.  */
-    return builtin_type_int32;
-  else if (mips_regsize (gdbarch) == 8)
-    /* 64-bit ISA.  */
-    return builtin_type_int64;
+  else if (regnum < NUM_REGS)
+    {
+      /* The raw or ISA registers.  These are all sized according to
+        the ISA regsize.  */
+      if (mips_isa_regsize (gdbarch) == 4)
+       return builtin_type_int32;
+      else
+       return builtin_type_int64;
+    }
   else
-    /* 32-bit ISA.  */
-    return builtin_type_int32;
+    {
+      /* The cooked or ABI registers.  These are sized according to
+        the ABI (with a few complications).  */
+      if (regnum >= (NUM_REGS
+                    + mips_regnum (current_gdbarch)->fp_control_status)
+         && regnum <= NUM_REGS + LAST_EMBED_REGNUM)
+       /* The pseudo/cooked view of the embedded registers is always
+          32-bit.  The raw view is handled below.  */
+       return builtin_type_int32;
+      else if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
+       /* The target, while possibly using a 64-bit register buffer,
+          is only transfering 32-bits of each integer register.
+          Reflect this in the cooked/pseudo (ABI) register value.  */
+       return builtin_type_int32;
+      else if (mips_abi_regsize (gdbarch) == 4)
+       /* The ABI is restricted to 32-bit registers (the ISA could be
+          32- or 64-bit).  */
+       return builtin_type_int32;
+      else
+       /* 64-bit ABI.  */
+       return builtin_type_int64;
+    }
 }
 
 /* TARGET_READ_SP -- Remove useless bits from the stack pointer.  */
@@ -735,7 +786,7 @@ mips_register_type (struct gdbarch *gdbarch, int regnum)
 static CORE_ADDR
 mips_read_sp (void)
 {
-  return read_signed_register (SP_REGNUM);
+  return read_signed_register (MIPS_SP_REGNUM);
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
@@ -803,7 +854,7 @@ pc_is_mips16 (bfd_vma memaddr)
     return 0;
 }
 
-/* MIPS believes that the PC has a sign extended value.  Perhaphs the
+/* MIPS believes that the PC has a sign extended value.  Perhaps the
    all registers should be sign extended for simplicity? */
 
 static CORE_ADDR
@@ -827,7 +878,7 @@ 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 + SP_REGNUM),
+  return frame_id_build (frame_unwind_register_signed (next_frame, NUM_REGS + MIPS_SP_REGNUM),
                         frame_pc_unwind (next_frame));
 }
 
@@ -858,7 +909,7 @@ after_prologue (CORE_ADDR pc, mips_extra_func_info_t proc_desc)
     {
       /* If function is frameless, then we need to do it the hard way.  I
          strongly suspect that frameless always means prologueless... */
-      if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+      if (PROC_FRAME_REG (proc_desc) == MIPS_SP_REGNUM
          && PROC_FRAME_OFFSET (proc_desc) == 0)
        return 0;
     }
@@ -951,7 +1002,7 @@ mips_fetch_instruction (CORE_ADDR addr)
     }
   else
     instlen = MIPS_INSTLEN;
-  status = read_memory_nobpt (addr, buf, instlen);
+  status = deprecated_read_memory_nobpt (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
@@ -966,7 +1017,7 @@ mips16_fetch_instruction (CORE_ADDR addr)
 
   instlen = MIPS16_INSTLEN;
   addr = unmake_mips16_addr (addr);
-  status = read_memory_nobpt (addr, buf, instlen);
+  status = deprecated_read_memory_nobpt (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
@@ -979,7 +1030,7 @@ mips32_fetch_instruction (CORE_ADDR addr)
   int instlen;
   int status;
   instlen = MIPS_INSTLEN;
-  status = read_memory_nobpt (addr, buf, instlen);
+  status = deprecated_read_memory_nobpt (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
   return extract_unsigned_integer (buf, instlen);
@@ -1451,39 +1502,568 @@ extended_mips16_next_pc (CORE_ADDR pc,
        break;
       }
     }
-  return pc;
+  return pc;
+}
+
+static CORE_ADDR
+mips16_next_pc (CORE_ADDR pc)
+{
+  unsigned int insn = fetch_mips_16 (pc);
+  return extended_mips16_next_pc (pc, 0, insn);
+}
+
+/* The mips_next_pc function supports single_step when the remote
+   target monitor or stub is not developed enough to do a single_step.
+   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
+mips_next_pc (CORE_ADDR pc)
+{
+  if (pc & 0x01)
+    return mips16_next_pc (pc);
+  else
+    return mips32_next_pc (pc);
+}
+
+struct mips_frame_cache
+{
+  CORE_ADDR base;
+  struct trad_frame_saved_reg *saved_regs;
+};
+
+
+static struct mips_frame_cache *
+mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  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 = find_proc_desc (frame_pc_unwind (next_frame), next_frame, 1);
+  if (proc_desc == NULL)
+    /* I'm not sure how/whether this can happen.  Normally when we
+       can't find a proc_desc, we "synthesize" one using
+       heuristic_proc_desc and set the saved_regs right away.  */
+    return cache;
+
+  /* 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));
+
+  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);
+  
+  /* 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 (frame_pc_unwind (next_frame), PROC_LOW_ADDR (proc_desc))
+      /* 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)
+    {
+      /* We need to figure out whether the registers that the
+         proc_desc claims are saved have been saved yet.  */
+
+      CORE_ADDR addr;
+
+      /* Bitmasks; set if we have found a save for the register.  */
+      unsigned long gen_save_found = 0;
+      unsigned long float_save_found = 0;
+      int mips16;
+
+      /* If the address is odd, assume this is MIPS16 code.  */
+      addr = PROC_LOW_ADDR (proc_desc);
+      mips16 = pc_is_mips16 (addr);
+
+      /* Scan through this function's instructions preceding the
+         current PC, and look for those that save registers.  */
+      while (addr < frame_pc_unwind (next_frame))
+       {
+         if (mips16)
+           {
+             mips16_decode_reg_save (mips16_fetch_instruction (addr),
+                                     &gen_save_found);
+             addr += MIPS16_INSTLEN;
+           }
+         else
+           {
+             mips32_decode_reg_save (mips32_fetch_instruction (addr),
+                                     &gen_save_found, &float_save_found);
+             addr += MIPS_INSTLEN;
+           }
+       }
+      gen_mask = gen_save_found;
+      float_mask = float_save_found;
+    }
+
+  /* Fill in the offsets for the registers which gen_mask says were
+     saved.  */
+  {
+    CORE_ADDR reg_position = (cache->base
+                             + PROC_REG_OFFSET (proc_desc));
+    int ireg;
+    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);
+       }
+  }
+
+  /* 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)))
+    {
+      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);
+           }
+       }
+    }
+
+  /* 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);
+}
+
+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);
+}
+
+static const struct frame_unwind mips_mdebug_frame_unwind =
+{
+  NORMAL_FRAME,
+  mips_mdebug_frame_this_id,
+  mips_mdebug_frame_prev_register
+};
+
+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;
+
+  /* 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.  */
+
+  proc_desc = non_heuristic_proc_desc (pc, &startaddr);
+  if (proc_desc == NULL)
+    return NULL;
+
+  /* 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;
+
+  return NULL;
+}
+
+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;
+}
+
+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
+};
+
+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;
+}
+
+/* Heuristic unwinder for 16-bit MIPS instruction set (aka MIPS16).
+   Procedures that use the 32-bit instruction set are handled by the
+   mips_insn32 unwinder.  */
+
+static struct mips_frame_cache *
+mips_insn16_frame_cache (struct frame_info *next_frame, void **this_cache)
+{
+  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 = find_proc_desc (frame_pc_unwind (next_frame), next_frame, 1);
+  if (proc_desc == NULL)
+    /* I'm not sure how/whether this can happen.  Normally when we
+       can't find a proc_desc, we "synthesize" one using
+       heuristic_proc_desc and set the saved_regs right away.  */
+    return cache;
+
+  /* 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));
+
+  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);
+  
+  /* 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 (frame_pc_unwind (next_frame), PROC_LOW_ADDR (proc_desc))
+      /* 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)
+    {
+      /* We need to figure out whether the registers that the
+         proc_desc claims are saved have been saved yet.  */
+
+      CORE_ADDR addr;
+
+      /* Bitmasks; set if we have found a save for the register.  */
+      unsigned long gen_save_found = 0;
+      unsigned long float_save_found = 0;
+      int mips16;
+
+      /* If the address is odd, assume this is MIPS16 code.  */
+      addr = PROC_LOW_ADDR (proc_desc);
+      mips16 = pc_is_mips16 (addr);
+
+      /* Scan through this function's instructions preceding the
+         current PC, and look for those that save registers.  */
+      while (addr < frame_pc_unwind (next_frame))
+       {
+         if (mips16)
+           {
+             mips16_decode_reg_save (mips16_fetch_instruction (addr),
+                                     &gen_save_found);
+             addr += MIPS16_INSTLEN;
+           }
+         else
+           {
+             mips32_decode_reg_save (mips32_fetch_instruction (addr),
+                                     &gen_save_found, &float_save_found);
+             addr += MIPS_INSTLEN;
+           }
+       }
+      gen_mask = gen_save_found;
+      float_mask = float_save_found;
+    }
+
+  /* Fill in the offsets for the registers which gen_mask says were
+     saved.  */
+  {
+    CORE_ADDR reg_position = (cache->base
+                             + PROC_REG_OFFSET (proc_desc));
+    int ireg;
+    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);
+       }
+  }
+
+  /* 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)))
+    {
+      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);
+           }
+       }
+    }
+
+  /* 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);
 }
 
-static CORE_ADDR
-mips16_next_pc (CORE_ADDR pc)
+static void
+mips_insn16_frame_this_id (struct frame_info *next_frame, void **this_cache,
+                          struct frame_id *this_id)
 {
-  unsigned int insn = fetch_mips_16 (pc);
-  return extended_mips16_next_pc (pc, 0, insn);
+  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));
 }
 
-/* The mips_next_pc function supports single_step when the remote
-   target monitor or stub is not developed enough to do a single_step.
-   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
-mips_next_pc (CORE_ADDR pc)
+static void
+mips_insn16_frame_prev_register (struct frame_info *next_frame,
+                                void **this_cache,
+                                int regnum, int *optimizedp,
+                                enum lval_type *lvalp, CORE_ADDR *addrp,
+                                int *realnump, void *valuep)
 {
-  if (pc & 0x01)
-    return mips16_next_pc (pc);
-  else
-    return mips32_next_pc (pc);
+  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+                                                          this_cache);
+  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
 }
 
-struct mips_frame_cache
+static const struct frame_unwind mips_insn16_frame_unwind =
 {
-  CORE_ADDR base;
-  struct trad_frame_saved_reg *saved_regs;
+  NORMAL_FRAME,
+  mips_insn16_frame_this_id,
+  mips_insn16_frame_prev_register
+};
+
+static const struct frame_unwind *
+mips_insn16_frame_sniffer (struct frame_info *next_frame)
+{
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  if (pc_is_mips16 (pc))
+    return &mips_insn16_frame_unwind;
+  return NULL;
+}
+
+static CORE_ADDR
+mips_insn16_frame_base_address (struct frame_info *next_frame,
+                               void **this_cache)
+{
+  struct mips_frame_cache *info = mips_insn16_frame_cache (next_frame,
+                                                          this_cache);
+  return info->base;
+}
+
+static const struct frame_base mips_insn16_frame_base =
+{
+  &mips_insn16_frame_unwind,
+  mips_insn16_frame_base_address,
+  mips_insn16_frame_base_address,
+  mips_insn16_frame_base_address
 };
 
+static const struct frame_base *
+mips_insn16_frame_base_sniffer (struct frame_info *next_frame)
+{
+  if (mips_insn16_frame_sniffer (next_frame) != NULL)
+    return &mips_insn16_frame_base;
+  else
+    return NULL;
+}
+
+/* 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_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
+mips_insn32_frame_cache (struct frame_info *next_frame, void **this_cache)
 {
   mips_extra_func_info_t proc_desc;
   struct mips_frame_cache *cache;
@@ -1572,7 +2152,7 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
       if (gen_mask & 0x80000000)
        {
          cache->saved_regs[NUM_REGS + ireg].addr = reg_position;
-         reg_position -= mips_saved_regsize (tdep);
+         reg_position -= mips_abi_regsize (gdbarch);
        }
   }
 
@@ -1593,7 +2173,7 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
          CORE_ADDR reg_position = (cache->base
                                    + PROC_REG_OFFSET (proc_desc));
          if (inst & 0x20)
-           reg_position -= mips_saved_regsize (tdep);
+           reg_position -= mips_abi_regsize (gdbarch);
 
          /* Check if the s0 and s1 registers were pushed on the
             stack.  */
@@ -1602,7 +2182,7 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
          for (reg = 16; reg < sreg_count + 16; reg++)
            {
              cache->saved_regs[NUM_REGS + reg].addr = reg_position;
-             reg_position -= mips_saved_regsize (tdep);
+             reg_position -= mips_abi_regsize (gdbarch);
            }
        }
     }
@@ -1618,7 +2198,7 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
     for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1)
       if (float_mask & 0x80000000)
        {
-         if (mips_saved_regsize (tdep) == 4
+         if (mips_abi_regsize (gdbarch) == 4
              && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
            {
              /* On a big endian 32 bit ABI, floating point registers
@@ -1645,15 +2225,15 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
                 loop).  */
              if ((ireg & 1))
                cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg]
-                 .addr = reg_position - mips_saved_regsize (tdep);
+                 .addr = reg_position - mips_abi_regsize (gdbarch);
              else
                cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->fp0 + ireg]
-                 .addr = reg_position + mips_saved_regsize (tdep);
+                 .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_saved_regsize (tdep);
+         reg_position -= mips_abi_regsize (gdbarch);
        }
 
     cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
@@ -1661,66 +2241,168 @@ mips_mdebug_frame_cache (struct frame_info *next_frame, void **this_cache)
   }
 
   /* SP_REGNUM, contains the value and not the address.  */
-  trad_frame_set_value (cache->saved_regs, NUM_REGS + SP_REGNUM, cache->base);
+  trad_frame_set_value (cache->saved_regs, NUM_REGS + MIPS_SP_REGNUM, cache->base);
 
   return (*this_cache);
 }
 
 static void
-mips_mdebug_frame_this_id (struct frame_info *next_frame, void **this_cache,
+mips_insn32_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,
+  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_mdebug_frame_prev_register (struct frame_info *next_frame,
+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_mdebug_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
                                                           this_cache);
-  trad_frame_prev_register (next_frame, info->saved_regs, regnum,
-                           optimizedp, lvalp, addrp, realnump, valuep);
+  trad_frame_get_prev_register (next_frame, info->saved_regs, regnum,
+                               optimizedp, lvalp, addrp, realnump, valuep);
 }
 
-static const struct frame_unwind mips_mdebug_frame_unwind =
+static const struct frame_unwind mips_insn32_frame_unwind =
 {
   NORMAL_FRAME,
-  mips_mdebug_frame_this_id,
-  mips_mdebug_frame_prev_register
+  mips_insn32_frame_this_id,
+  mips_insn32_frame_prev_register
 };
 
 static const struct frame_unwind *
-mips_mdebug_frame_sniffer (struct frame_info *next_frame)
+mips_insn32_frame_sniffer (struct frame_info *next_frame)
 {
-  return &mips_mdebug_frame_unwind;
+  CORE_ADDR pc = frame_pc_unwind (next_frame);
+  if (! pc_is_mips16 (pc))
+    return &mips_insn32_frame_unwind;
+  return NULL;
 }
 
 static CORE_ADDR
-mips_mdebug_frame_base_address (struct frame_info *next_frame,
+mips_insn32_frame_base_address (struct frame_info *next_frame,
                                void **this_cache)
 {
-  struct mips_frame_cache *info = mips_mdebug_frame_cache (next_frame,
+  struct mips_frame_cache *info = mips_insn32_frame_cache (next_frame,
                                                           this_cache);
   return info->base;
 }
 
-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
+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_mdebug_frame_base_sniffer (struct frame_info *next_frame)
+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, 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, 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 =
 {
-  return &mips_mdebug_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
@@ -1734,8 +2416,8 @@ read_next_frame_reg (struct frame_info *fi, int regno)
       regcache_cooked_read_signed (current_regcache, regno, &val);
       return val;
     }
-  else if ((regno % NUM_REGS) == SP_REGNUM)
-    /* The SP_REGNUM is special, its value is stored in saved_regs.
+  else if ((regno % NUM_REGS) == MIPS_SP_REGNUM)
+    /* MIPS_SP_REGNUM is special, its value is stored in saved_regs.
        In fact, it is so special that it can even only be fetched
        using a raw register number!  Once this code as been converted
        to frame-unwind the problem goes away.  */
@@ -1884,9 +2566,8 @@ heuristic_proc_start (CORE_ADDR pc)
          {
            static int blurb_printed = 0;
 
-           warning
-             ("Warning: GDB can't find the start of the function at 0x%s.",
-              paddr_nz (pc));
+           warning ("GDB can't find the start of the function at 0x%s.",
+                    paddr_nz (pc));
 
            if (!blurb_printed)
              {
@@ -2098,7 +2779,7 @@ mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
        {
          PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
          set_reg_offset (temp_saved_regs, reg, sp + offset);
-         offset += mips_saved_regsize (tdep);
+         offset += mips_abi_regsize (current_gdbarch);
        }
 
       /* Check if the ra register was pushed on the stack.  */
@@ -2107,7 +2788,7 @@ mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
        {
          PROC_REG_MASK (&temp_proc_desc) |= 1 << RA_REGNUM;
          set_reg_offset (temp_saved_regs, RA_REGNUM, sp + offset);
-         offset -= mips_saved_regsize (tdep);
+         offset -= mips_abi_regsize (current_gdbarch);
        }
 
       /* Check if the s0 and s1 registers were pushed on the stack.  */
@@ -2115,7 +2796,7 @@ mips16_heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
        {
          PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
          set_reg_offset (temp_saved_regs, reg, sp + offset);
-         offset -= mips_saved_regsize (tdep);
+         offset -= mips_abi_regsize (current_gdbarch);
        }
     }
 }
@@ -2163,19 +2844,17 @@ restart:
        }
       else if ((high_word & 0xFFE0) == 0xffa0) /* sd reg,offset($sp) */
        {
-         /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and $ra,
-            but the register size used is only 32 bits. Make the address
-            for the saved register point to the lower 32 bits.  */
+         /* Irix 6.2 N32 ABI uses sd instructions for saving $gp and
+            $ra.  */
          PROC_REG_MASK (&temp_proc_desc) |= 1 << reg;
-         set_reg_offset (temp_saved_regs, reg,
-                         sp + low_word + 8 - mips_regsize (current_gdbarch));
+         set_reg_offset (temp_saved_regs, reg, sp + low_word);
        }
       else if (high_word == 0x27be)    /* addiu $30,$sp,size */
        {
          /* Old gcc frame, r30 is virtual frame pointer.  */
          if ((long) low_word != PROC_FRAME_OFFSET (&temp_proc_desc))
            frame_addr = sp + low_word;
-         else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+         else if (PROC_FRAME_REG (&temp_proc_desc) == MIPS_SP_REGNUM)
            {
              unsigned alloca_adjust;
              PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2198,7 +2877,7 @@ restart:
       else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
        {
          /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */
-         if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+         if (PROC_FRAME_REG (&temp_proc_desc) == MIPS_SP_REGNUM)
            {
              unsigned alloca_adjust;
              PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2230,7 +2909,7 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   CORE_ADDR sp;
 
   if (cur_frame)
-    sp = read_next_frame_reg (next_frame, NUM_REGS + SP_REGNUM);
+    sp = read_next_frame_reg (next_frame, NUM_REGS + MIPS_SP_REGNUM);
   else
     sp = 0;
 
@@ -2240,7 +2919,7 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
   memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
   PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
-  PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
+  PROC_FRAME_REG (&temp_proc_desc) = MIPS_SP_REGNUM;
   PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
 
   if (start_pc + 200 < limit_pc)
@@ -2286,9 +2965,6 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
   struct obj_section *sec;
   struct mips_objfile_private *priv;
 
-  if (DEPRECATED_PC_IN_CALL_DUMMY (pc, 0, 0))
-    return NULL;
-
   find_pc_partial_function (pc, NULL, &startaddr, NULL);
   if (addrptr)
     *addrptr = startaddr;
@@ -2298,7 +2974,7 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
   sec = find_pc_section (pc);
   if (sec != NULL)
     {
-      priv = (struct mips_objfile_private *) sec->objfile->obj_private;
+      priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data);
 
       /* Search the ".pdr" section generated by GAS.  This includes most of
          the information normally found in ECOFF PDRs.  */
@@ -2316,7 +2992,7 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
          priv = obstack_alloc (&sec->objfile->objfile_obstack,
                                sizeof (struct mips_objfile_private));
          priv->size = 0;
-         sec->objfile->obj_private = priv;
+         set_objfile_data (sec->objfile, mips_pdr_data, priv);
        }
       else if (priv == NULL)
        {
@@ -2344,7 +3020,7 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
          else
            priv->size = 0;
 
-         sec->objfile->obj_private = priv;
+         set_objfile_data (sec->objfile, mips_pdr_data, priv);
        }
       the_bfd = NULL;
 
@@ -2352,38 +3028,70 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
        {
          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
            {
-             CORE_ADDR pdr_pc;
-
              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));
-             if (pdr_pc == startaddr)
-               break;
-             if (pdr_pc > startaddr)
+
+             if (pdr_pc > pc)
                high = mid;
              else
                low = mid + 1;
            }
          while (low != high);
 
-         if (low != high)
+         /* 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));
+           }
+
+         /* 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) = startaddr;
+             PROC_LOW_ADDR (proc_desc) = pdr_pc;
 
              /* Only used for dummy frames.  */
              PROC_HIGH_ADDR (proc_desc) = 0;
@@ -2600,10 +3308,10 @@ return_value_location (struct type *valtype,
       && ((MIPS_FPU_TYPE == MIPS_FPU_DOUBLE && (len == 4 || len == 8))
          || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE && len == 4)))
     {
-      if (!FP_REGISTER_DOUBLE && len == 8)
+      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. */
+            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
@@ -2641,22 +3349,22 @@ return_value_location (struct type *valtype,
       lo->reg = regnum + 0;
       hi->reg = regnum + 1;
       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-         && len < mips_saved_regsize (tdep))
+         && len < mips_abi_regsize (current_gdbarch))
        {
          /* "un-left-justify" the value in the low register */
-         lo->reg_offset = mips_saved_regsize (tdep) - len;
+         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_saved_regsize (tdep)  /* odd-size structs */
-              && len < mips_saved_regsize (tdep) * 2
+      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_saved_regsize (tdep) - len;
-         lo->len = mips_saved_regsize (tdep) - lo->reg_offset;
+         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;
        }
@@ -2665,10 +3373,10 @@ return_value_location (struct type *valtype,
          /* Only perform a partial copy of the second register. */
          lo->reg_offset = 0;
          hi->reg_offset = 0;
-         if (len > mips_saved_regsize (tdep))
+         if (len > mips_abi_regsize (current_gdbarch))
            {
-             lo->len = mips_saved_regsize (tdep);
-             hi->len = len - mips_saved_regsize (tdep);
+             lo->len = mips_abi_regsize (current_gdbarch);
+             hi->len = len - mips_abi_regsize (current_gdbarch);
            }
          else
            {
@@ -2678,7 +3386,7 @@ return_value_location (struct type *valtype,
        }
       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && register_size (current_gdbarch, regnum) == 8
-         && mips_saved_regsize (tdep) == 4)
+         && mips_abi_regsize (current_gdbarch) == 4)
        {
          /* Account for the fact that only the least-signficant part
             of the register is being used */
@@ -2696,7 +3404,7 @@ static int
 mips_eabi_use_struct_convention (int gcc_p, struct type *type)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
-  return (TYPE_LENGTH (type) > 2 * mips_saved_regsize (tdep));
+  return (TYPE_LENGTH (type) > 2 * mips_abi_regsize (current_gdbarch));
 }
 
 /* Should call_function pass struct by reference? 
@@ -2711,13 +3419,13 @@ mips_eabi_reg_struct_has_addr (int gcc_p, struct type *type)
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
 
   if (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION)
-    return (len > mips_saved_regsize (tdep));
+    return (len > mips_abi_regsize (current_gdbarch));
 
   return 0;
 }
 
 static CORE_ADDR
-mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                           struct regcache *regcache, CORE_ADDR bp_addr,
                           int nargs, struct value **args, CORE_ADDR sp,
                           int struct_return, CORE_ADDR struct_addr)
@@ -2728,6 +3436,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
@@ -2751,7 +3460,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
      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 (tdep));
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -2792,13 +3501,13 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
       /* The EABI passes structures that do not fit in a register by
          reference.  */
-      if (len > mips_saved_regsize (tdep)
+      if (len > mips_abi_regsize (gdbarch)
          && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
-         store_unsigned_integer (valbuf, mips_saved_regsize (tdep),
+         store_unsigned_integer (valbuf, mips_abi_regsize (gdbarch),
                                  VALUE_ADDRESS (arg));
          typecode = TYPE_CODE_PTR;
-         len = mips_saved_regsize (tdep);
+         len = mips_abi_regsize (gdbarch);
          val = valbuf;
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " push");
@@ -2811,7 +3520,8 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
          up before the check to see if there are any FP registers
          left.  Non MIPS_EABI targets also pass the FP in the integer
          registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE && fp_register_arg_p (typecode, arg_type))
+      if (mips_abi_regsize (gdbarch) < 8
+         && fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
            float_argreg++;
@@ -2832,7 +3542,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (!FP_REGISTER_DOUBLE && len == 8)
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
            {
              int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
@@ -2870,12 +3580,12 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
 
          /* Note: Floating-point values that didn't fit into an FP
             register are only written to memory.  */
@@ -2883,8 +3593,8 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
            {
              /* Remember if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -2902,16 +3612,16 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
                              || typecode == TYPE_CODE_FLT) && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                      else if ((typecode == TYPE_CODE_STRUCT
                                || typecode == TYPE_CODE_UNION)
                               && (TYPE_LENGTH (arg_type)
-                                  < mips_stack_argsize (tdep)))
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                                  < mips_stack_argsize (gdbarch)))
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -2953,7 +3663,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
                                      phex (regval,
-                                           mips_saved_regsize (tdep)));
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
                }
@@ -2969,14 +3679,14 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
              if (stack_used_p)
                stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (tdep));
+                                         mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
@@ -3034,7 +3744,7 @@ mips_eabi_store_return_value (struct type *valtype, char *valbuf)
 /* N32/N64 ABI stuff.  */
 
 static CORE_ADDR
-mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                             struct regcache *regcache, CORE_ADDR bp_addr,
                             int nargs, struct value **args, CORE_ADDR sp,
                             int struct_return, CORE_ADDR struct_addr)
@@ -3045,6 +3755,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
@@ -3066,7 +3777,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
     len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])),
-                    mips_stack_argsize (tdep));
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3131,20 +3842,20 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
          /* 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.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3162,11 +3873,11 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
                              || typecode == TYPE_CODE_FLT) && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -3215,10 +3926,10 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
                     cagney/2001-07-23: gdb/179: Also, GCC, when
                     outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
+                    mips_abi_regsize(), generates a left shift as
                     part of storing the argument in a register a
                     register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
+                    sizeof (struct) >= mips_abi_regsize()).  Since
                     it is quite possible that this is GCC
                     contradicting the LE/O32 ABI, GDB has not been
                     adjusted to accommodate this.  Either someone
@@ -3228,17 +3939,17 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     accordingly.  */
 
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
+                     && partial_len < mips_abi_regsize (gdbarch)
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
                                TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
                                      phex (regval,
-                                           mips_saved_regsize (tdep)));
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
                }
@@ -3254,14 +3965,14 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
              if (stack_used_p)
                stack_offset += align_up (partial_len,
-                                         mips_stack_argsize (tdep));
+                                         mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
@@ -3276,7 +3987,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
   if (TYPE_CODE (type) == TYPE_CODE_STRUCT
       || TYPE_CODE (type) == TYPE_CODE_UNION
       || TYPE_CODE (type) == TYPE_CODE_ARRAY
-      || TYPE_LENGTH (type) > 2 * mips_saved_regsize (tdep))
+      || TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
     return RETURN_VALUE_STRUCT_CONVENTION;
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
           && tdep->mips_fpu_type != MIPS_FPU_NONE)
@@ -3372,7 +4083,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch,
 /* O32 ABI stuff.  */
 
 static CORE_ADDR
-mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                          struct regcache *regcache, CORE_ADDR bp_addr,
                          int nargs, struct value **args, CORE_ADDR sp,
                          int struct_return, CORE_ADDR struct_addr)
@@ -3383,6 +4094,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
@@ -3404,7 +4116,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
     len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])),
-                    mips_stack_argsize (tdep));
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3424,7 +4136,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                            "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 (tdep);
+      stack_offset += mips_stack_argsize (gdbarch);
     }
 
   /* Now load as many as possible of the first arguments into
@@ -3450,7 +4162,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
          up before the check to see if there are any FP registers
          left.  O32/O64 targets also pass the FP in the integer
          registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE && fp_register_arg_p (typecode, arg_type))
+      if (mips_abi_regsize (gdbarch) < 8
+         && fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
            float_argreg++;
@@ -3469,7 +4182,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (!FP_REGISTER_DOUBLE && len == 8)
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
            {
              int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
@@ -3516,10 +4229,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                    argreg, phex (regval, len));
              write_register (argreg, regval);
-             argreg += FP_REGISTER_DOUBLE ? 1 : 2;
+             argreg += (mips_abi_regsize (gdbarch) == 8) ? 1 : 2;
            }
          /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (tdep));
+         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
        }
       else
        {
@@ -3527,15 +4240,15 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
          /* Structures should be aligned to eight bytes (even arg registers)
             on MIPS_ABI_O32, if their first member has double precision.  */
-         if (mips_saved_regsize (tdep) < 8
+         if (mips_abi_regsize (gdbarch) < 8
              && mips_type_needs_double_align (arg_type))
            {
              if ((argreg & 1))
@@ -3547,8 +4260,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
            {
              /* Remember if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -3566,11 +4279,11 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
                              || typecode == TYPE_CODE_FLT) && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -3607,7 +4320,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                {
                  LONGEST regval = extract_signed_integer (val, partial_len);
                  /* Value may need to be sign extended, because
-                    mips_regsize() != mips_saved_regsize().  */
+                    mips_isa_regsize() != mips_abi_regsize().  */
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -3622,10 +4335,10 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
                     cagney/2001-07-23: gdb/179: Also, GCC, when
                     outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
+                    mips_abi_regsize(), generates a left shift as
                     part of storing the argument in a register a
                     register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
+                    sizeof (struct) >= mips_abi_regsize()).  Since
                     it is quite possible that this is GCC
                     contradicting the LE/O32 ABI, GDB has not been
                     adjusted to accommodate this.  Either someone
@@ -3634,19 +4347,19 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     identified as such and GDB gets tweaked
                     accordingly.  */
 
-                 if (mips_saved_regsize (tdep) < 8
+                 if (mips_abi_regsize (gdbarch) < 8
                      && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
+                     && partial_len < mips_abi_regsize (gdbarch)
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
                                TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
                                      phex (regval,
-                                           mips_saved_regsize (tdep)));
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
 
@@ -3667,14 +4380,14 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 always allocated.  */
 
              stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (tdep));
+                                       mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
@@ -3804,9 +4517,9 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
       int regnum;
       for (offset = 0, regnum = V0_REGNUM;
           offset < TYPE_LENGTH (type);
-          offset += mips_stack_argsize (tdep), regnum++)
+          offset += mips_stack_argsize (gdbarch), regnum++)
        {
-         int xfer = mips_stack_argsize (tdep);
+         int xfer = mips_stack_argsize (gdbarch);
          if (offset + xfer > TYPE_LENGTH (type))
            xfer = TYPE_LENGTH (type) - offset;
          if (mips_debug)
@@ -3823,7 +4536,7 @@ mips_o32_return_value (struct gdbarch *gdbarch, struct type *type,
    ABI.  */
 
 static CORE_ADDR
-mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
+mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                          struct regcache *regcache, CORE_ADDR bp_addr,
                          int nargs,
                          struct value **args, CORE_ADDR sp,
@@ -3835,6 +4548,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
      address.  */
@@ -3856,7 +4570,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
   /* Now make space on the stack for the args.  */
   for (argnum = 0; argnum < nargs; argnum++)
     len += align_up (TYPE_LENGTH (VALUE_TYPE (args[argnum])),
-                    mips_stack_argsize (tdep));
+                    mips_stack_argsize (gdbarch));
   sp -= align_up (len, 16);
 
   if (mips_debug)
@@ -3876,7 +4590,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                            "mips_o64_push_dummy_call: struct_return reg=%d 0x%s\n",
                            argreg, paddr_nz (struct_addr));
       write_register (argreg++, struct_addr);
-      stack_offset += mips_stack_argsize (tdep);
+      stack_offset += mips_stack_argsize (gdbarch);
     }
 
   /* Now load as many as possible of the first arguments into
@@ -3902,7 +4616,8 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
          up before the check to see if there are any FP registers
          left.  O32/O64 targets also pass the FP in the integer
          registers so also round up normal registers.  */
-      if (!FP_REGISTER_DOUBLE && fp_register_arg_p (typecode, arg_type))
+      if (mips_abi_regsize (gdbarch) < 8
+         && fp_register_arg_p (typecode, arg_type))
        {
          if ((float_argreg & 1))
            float_argreg++;
@@ -3921,7 +4636,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
-         if (!FP_REGISTER_DOUBLE && len == 8)
+         if (mips_abi_regsize (gdbarch) < 8 && len == 8)
            {
              int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
@@ -3968,10 +4683,10 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                    argreg, phex (regval, len));
              write_register (argreg, regval);
-             argreg += FP_REGISTER_DOUBLE ? 1 : 2;
+             argreg += (mips_abi_regsize (gdbarch) == 8) ? 1 : 2;
            }
          /* Reserve space for the FP register.  */
-         stack_offset += align_up (len, mips_stack_argsize (tdep));
+         stack_offset += align_up (len, mips_stack_argsize (gdbarch));
        }
       else
        {
@@ -3979,15 +4694,15 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
          /* Note: structs whose size is not a multiple of
-            mips_regsize() are treated specially: Irix cc passes them
-            in registers where gcc sometimes puts them on the stack.
-            For maximum compatibility, we will put them in both
-            places.  */
-         int odd_sized_struct = ((len > mips_saved_regsize (tdep))
-                                 && (len % mips_saved_regsize (tdep) != 0));
+            mips_abi_regsize() are treated specially: Irix cc passes
+            them in registers where gcc sometimes puts them on the
+            stack.  For maximum compatibility, we will put them in
+            both places.  */
+         int odd_sized_struct = ((len > mips_abi_regsize (gdbarch))
+                                 && (len % mips_abi_regsize (gdbarch) != 0));
          /* Structures should be aligned to eight bytes (even arg registers)
             on MIPS_ABI_O32, if their first member has double precision.  */
-         if (mips_saved_regsize (tdep) < 8
+         if (mips_abi_regsize (gdbarch) < 8
              && mips_type_needs_double_align (arg_type))
            {
              if ((argreg & 1))
@@ -3999,8 +4714,8 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
            {
              /* Remember if the argument was written to the stack.  */
              int stack_used_p = 0;
-             int partial_len = (len < mips_saved_regsize (tdep)
-                                ? len : mips_saved_regsize (tdep));
+             int partial_len = (len < mips_abi_regsize (gdbarch)
+                                ? len : mips_abi_regsize (gdbarch));
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " -- partial=%d",
@@ -4018,11 +4733,11 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                  stack_used_p = 1;
                  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
-                     if (mips_stack_argsize (tdep) == 8
+                     if (mips_stack_argsize (gdbarch) == 8
                          && (typecode == TYPE_CODE_INT
                              || typecode == TYPE_CODE_PTR
                              || typecode == TYPE_CODE_FLT) && len <= 4)
-                       longword_offset = mips_stack_argsize (tdep) - len;
+                       longword_offset = mips_stack_argsize (gdbarch) - len;
                    }
 
                  if (mips_debug)
@@ -4059,7 +4774,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                {
                  LONGEST regval = extract_signed_integer (val, partial_len);
                  /* Value may need to be sign extended, because
-                    mips_regsize() != mips_saved_regsize().  */
+                    mips_isa_regsize() != mips_abi_regsize().  */
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -4074,10 +4789,10 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
 
                     cagney/2001-07-23: gdb/179: Also, GCC, when
                     outputting LE O32 with sizeof (struct) <
-                    mips_saved_regsize(), generates a left shift as
+                    mips_abi_regsize(), generates a left shift as
                     part of storing the argument in a register a
                     register (the left shift isn't generated when
-                    sizeof (struct) >= mips_saved_regsize()).  Since
+                    sizeof (struct) >= mips_abi_regsize()).  Since
                     it is quite possible that this is GCC
                     contradicting the LE/O32 ABI, GDB has not been
                     adjusted to accommodate this.  Either someone
@@ -4086,19 +4801,19 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                     identified as such and GDB gets tweaked
                     accordingly.  */
 
-                 if (mips_saved_regsize (tdep) < 8
+                 if (mips_abi_regsize (gdbarch) < 8
                      && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-                     && partial_len < mips_saved_regsize (tdep)
+                     && partial_len < mips_abi_regsize (gdbarch)
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
-                   regval <<= ((mips_saved_regsize (tdep) - partial_len) *
+                   regval <<= ((mips_abi_regsize (gdbarch) - partial_len) *
                                TARGET_CHAR_BIT);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
                                      phex (regval,
-                                           mips_saved_regsize (tdep)));
+                                           mips_abi_regsize (gdbarch)));
                  write_register (argreg, regval);
                  argreg++;
 
@@ -4119,14 +4834,14 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
                 always allocated.  */
 
              stack_offset += align_up (partial_len,
-                                       mips_stack_argsize (tdep));
+                                       mips_stack_argsize (gdbarch));
            }
        }
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog, "\n");
     }
 
-  regcache_cooked_write_signed (regcache, SP_REGNUM, sp);
+  regcache_cooked_write_signed (regcache, MIPS_SP_REGNUM, sp);
 
   /* Return adjusted stack pointer.  */
   return sp;
@@ -4433,7 +5148,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
   struct gdbarch *gdbarch = get_frame_arch (frame);
   /* do values for GP (int) regs */
   char raw_buffer[MAX_REGISTER_SIZE];
-  int ncols = (mips_regsize (gdbarch) == 8 ? 4 : 8);   /* display cols per row */
+  int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8);       /* display cols per row */
   int col, byte;
   int regnum;
 
@@ -4448,7 +5163,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
          TYPE_CODE_FLT)
        break;                  /* end the row: reached FP register */
       fprintf_filtered (file,
-                       mips_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
+                       mips_abi_regsize (current_gdbarch) == 8 ? "%17s" : "%9s",
                        REGISTER_NAME (regnum));
       col++;
     }
@@ -4472,7 +5187,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
       /* pad small registers */
       for (byte = 0;
-          byte < (mips_regsize (current_gdbarch)
+          byte < (mips_abi_regsize (current_gdbarch)
                   - register_size (current_gdbarch, regnum)); byte++)
        printf_filtered ("  ");
       /* Now print the register value in hex, endian order. */
@@ -4564,62 +5279,6 @@ mips_step_skips_delay (CORE_ADDR pc)
                     extract_unsigned_integer (buf, MIPS_INSTLEN));
 }
 
-
-/* Given PC at the function's start address, attempt to find the
-   prologue end using SAL information.  Return zero if the skip fails.
-
-   A non-optimized prologue traditionally has one SAL for the function
-   and a second for the function body.  A single line function has
-   them both pointing at the same line.
-
-   An optimized prologue is similar but the prologue may contain
-   instructions (SALs) from the instruction body.  Need to skip those
-   while not getting into the function body.
-
-   The functions end point and an increasing SAL line are used as
-   indicators of the prologue's endpoint.
-
-   This code is based on the function refine_prologue_limit (versions
-   found in both ia64 and ppc).  */
-
-static CORE_ADDR
-skip_prologue_using_sal (CORE_ADDR func_addr)
-{
-  struct symtab_and_line prologue_sal;
-  CORE_ADDR start_pc;
-  CORE_ADDR end_pc;
-
-  /* Get an initial range for the function.  */
-  find_pc_partial_function (func_addr, NULL, &start_pc, &end_pc);
-  start_pc += FUNCTION_START_OFFSET;
-
-  prologue_sal = find_pc_line (start_pc, 0);
-  if (prologue_sal.line != 0)
-    {
-      while (prologue_sal.end < end_pc)
-       {
-         struct symtab_and_line sal;
-
-         sal = find_pc_line (prologue_sal.end, 0);
-         if (sal.line == 0)
-           break;
-         /* Assume that a consecutive SAL for the same (or larger)
-            line mark the prologue -> body transition.  */
-         if (sal.line >= prologue_sal.line)
-           break;
-         /* The case in which compiler's optimizer/scheduler has
-            moved instructions into the prologue.  We look ahead in
-            the function looking for address ranges whose
-            corresponding line number is less the first one that we
-            found for the function.  This is more conservative then
-            refine_prologue_limit which scans a large number of SALs
-            looking for any in the prologue */
-         prologue_sal = sal;
-       }
-    }
-  return prologue_sal.end;
-}
-
 /* Skip the PC past function prologue instructions (32-bit version).
    This is a helper function for mips_skip_prologue.  */
 
@@ -4843,16 +5502,6 @@ mips_skip_prologue (CORE_ADDR pc)
     return mips32_skip_prologue (pc);
 }
 
-/* Exported procedure: Is PC in the signal trampoline code */
-
-static int
-mips_pc_in_sigtramp (CORE_ADDR pc, char *ignore)
-{
-  if (sigtramp_address == 0)
-    fixup_sigtramp ();
-  return (pc >= sigtramp_address && pc < sigtramp_end);
-}
-
 /* Root of all "set mips "/"show mips " commands. This will eventually be
    used for all MIPS-specific commands.  */
 
@@ -5271,8 +5920,9 @@ mips_in_return_stub (CORE_ADDR pc, char *name)
 }
 
 
-/* Return non-zero if the PC is in a library helper function that should
-   be ignored.  This implements the IGNORE_HELPER_CALL macro.  */
+/* 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)
@@ -5453,7 +6103,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   if (found_abi == MIPS_ABI_UNKNOWN && info.abfd != NULL)
     bfd_map_over_sections (info.abfd, mips_find_abi_section, &found_abi);
 
-  /* If we have no usefu BFD information, use the ABI from the last
+  /* If we have no useful BFD information, use the ABI from the last
      MIPS architecture (if there is one).  */
   if (found_abi == MIPS_ABI_UNKNOWN && info.abfd == NULL && arches != NULL)
     found_abi = gdbarch_tdep (arches->gdbarch)->found_abi;
@@ -5524,6 +6174,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       case bfd_mach_mips3900:
       case bfd_mach_mips4100:
       case bfd_mach_mips4111:
+      case bfd_mach_mips4120:
        fpu_type = MIPS_FPU_NONE;
        break;
       case bfd_mach_mips4650:
@@ -5622,7 +6273,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       }
     /* FIXME: cagney/2003-11-15: For MIPS, hasn't PC_REGNUM been
        replaced by read_pc?  */
-    set_gdbarch_pc_regnum (gdbarch, regnum->pc);
+    set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
+    set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
     set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
     set_gdbarch_num_regs (gdbarch, num_regs);
     set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
@@ -5636,9 +6288,6 @@ 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_default_saved_regsize = 4;
-      tdep->mips_default_stack_argsize = 4;
-      tdep->mips_fp_register_double = 0;
       tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 1;
       tdep->default_mask_address_p = 0;
@@ -5652,17 +6301,13 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                                 mips_o64_store_return_value);
       set_gdbarch_deprecated_extract_return_value (gdbarch,
                                                   mips_o64_extract_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
       tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 4 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
-      set_gdbarch_use_struct_convention (gdbarch,
-                                        always_use_struct_convention);
+      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);
@@ -5670,9 +6315,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                                 mips_eabi_store_return_value);
       set_gdbarch_deprecated_extract_return_value (gdbarch,
                                                   mips_eabi_extract_return_value);
-      tdep->mips_default_saved_regsize = 4;
-      tdep->mips_default_stack_argsize = 4;
-      tdep->mips_fp_register_double = 0;
       tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
@@ -5681,8 +6323,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_long_long_bit (gdbarch, 64);
       set_gdbarch_deprecated_reg_struct_has_addr
        (gdbarch, mips_eabi_reg_struct_has_addr);
-      set_gdbarch_use_struct_convention (gdbarch,
-                                        mips_eabi_use_struct_convention);
+      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);
@@ -5690,9 +6331,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                                 mips_eabi_store_return_value);
       set_gdbarch_deprecated_extract_return_value (gdbarch,
                                                   mips_eabi_extract_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
       tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
@@ -5701,34 +6339,33 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_long_long_bit (gdbarch, 64);
       set_gdbarch_deprecated_reg_struct_has_addr
        (gdbarch, mips_eabi_reg_struct_has_addr);
-      set_gdbarch_use_struct_convention (gdbarch,
-                                        mips_eabi_use_struct_convention);
+      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_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
       tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_long_double_bit (gdbarch, 128);
+      set_gdbarch_long_double_format (gdbarch,
+                                      &floatformat_n32n64_long_double_big);
       break;
     case MIPS_ABI_N64:
       set_gdbarch_push_dummy_call (gdbarch, mips_n32n64_push_dummy_call);
       set_gdbarch_return_value (gdbarch, mips_n32n64_return_value);
-      tdep->mips_default_saved_regsize = 8;
-      tdep->mips_default_stack_argsize = 8;
-      tdep->mips_fp_register_double = 1;
       tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
       tdep->mips_last_fp_arg_regnum = tdep->regnum->fp0 + 12 + 8 - 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 64);
       set_gdbarch_ptr_bit (gdbarch, 64);
       set_gdbarch_long_long_bit (gdbarch, 64);
+      set_gdbarch_long_double_bit (gdbarch, 128);
+      set_gdbarch_long_double_format (gdbarch,
+                                      &floatformat_n32n64_long_double_big);
       break;
     default:
       internal_error (__FILE__, __LINE__, "unknown ABI in switch");
@@ -5765,9 +6402,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   /* Unwind the frame.  */
   set_gdbarch_unwind_pc (gdbarch, mips_unwind_pc);
-  frame_unwind_append_sniffer (gdbarch, mips_mdebug_frame_sniffer);
   set_gdbarch_unwind_dummy_id (gdbarch, mips_unwind_dummy_id);
-  frame_base_append_sniffer (gdbarch, mips_mdebug_frame_base_sniffer);
 
   /* Map debug register numbers onto internal register numbers.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
@@ -5791,8 +6426,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
   set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
 
-  set_gdbarch_frame_args_skip (gdbarch, 0);
-
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
 
@@ -5805,7 +6438,6 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_register_type (gdbarch, mips_register_type);
 
   set_gdbarch_print_registers_info (gdbarch, mips_print_registers_info);
-  set_gdbarch_pc_in_sigtramp (gdbarch, mips_pc_in_sigtramp);
 
   set_gdbarch_print_insn (gdbarch, gdb_print_insn_mips);
 
@@ -5817,13 +6449,32 @@ 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);
+
+  /* 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);
+    }
+
   /* Hook in OS ABI-specific overrides, if they have been registered.  */
   gdbarch_init_osabi (info, gdbarch);
 
-  set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_stub);
-
-  set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub);
-  set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
+  /* Unwind the frame.  */
+  frame_unwind_append_sniffer (gdbarch, mips_stub_frame_sniffer);
+  frame_unwind_append_sniffer (gdbarch, mips_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, 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);
 
   return gdbarch;
 }
@@ -5917,9 +6568,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                          mips_mask_address_p (tdep),
                          tdep->default_mask_address_p);
     }
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
-                     FP_REGISTER_DOUBLE);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: MIPS_DEFAULT_FPU_TYPE = %d (%s)\n",
                      MIPS_DEFAULT_FPU_TYPE,
@@ -5935,12 +6583,9 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                       : MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? "single"
                       : MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? "double"
                       : "???"));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
-                     FP_REGISTER_DOUBLE);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: mips_stack_argsize() = %d\n",
-                     mips_stack_argsize (tdep));
+                     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",
@@ -5958,8 +6603,8 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                      "mips_dump_tdep: FIRST_EMBED_REGNUM = %d\n",
                      FIRST_EMBED_REGNUM);
   fprintf_unfiltered (file,
-                     "mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
-                     XSTRING (IGNORE_HELPER_CALL (PC)));
+                     "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)));
@@ -5999,8 +6644,8 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                      "mips_dump_tdep: MIPS_NUMREGS = %d\n", MIPS_NUMREGS);
   fprintf_unfiltered (file,
-                     "mips_dump_tdep: mips_saved_regsize() = %d\n",
-                     mips_saved_regsize (tdep));
+                     "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,
@@ -6119,6 +6764,8 @@ _initialize_mips_tdep (void)
 
   gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
 
+  mips_pdr_data = register_objfile_data ();
+
   /* Add root prefix command for all "set mips"/"show mips" commands */
   add_prefix_cmd ("mips", no_class, set_mips_command,
                  "Various MIPS specific commands.",
@@ -6129,10 +6776,10 @@ _initialize_mips_tdep (void)
                  &showmipscmdlist, "show mips ", 0, &showlist);
 
   /* Allow the user to override the saved register size. */
-  add_show_from_set (add_set_enum_cmd ("saved-gpreg-size",
-                                      class_obscure,
-                                      size_enums,
-                                      &mips_saved_regsize_string, "\
+  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\
@@ -6142,16 +6789,18 @@ This option can be set to one of:\n\
           (default: auto)", &setmipscmdlist), &showmipscmdlist);
 
   /* Allow the user to override the argument stack size. */
-  add_show_from_set (add_set_enum_cmd ("stack-arg-size",
-                                      class_obscure,
-                                      size_enums,
-                                      &mips_stack_argsize_string, "\
+  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);
+          target and executable (default)", &setmipscmdlist),
+     &showmipscmdlist);
 
   /* Allow the user to override the ABI. */
   c = add_set_enum_cmd
@@ -6204,32 +6853,34 @@ search.  The only need to set it is when debugging a stripped executable.", &set
   /* We need to throw away the frame cache when we set this, since it
      might change our ability to get backtraces.  */
   set_cmd_sfunc (c, reinit_frame_cache_sfunc);
-  add_show_from_set (c, &showlist);
+  deprecated_add_show_from_set (c, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
      addresses should be zeroed.  */
   add_setshow_auto_boolean_cmd ("mask-address", no_class, &mask_address_var, "\
-Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Set zeroing of upper 32 bits of 64-bit addresses.", "\
+Show zeroing of upper 32 bits of 64-bit addresses.", "\
 Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\
 allow GDB to determine the correct value.\n", "\
-Show zeroing of upper 32 bits of 64-bit addresses.",
+Zerroing of upper 32 bits of 64-bit address is %s.",
                                NULL, show_mask_address, &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to control the size of 32 bit registers within the
      raw remote packet.  */
-  add_setshow_cmd ("remote-mips64-transfers-32bit-regs", class_obscure,
-                  var_boolean, &mips64_transfers_32bit_regs_p, "\
-Set compatibility with 64-bit MIPS targets that transfer 32-bit quantities.\n\
+  add_setshow_boolean_cmd ("remote-mips64-transfers-32bit-regs", class_obscure,
+                          &mips64_transfers_32bit_regs_p, "\
+Set compatibility with 64-bit MIPS target that transfers 32-bit quantities.", "\
+Show compatibility with 64-bit MIPS target that transfers 32-bit quantities.", "\
 Use \"on\" to enable backward compatibility with older MIPS 64 GDB+target\n\
 that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
 64 bits for others.  Use \"off\" to disable compatibility mode", "\
-Show compatibility with 64-bit MIPS targets that transfer 32-bit quantities.\n\
-Use \"on\" to enable backward compatibility with older MIPS 64 GDB+target\n\
-that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
-64 bits for others.  Use \"off\" to disable compatibility mode", set_mips64_transfers_32bit_regs, NULL, &setlist, &showlist);
+Compatibility with 64-bit MIPS target that transfers 32-bit quantities is %s.",
+ set_mips64_transfers_32bit_regs, NULL, &setlist, &showlist);
 
   /* Debug this files internals. */
-  add_show_from_set (add_set_cmd ("mips", class_maintenance, var_zinteger,
-                                 &mips_debug, "Set mips debugging.\n\
-When non-zero, mips specific debugging is enabled.", &setdebuglist), &showdebuglist);
+  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);
 }
This page took 0.057362 seconds and 4 git commands to generate.