Rotate GDB's main ChangeLog file
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index ad0076d0b8ea8691f5aa7e54564ca15ce0ead0a5..9b384ac17879bb64e9446cbedddbd5ea9d6fbd4f 100644 (file)
@@ -1,8 +1,8 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
-   Free Software Foundation, Inc.
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+   2010 Free Software Foundation, Inc.
 
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
    and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
@@ -58,6 +58,7 @@
 #include "dwarf2-frame.h"
 #include "user-regs.h"
 #include "valprint.h"
+#include "ax.h"
 
 static const struct objfile_data *mips_pdr_data;
 
@@ -205,6 +206,12 @@ unmake_mips16_addr (CORE_ADDR addr)
   return ((addr) & ~(CORE_ADDR) 1);
 }
 
+static CORE_ADDR
+make_mips16_addr (CORE_ADDR addr)
+{
+  return ((addr) | (CORE_ADDR) 1);
+}
+
 /* Return the MIPS ABI associated with GDBARCH.  */
 enum mips_abi
 mips_abi (struct gdbarch *gdbarch)
@@ -264,7 +271,6 @@ mips_elf_make_msymbol_special (asymbol * sym, struct minimal_symbol *msym)
   if (((elf_symbol_type *) (sym))->internal_elf_sym.st_other == STO_MIPS16)
     {
       MSYMBOL_TARGET_FLAG_1 (msym) = 1;
-      SYMBOL_VALUE_ADDRESS (msym) |= 1;
     }
 }
 
@@ -449,7 +455,16 @@ mips_register_name (struct gdbarch *gdbarch, int regno)
   enum mips_abi abi = mips_abi (gdbarch);
 
   /* Map [gdbarch_num_regs .. 2*gdbarch_num_regs) onto the raw registers, 
-     but then don't make the raw register names visible.  */
+     but then don't make the raw register names visible.  This (upper)
+     range of user visible register numbers are the pseudo-registers.
+
+     This approach was adopted accommodate the following scenario:
+     It is possible to debug a 64-bit device using a 32-bit
+     programming model.  In such instances, the raw registers are
+     configured to be 64-bits wide, while the pseudo registers are
+     configured to be 32-bits wide.  The registers that the user
+     sees - the pseudo registers - match the users expectations
+     given the programming model being used.  */
   int rawnum = regno % gdbarch_num_regs (gdbarch);
   if (regno < gdbarch_num_regs (gdbarch))
     return "";
@@ -559,11 +574,15 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   else if (register_size (gdbarch, rawnum) >
           register_size (gdbarch, cookednum))
     {
-      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
-         || gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
        regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
       else
-       regcache_raw_read_part (regcache, rawnum, 4, 4, buf);
+       {
+         enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+         LONGEST regval;
+         regcache_raw_read_signed (regcache, rawnum, &regval);
+         store_signed_integer (buf, 4, byte_order, regval);
+       }
     }
   else
     internal_error (__FILE__, __LINE__, _("bad register size"));
@@ -582,16 +601,64 @@ mips_pseudo_register_write (struct gdbarch *gdbarch,
   else if (register_size (gdbarch, rawnum) >
           register_size (gdbarch, cookednum))
     {
-      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
-         || gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
        regcache_raw_write_part (regcache, rawnum, 0, 4, buf);
       else
-       regcache_raw_write_part (regcache, rawnum, 4, 4, buf);
+       {
+         /* Sign extend the shortened version of the register prior
+            to placing it in the raw register.  This is required for
+            some mips64 parts in order to avoid unpredictable behavior.  */
+         enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+         LONGEST regval = extract_signed_integer (buf, 4, byte_order);
+         regcache_raw_write_signed (regcache, rawnum, regval);
+       }
     }
   else
     internal_error (__FILE__, __LINE__, _("bad register size"));
 }
 
+static int
+mips_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+                                struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+             && reg < 2 * gdbarch_num_regs (gdbarch));
+
+  ax_reg_mask (ax, rawnum);
+
+  return 0;
+}
+
+static int
+mips_ax_pseudo_register_push_stack (struct gdbarch *gdbarch,
+                                   struct agent_expr *ax, int reg)
+{
+  int rawnum = reg % gdbarch_num_regs (gdbarch);
+  gdb_assert (reg >= gdbarch_num_regs (gdbarch)
+             && reg < 2 * gdbarch_num_regs (gdbarch));
+  if (register_size (gdbarch, rawnum) >= register_size (gdbarch, reg))
+    {
+      ax_reg (ax, rawnum);
+
+      if (register_size (gdbarch, rawnum) > register_size (gdbarch, reg))
+        {
+         if (!gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
+             || gdbarch_byte_order (gdbarch) != BFD_ENDIAN_BIG)
+           {
+             ax_const_l (ax, 32);
+             ax_simple (ax, aop_lsh);
+           }
+         ax_const_l (ax, 32);
+         ax_simple (ax, aop_rsh_signed);
+       }
+    }
+  else
+    internal_error (__FILE__, __LINE__, _("bad register size"));
+
+  return 0;
+}
+
 /* Table to translate MIPS16 register field to actual register number.  */
 static int mips16_to_32_reg[8] = { 16, 17, 2, 3, 4, 5, 6, 7 };
 
@@ -625,8 +692,13 @@ set_mips64_transfers_32bit_regs (char *args, int from_tty,
 
 /* Convert to/from a register and the corresponding memory value.  */
 
+/* This predicate tests for the case of an 8 byte floating point
+   value that is being transferred to or from a pair of floating point
+   registers each of which are (or are considered to be) only 4 bytes
+   wide.  */
 static int
-mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+mips_convert_register_float_case_p (struct gdbarch *gdbarch, int regnum,
+                                   struct type *type)
 {
   return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
          && register_size (gdbarch, regnum) == 4
@@ -637,20 +709,99 @@ mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
          && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
 }
 
+/* This predicate tests for the case of a value of less than 8
+   bytes in width that is being transfered to or from an 8 byte
+   general purpose register.  */
+static int
+mips_convert_register_gpreg_case_p (struct gdbarch *gdbarch, int regnum,
+                                   struct type *type)
+{
+  int num_regs = gdbarch_num_regs (gdbarch);
+
+  return (register_size (gdbarch, regnum) == 8
+          && regnum % num_regs > 0 && regnum % num_regs < 32
+          && TYPE_LENGTH (type) < 8);
+}
+
+static int
+mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
+{
+  return mips_convert_register_float_case_p (gdbarch, regnum, type)
+      || mips_convert_register_gpreg_case_p (gdbarch, regnum, type);
+}
+
 static void
 mips_register_to_value (struct frame_info *frame, int regnum,
                        struct type *type, gdb_byte *to)
 {
-  get_frame_register (frame, regnum + 0, to + 4);
-  get_frame_register (frame, regnum + 1, to + 0);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (mips_convert_register_float_case_p (gdbarch, regnum, type))
+    {
+      get_frame_register (frame, regnum + 0, to + 4);
+      get_frame_register (frame, regnum + 1, to + 0);
+    }
+  else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+    {
+      int len = TYPE_LENGTH (type);
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       get_frame_register_bytes (frame, regnum, 8 - len, len, to);
+      else
+       get_frame_register_bytes (frame, regnum, 0, len, to);
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__,
+                      _("mips_register_to_value: unrecognized case"));
+    }
 }
 
 static void
 mips_value_to_register (struct frame_info *frame, int regnum,
                        struct type *type, const gdb_byte *from)
 {
-  put_frame_register (frame, regnum + 0, from + 4);
-  put_frame_register (frame, regnum + 1, from + 0);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+
+  if (mips_convert_register_float_case_p (gdbarch, regnum, type))
+    {
+      put_frame_register (frame, regnum + 0, from + 4);
+      put_frame_register (frame, regnum + 1, from + 0);
+    }
+  else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+    {
+      gdb_byte fill[8];
+      int len = TYPE_LENGTH (type);
+      
+      /* Sign extend values, irrespective of type, that are stored to 
+         a 64-bit general purpose register.  (32-bit unsigned values
+        are stored as signed quantities within a 64-bit register.
+        When performing an operation, in compiled code, that combines
+        a 32-bit unsigned value with a signed 64-bit value, a type
+        conversion is first performed that zeroes out the high 32 bits.)  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       {
+         if (from[0] & 0x80)
+           store_signed_integer (fill, 8, BFD_ENDIAN_BIG, -1);
+         else
+           store_signed_integer (fill, 8, BFD_ENDIAN_BIG, 0);
+         put_frame_register_bytes (frame, regnum, 0, 8 - len, fill);
+         put_frame_register_bytes (frame, regnum, 8 - len, len, from);
+       }
+      else
+       {
+         if (from[len-1] & 0x80)
+           store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, -1);
+         else
+           store_signed_integer (fill, 8, BFD_ENDIAN_LITTLE, 0);
+         put_frame_register_bytes (frame, regnum, 0, len, from);
+         put_frame_register_bytes (frame, regnum, len, 8 - len, fill);
+       }
+    }
+  else
+    {
+      internal_error (__FILE__, __LINE__,
+                      _("mips_value_to_register: unrecognized case"));
+    }
 }
 
 /* Return the GDB type object for the "standard" data type of data in
@@ -837,14 +988,21 @@ mips_read_pc (struct regcache *regcache)
   ULONGEST pc;
   int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
   regcache_cooked_read_signed (regcache, regnum, &pc);
+  if (is_mips16_addr (pc))
+    pc = unmake_mips16_addr (pc);
   return pc;
 }
 
 static CORE_ADDR
 mips_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
 {
-  return frame_unwind_register_signed
-          (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+  ULONGEST pc;
+
+  pc = frame_unwind_register_signed
+        (next_frame, gdbarch_num_regs (gdbarch) + mips_regnum (gdbarch)->pc);
+  if (is_mips16_addr (pc))
+    pc = unmake_mips16_addr (pc);
+  return pc;
 }
 
 static CORE_ADDR
@@ -873,15 +1031,19 @@ static void
 mips_write_pc (struct regcache *regcache, CORE_ADDR pc)
 {
   int regnum = mips_regnum (get_regcache_arch (regcache))->pc;
-  regcache_cooked_write_unsigned (regcache, regnum, pc);
+  if (mips_pc_is_mips16 (pc))
+    regcache_cooked_write_unsigned (regcache, regnum, make_mips16_addr (pc));
+  else
+    regcache_cooked_write_unsigned (regcache, regnum, pc);
 }
 
 /* Fetch and return instruction from the specified location.  If the PC
    is odd, assume it's a MIPS16 instruction; otherwise MIPS32.  */
 
 static ULONGEST
-mips_fetch_instruction (CORE_ADDR addr)
+mips_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[MIPS_INSN32_SIZE];
   int instlen;
   int status;
@@ -896,7 +1058,7 @@ mips_fetch_instruction (CORE_ADDR addr)
   status = target_read_memory (addr, buf, instlen);
   if (status)
     memory_error (status, addr);
-  return extract_unsigned_integer (buf, instlen);
+  return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
 /* These the fields of 32 bit mips instructions */
@@ -927,9 +1089,10 @@ mips32_relative_offset (ULONGEST inst)
 static CORE_ADDR
 mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   unsigned long inst;
   int op;
-  inst = mips_fetch_instruction (pc);
+  inst = mips_fetch_instruction (gdbarch, pc);
   if ((inst & 0xe0000000) != 0)        /* Not a special, jump or branch instruction */
     {
       if (itype_op (inst) >> 2 == 5)
@@ -1151,16 +1314,17 @@ extended_offset (unsigned int extension)
    when the offset is to be used in relative addressing.  */
 
 static unsigned int
-fetch_mips_16 (CORE_ADDR pc)
+fetch_mips_16 (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[8];
   pc &= 0xfffffffe;            /* clear the low order bit */
   target_read_memory (pc, buf, 2);
-  return extract_unsigned_integer (buf, 2);
+  return extract_unsigned_integer (buf, 2, byte_order);
 }
 
 static void
-unpack_mips16 (CORE_ADDR pc,
+unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc,
               unsigned int extension,
               unsigned int inst,
               enum mips16_inst_fmts insn_format, struct upk_mips16 *upk)
@@ -1228,7 +1392,7 @@ unpack_mips16 (CORE_ADDR pc,
        unsigned int nexthalf;
        value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
        value = value << 16;
-       nexthalf = mips_fetch_instruction (pc + 2);     /* low bit still set */
+       nexthalf = mips_fetch_instruction (gdbarch, pc + 2);    /* low bit still set */
        value |= nexthalf;
        offset = value;
        regx = -1;
@@ -1254,6 +1418,7 @@ static CORE_ADDR
 extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
                         unsigned int extension, unsigned int insn)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   int op = (insn >> 11);
   switch (op)
     {
@@ -1261,7 +1426,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
       {
        CORE_ADDR offset;
        struct upk_mips16 upk;
-       unpack_mips16 (pc, extension, insn, itype, &upk);
+       unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
        offset = upk.offset;
        if (offset & 0x800)
          {
@@ -1274,7 +1439,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
     case 3:                    /* JAL , JALX - Watch out, these are 32 bit instruction */
       {
        struct upk_mips16 upk;
-       unpack_mips16 (pc, extension, insn, jalxtype, &upk);
+       unpack_mips16 (gdbarch, pc, extension, insn, jalxtype, &upk);
        pc = add_offset_16 (pc, upk.offset);
        if ((insn >> 10) & 0x01)        /* Exchange mode */
          pc = pc & ~0x01;      /* Clear low bit, indicate 32 bit mode */
@@ -1286,7 +1451,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
       {
        struct upk_mips16 upk;
        int reg;
-       unpack_mips16 (pc, extension, insn, ritype, &upk);
+       unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
        reg = get_frame_register_signed (frame, upk.regx);
        if (reg == 0)
          pc += (upk.offset << 1) + 2;
@@ -1298,7 +1463,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
       {
        struct upk_mips16 upk;
        int reg;
-       unpack_mips16 (pc, extension, insn, ritype, &upk);
+       unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
        reg = get_frame_register_signed (frame, upk.regx);
        if (reg != 0)
          pc += (upk.offset << 1) + 2;
@@ -1310,7 +1475,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
       {
        struct upk_mips16 upk;
        int reg;
-       unpack_mips16 (pc, extension, insn, i8type, &upk);
+       unpack_mips16 (gdbarch, pc, extension, insn, i8type, &upk);
        /* upk.regx contains the opcode */
        reg = get_frame_register_signed (frame, 24);  /* Test register is 24 */
        if (((upk.regx == 0) && (reg == 0))     /* BTEZ */
@@ -1358,7 +1523,8 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
          that. */
       {
        pc += 2;
-       pc = extended_mips16_next_pc (frame, pc, insn, fetch_mips_16 (pc));
+       pc = extended_mips16_next_pc (frame, pc, insn,
+                                     fetch_mips_16 (gdbarch, pc));
        break;
       }
     default:
@@ -1373,7 +1539,8 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
 static CORE_ADDR
 mips16_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
-  unsigned int insn = fetch_mips_16 (pc);
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  unsigned int insn = fetch_mips_16 (gdbarch, pc);
   return extended_mips16_next_pc (frame, pc, 0, insn);
 }
 
@@ -1463,7 +1630,8 @@ mips16_get_imm (unsigned short prev_inst, /* previous instruction */
    Return the address of the first instruction past the prologue.  */
 
 static CORE_ADDR
-mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+mips16_scan_prologue (struct gdbarch *gdbarch,
+                     CORE_ADDR start_pc, CORE_ADDR limit_pc,
                       struct frame_info *this_frame,
                       struct mips_frame_cache *this_cache)
 {
@@ -1482,7 +1650,6 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   int extend_bytes = 0;
   int prev_extend_bytes;
   CORE_ADDR end_prologue_addr = 0;
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
 
   /* Can be called when there's no process, and hence when there's no
      THIS_FRAME.  */
@@ -1503,7 +1670,7 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
       prev_inst = inst;
 
       /* Fetch and decode the instruction.   */
-      inst = (unsigned short) mips_fetch_instruction (cur_pc);
+      inst = (unsigned short) mips_fetch_instruction (gdbarch, cur_pc);
 
       /* Normally we ignore extend instructions.  However, if it is
          not followed by a valid prologue instruction, then this
@@ -1769,6 +1936,7 @@ mips16_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 static struct mips_frame_cache *
 mips_insn16_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct mips_frame_cache *cache;
 
   if ((*this_cache) != NULL)
@@ -1784,19 +1952,18 @@ mips_insn16_frame_cache (struct frame_info *this_frame, void **this_cache)
 
     find_pc_partial_function (pc, NULL, &start_addr, NULL);
     if (start_addr == 0)
-      start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
+      start_addr = heuristic_proc_start (gdbarch, pc);
     /* We can't analyze the prologue if we couldn't find the begining
        of the function.  */
     if (start_addr == 0)
       return cache;
 
-    mips16_scan_prologue (start_addr, pc, this_frame, *this_cache);
+    mips16_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
   }
   
   /* gdbarch_sp_regnum contains the value and not the address.  */
   trad_frame_set_value (cache->saved_regs,
-                       gdbarch_num_regs (get_frame_arch (this_frame))
-                       + MIPS_SP_REGNUM,
+                       gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
                        cache->base);
 
   return (*this_cache);
@@ -1808,6 +1975,9 @@ mips_insn16_frame_this_id (struct frame_info *this_frame, void **this_cache,
 {
   struct mips_frame_cache *info = mips_insn16_frame_cache (this_frame,
                                                           this_cache);
+  /* This marks the outermost frame.  */
+  if (info->base == 0)
+    return;
   (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
 }
 
@@ -1891,7 +2061,8 @@ reset_saved_regs (struct gdbarch *gdbarch, struct mips_frame_cache *this_cache)
    Return the address of the first instruction past the prologue.  */
 
 static CORE_ADDR
-mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
+mips32_scan_prologue (struct gdbarch *gdbarch,
+                     CORE_ADDR start_pc, CORE_ADDR limit_pc,
                       struct frame_info *this_frame,
                       struct mips_frame_cache *this_cache)
 {
@@ -1905,7 +2076,6 @@ mips32_scan_prologue (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   int seen_sp_adjust = 0;
   int load_immediate_bytes = 0;
   int in_delay_slot = 0;
-  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   int regsize_is_64_bits = (mips_abi_regsize (gdbarch) == 8);
 
   /* Can be called when there's no process, and hence when there's no
@@ -1929,7 +2099,7 @@ restart:
       int reg;
 
       /* Fetch the instruction.   */
-      inst = (unsigned long) mips_fetch_instruction (cur_pc);
+      inst = (unsigned long) mips_fetch_instruction (gdbarch, cur_pc);
 
       /* Save some code by pre-extracting some useful fields.  */
       high_word = (inst >> 16) & 0xffff;
@@ -2117,6 +2287,7 @@ restart:
 static struct mips_frame_cache *
 mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   struct mips_frame_cache *cache;
 
   if ((*this_cache) != NULL)
@@ -2133,19 +2304,18 @@ mips_insn32_frame_cache (struct frame_info *this_frame, void **this_cache)
 
     find_pc_partial_function (pc, NULL, &start_addr, NULL);
     if (start_addr == 0)
-      start_addr = heuristic_proc_start (get_frame_arch (this_frame), pc);
+      start_addr = heuristic_proc_start (gdbarch, pc);
     /* We can't analyze the prologue if we couldn't find the begining
        of the function.  */
     if (start_addr == 0)
       return cache;
 
-    mips32_scan_prologue (start_addr, pc, this_frame, *this_cache);
+    mips32_scan_prologue (gdbarch, start_addr, pc, this_frame, *this_cache);
   }
   
   /* gdbarch_sp_regnum contains the value and not the address.  */
   trad_frame_set_value (cache->saved_regs,
-                       gdbarch_num_regs (get_frame_arch (this_frame))
-                       + MIPS_SP_REGNUM,
+                       gdbarch_num_regs (gdbarch) + MIPS_SP_REGNUM,
                        cache->base);
 
   return (*this_cache);
@@ -2157,6 +2327,9 @@ mips_insn32_frame_this_id (struct frame_info *this_frame, void **this_cache,
 {
   struct mips_frame_cache *info = mips_insn32_frame_cache (this_frame,
                                                           this_cache);
+  /* This marks the outermost frame.  */
+  if (info->base == 0)
+    return;
   (*this_id) = frame_id_build (info->base, get_frame_func (this_frame));
 }
 
@@ -2344,6 +2517,10 @@ static CORE_ADDR
 mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (is_mips16_addr (addr))
+    addr = unmake_mips16_addr (addr);
+
   if (mips_mask_address_p (tdep) && (((ULONGEST) addr) >> 32 == 0xffffffffUL))
     /* This hack is a work-around for existing boards using PMON, the
        simulator, and any other 64-bit targets that doesn't have true
@@ -2377,7 +2554,8 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr)
    the sequence.  */
 
 static int
-deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
+deal_with_atomic_sequence (struct gdbarch *gdbarch,
+                          struct address_space *aspace, CORE_ADDR pc)
 {
   CORE_ADDR breaks[2] = {-1, -1};
   CORE_ADDR loc = pc;
@@ -2391,7 +2569,7 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
   if (pc & 0x01)
     return 0;
 
-  insn = mips_fetch_instruction (loc);
+  insn = mips_fetch_instruction (gdbarch, loc);
   /* Assume all atomic sequences start with a ll/lld instruction.  */
   if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE)
     return 0;
@@ -2402,7 +2580,7 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       int is_branch = 0;
       loc += MIPS_INSN32_SIZE;
-      insn = mips_fetch_instruction (loc);
+      insn = mips_fetch_instruction (gdbarch, loc);
 
       /* Assume that there is at most one branch in the atomic
         sequence.  If a branch is found, put a breakpoint in its
@@ -2465,7 +2643,7 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch, CORE_ADDR pc)
 
   /* Effectively inserts the breakpoints.  */
   for (index = 0; index <= last_breakpoint; index++)
-      insert_single_step_breakpoint (gdbarch, breaks[index]);
+    insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
 
   return 1;
 }
@@ -2479,15 +2657,16 @@ int
 mips_software_single_step (struct frame_info *frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct address_space *aspace = get_frame_address_space (frame);
   CORE_ADDR pc, next_pc;
 
   pc = get_frame_pc (frame);
-  if (deal_with_atomic_sequence (gdbarch, pc))
+  if (deal_with_atomic_sequence (gdbarch, aspace, pc))
     return 1;
 
   next_pc = mips_next_pc (frame, pc);
 
-  insert_single_step_breakpoint (gdbarch, next_pc);
+  insert_single_step_breakpoint (gdbarch, aspace, next_pc);
   return 1;
 }
 
@@ -2495,7 +2674,7 @@ mips_software_single_step (struct frame_info *frame)
    end of a function. */
 
 static int
-mips_about_to_return (CORE_ADDR pc)
+mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   if (mips_pc_is_mips16 (pc))
     /* This mips16 case isn't necessarily reliable.  Sometimes the compiler
@@ -2504,9 +2683,9 @@ mips_about_to_return (CORE_ADDR pc)
        as $a3), then a "jr" using that register.  This second case
        is almost impossible to distinguish from an indirect jump
        used for switch statements, so we don't even try.  */
-    return mips_fetch_instruction (pc) == 0xe820;      /* jr $ra */
+    return mips_fetch_instruction (gdbarch, pc) == 0xe820;     /* jr $ra */
   else
-    return mips_fetch_instruction (pc) == 0x3e00008;   /* jr $ra */
+    return mips_fetch_instruction (gdbarch, pc) == 0x3e00008;  /* jr $ra */
 }
 
 
@@ -2544,7 +2723,7 @@ heuristic_proc_start (struct gdbarch *gdbarch, CORE_ADDR pc)
           stop_soon, but with this test, at least we
           don't print out warnings for every child forked (eg, on
           decstation).  22apr93 rich@cygnus.com.  */
-       if (inf->stop_soon == NO_STOP_QUIETLY)
+       if (inf->control.stop_soon == NO_STOP_QUIETLY)
          {
            static int blurb_printed = 0;
 
@@ -2589,12 +2768,12 @@ heuristic-fence-post' command.\n",
           addiu sp,-n
           daddiu sp,-n
           extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'  */
-       inst = mips_fetch_instruction (start_pc);
+       inst = mips_fetch_instruction (gdbarch, start_pc);
        if ((inst & 0xff80) == 0x6480)          /* save */
          {
            if (start_pc - instlen >= fence)
              {
-               inst = mips_fetch_instruction (start_pc - instlen);
+               inst = mips_fetch_instruction (gdbarch, start_pc - instlen);
                if ((inst & 0xf800) == 0xf000)  /* extend */
                  start_pc -= instlen;
              }
@@ -2612,7 +2791,7 @@ heuristic-fence-post' command.\n",
        else
          seen_adjsp = 0;
       }
-    else if (mips_about_to_return (start_pc))
+    else if (mips_about_to_return (gdbarch, start_pc))
       {
        /* Skip return and its delay slot.  */
        start_pc += 2 * MIPS_INSN32_SIZE;
@@ -2697,6 +2876,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR func_addr = find_function_addr (function, NULL);
   int regsize = mips_abi_regsize (gdbarch);
 
@@ -2760,12 +2940,29 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                            "mips_eabi_push_dummy_call: %d len=%d type=%d",
                            argnum + 1, len, (int) typecode);
 
+      /* Function pointer arguments to mips16 code need to be made into
+         mips16 pointers.  */
+      if (typecode == TYPE_CODE_PTR
+          && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
+       {
+         CORE_ADDR addr = extract_signed_integer (value_contents (arg),
+                                                  len, byte_order);
+         if (mips_pc_is_mips16 (addr))
+           {
+             store_signed_integer (valbuf, len, byte_order, 
+                                   make_mips16_addr (addr));
+             val = valbuf;
+           }
+         else
+           val = value_contents (arg);
+       }
       /* The EABI passes structures that do not fit in a register by
          reference.  */
-      if (len > regsize
+      else if (len > regsize
          && (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
-         store_unsigned_integer (valbuf, regsize, value_address (arg));
+         store_unsigned_integer (valbuf, regsize, byte_order,
+                                 value_address (arg));
          typecode = TYPE_CODE_PTR;
          len = regsize;
          val = valbuf;
@@ -2810,21 +3007,23 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            {
              int low_offset = gdbarch_byte_order (gdbarch)
                               == BFD_ENDIAN_BIG ? 4 : 0;
-             unsigned long regval;
+             long regval;
 
              /* Write the low word of the double to the even register(s).  */
-             regval = extract_unsigned_integer (val + low_offset, 4);
+             regval = extract_signed_integer (val + low_offset,
+                                              4, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, 4));
-             regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+             regcache_cooked_write_signed (regcache, float_argreg++, regval);
 
              /* Write the high word of the double to the odd register(s).  */
-             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+             regval = extract_signed_integer (val + 4 - low_offset,
+                                              4, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, 4));
-             regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+             regcache_cooked_write_signed (regcache, float_argreg++, regval);
            }
          else
            {
@@ -2832,11 +3031,11 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 in a single register.  */
              /* On 32 bit ABI's the float_argreg is further adjusted
                 above to ensure that it is even register aligned.  */
-             LONGEST regval = extract_unsigned_integer (val, len);
+             LONGEST regval = extract_signed_integer (val, len, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, len));
-             regcache_cooked_write_unsigned (regcache, float_argreg++, regval);
+             regcache_cooked_write_signed (regcache, float_argreg++, regval);
            }
        }
       else
@@ -2919,13 +3118,13 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  && !fp_register_arg_p (gdbarch, typecode, arg_type))
                {
                  LONGEST regval =
-                   extract_unsigned_integer (val, partial_len);
+                   extract_signed_integer (val, partial_len, byte_order);
 
                  if (mips_debug)
                    fprintf_filtered (gdb_stdlog, " - reg=%d val=%s",
                                      argreg,
                                      phex (regval, regsize));
-                 regcache_cooked_write_unsigned (regcache, argreg, regval);
+                 regcache_cooked_write_signed (regcache, argreg, regval);
                  argreg++;
                }
 
@@ -3084,6 +3283,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
@@ -3161,7 +3361,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          /* This is a floating point value that fits entirely
             in a single register or a pair of registers.  */
          int reglen = (len <= MIPS64_REGSIZE ? len : MIPS64_REGSIZE);
-         LONGEST regval = extract_unsigned_integer (val, reglen);
+         LONGEST regval = extract_unsigned_integer (val, reglen, byte_order);
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                float_argreg, phex (regval, reglen));
@@ -3175,7 +3375,8 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          argreg++;
          if (len == 16)
            {
-             regval = extract_unsigned_integer (val + reglen, reglen);
+             regval = extract_unsigned_integer (val + reglen,
+                                                reglen, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, reglen));
@@ -3275,9 +3476,11 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                      || (partial_len < 4
                          && typecode == TYPE_CODE_INT
                          && !TYPE_UNSIGNED (arg_type)))
-                   regval = extract_signed_integer (val, partial_len);
+                   regval = extract_signed_integer (val, partial_len,
+                                                    byte_order);
                  else
-                   regval = extract_unsigned_integer (val, partial_len);
+                   regval = extract_unsigned_integer (val, partial_len,
+                                                      byte_order);
 
                  /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
@@ -3357,7 +3560,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type,
      (and $f2 if necessary).  This is a generalization of the Fortran COMPLEX
      case.
 
-     * Any other struct or union results of at most 128 bits are returned in
+     * Any other composite results of at most 128 bits are returned in
      $2 (first 64 bits) and $3 (remainder, if necessary).
 
      * Larger composite results are handled by converting the function to a
@@ -3368,8 +3571,7 @@ mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type,
      specific exception to return COMPLEX results in the floating point
      registers.]  */
 
-  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
-      || TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
+  if (TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
     return RETURN_VALUE_STRUCT_CONVENTION;
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
           && TYPE_LENGTH (type) == 16
@@ -3459,9 +3661,10 @@ mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type,
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
   else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
-          || TYPE_CODE (type) == TYPE_CODE_UNION)
+          || TYPE_CODE (type) == TYPE_CODE_UNION
+          || TYPE_CODE (type) == TYPE_CODE_ARRAY)
     {
-      /* A structure or union.  Extract the left justified value,
+      /* A composite type.  Extract the left justified value,
          regardless of the byte order.  I.e. DO NOT USE
          mips_xfer_lower.  */
       int offset;
@@ -3522,6 +3725,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
@@ -3624,7 +3828,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
-             regval = extract_unsigned_integer (val + low_offset, 4);
+             regval = extract_unsigned_integer (val + low_offset,
+                                                4, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, 4));
@@ -3635,7 +3840,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              regcache_cooked_write_unsigned (regcache, argreg++, regval);
 
              /* Write the high word of the double to the odd register(s).  */
-             regval = extract_unsigned_integer (val + 4 - low_offset, 4);
+             regval = extract_unsigned_integer (val + 4 - low_offset,
+                                                4, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, 4));
@@ -3652,7 +3858,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 in a single register.  */
              /* On 32 bit ABI's the float_argreg is further adjusted
                 above to ensure that it is even register aligned.  */
-             LONGEST regval = extract_unsigned_integer (val, len);
+             LONGEST regval = extract_unsigned_integer (val, len, byte_order);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                    float_argreg, phex (regval, len));
@@ -3740,7 +3946,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM (gdbarch))
                {
-                 LONGEST regval = extract_signed_integer (val, partial_len);
+                 LONGEST regval = extract_signed_integer (val, partial_len,
+                                                          byte_order);
                  /* Value may need to be sign extended, because
                     mips_isa_regsize() != mips_abi_regsize().  */
 
@@ -3982,6 +4189,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   int len = 0;
   int stack_offset = 0;
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR func_addr = find_function_addr (function, NULL);
 
   /* For shared libraries, "t9" needs to point at the function
@@ -4038,6 +4246,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   for (argnum = 0; argnum < nargs; argnum++)
     {
       const gdb_byte *val;
+      gdb_byte valbuf[MAX_REGISTER_SIZE];
       struct value *arg = args[argnum];
       struct type *arg_type = check_typedef (value_type (arg));
       int len = TYPE_LENGTH (arg_type);
@@ -4050,6 +4259,21 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
       val = value_contents (arg);
 
+      /* Function pointer arguments to mips16 code need to be made into
+         mips16 pointers.  */
+      if (typecode == TYPE_CODE_PTR
+          && TYPE_CODE (TYPE_TARGET_TYPE (arg_type)) == TYPE_CODE_FUNC)
+       {
+         CORE_ADDR addr = extract_signed_integer (value_contents (arg),
+                                                  len, byte_order);
+         if (mips_pc_is_mips16 (addr))
+           {
+             store_signed_integer (valbuf, len, byte_order, 
+                                   make_mips16_addr (addr));
+             val = valbuf;
+           }
+       }
+
       /* Floating point arguments passed in registers have to be
          treated specially.  On 32-bit architectures, doubles
          are passed in register pairs; the even register gets
@@ -4063,7 +4287,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       if (fp_register_arg_p (gdbarch, typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM (gdbarch))
        {
-         LONGEST regval = extract_unsigned_integer (val, len);
+         LONGEST regval = extract_unsigned_integer (val, len, byte_order);
          if (mips_debug)
            fprintf_unfiltered (gdb_stdlog, " - fpreg=%d val=%s",
                                float_argreg, phex (regval, len));
@@ -4145,7 +4369,8 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                 purpose register.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM (gdbarch))
                {
-                 LONGEST regval = extract_signed_integer (val, partial_len);
+                 LONGEST regval = extract_signed_integer (val, partial_len,
+                                                          byte_order);
                  /* Value may need to be sign extended, because
                     mips_isa_regsize() != mips_abi_regsize().  */
 
@@ -4649,6 +4874,7 @@ static int
 mips_single_step_through_delay (struct gdbarch *gdbarch,
                                struct frame_info *frame)
 {
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR pc = get_frame_pc (frame);
   gdb_byte buf[MIPS_INSN32_SIZE];
 
@@ -4656,14 +4882,14 @@ mips_single_step_through_delay (struct gdbarch *gdbarch,
   if (mips_pc_is_mips16 (pc))
     return 0;
 
-  if (!breakpoint_here_p (pc + 4))
+  if (!breakpoint_here_p (get_frame_address_space (frame), pc + 4))
     return 0;
 
   if (!safe_frame_unwind_memory (frame, pc, buf, sizeof buf))
     /* If error reading memory, guess that it is not a delayed
        branch.  */
     return 0;
-  return is_delayed (extract_unsigned_integer (buf, sizeof buf));
+  return is_delayed (extract_unsigned_integer (buf, sizeof buf, byte_order));
 }
 
 /* To skip prologues, I use this predicate.  Returns either PC itself
@@ -4703,15 +4929,15 @@ mips_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
     limit_pc = pc + 100;          /* Magic.  */
 
   if (mips_pc_is_mips16 (pc))
-    return mips16_scan_prologue (pc, limit_pc, NULL, NULL);
+    return mips16_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
   else
-    return mips32_scan_prologue (pc, limit_pc, NULL, NULL);
+    return mips32_scan_prologue (gdbarch, pc, limit_pc, NULL, NULL);
 }
 
 /* Check whether the PC is in a function epilogue (32-bit version).
    This is a helper function for mips_in_function_epilogue_p.  */
 static int
-mips32_in_function_epilogue_p (CORE_ADDR pc)
+mips32_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr = 0, func_end = 0;
 
@@ -4730,7 +4956,7 @@ mips32_in_function_epilogue_p (CORE_ADDR pc)
          unsigned long high_word;
          unsigned long inst;
 
-         inst = mips_fetch_instruction (pc);
+         inst = mips_fetch_instruction (gdbarch, pc);
          high_word = (inst >> 16) & 0xffff;
 
          if (high_word != 0x27bd       /* addiu $sp,$sp,offset */
@@ -4749,7 +4975,7 @@ mips32_in_function_epilogue_p (CORE_ADDR pc)
 /* Check whether the PC is in a function epilogue (16-bit version).
    This is a helper function for mips_in_function_epilogue_p.  */
 static int
-mips16_in_function_epilogue_p (CORE_ADDR pc)
+mips16_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   CORE_ADDR func_addr = 0, func_end = 0;
 
@@ -4767,7 +4993,7 @@ mips16_in_function_epilogue_p (CORE_ADDR pc)
        {
          unsigned short inst;
 
-         inst = mips_fetch_instruction (pc);
+         inst = mips_fetch_instruction (gdbarch, pc);
 
          if ((inst & 0xf800) == 0xf000)        /* extend */
            continue;
@@ -4792,9 +5018,9 @@ static int
 mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   if (mips_pc_is_mips16 (pc))
-    return mips16_in_function_epilogue_p (pc);
+    return mips16_in_function_epilogue_p (gdbarch, pc);
   else
-    return mips32_in_function_epilogue_p (pc);
+    return mips32_in_function_epilogue_p (gdbarch, pc);
 }
 
 /* Root of all "set mips "/"show mips " commands. This will eventually be
@@ -5016,6 +5242,9 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
          static gdb_byte big_breakpoint[] = { 0, 0x5, 0, 0xd };
          static gdb_byte pmon_big_breakpoint[] = { 0, 0, 0, 0xd };
          static gdb_byte idt_big_breakpoint[] = { 0, 0, 0x0a, 0xd };
+         /* Likewise, IRIX appears to expect a different breakpoint,
+            although this is not apparent until you try to use pthreads. */
+         static gdb_byte irix_big_breakpoint[] = { 0, 0, 0, 0xd };
 
          *lenptr = sizeof (big_breakpoint);
 
@@ -5025,6 +5254,8 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
                   || strcmp (target_shortname, "pmon") == 0
                   || strcmp (target_shortname, "lsi") == 0)
            return pmon_big_breakpoint;
+         else if (gdbarch_osabi (gdbarch) == GDB_OSABI_IRIX)
+           return irix_big_breakpoint;
          else
            return big_breakpoint;
        }
@@ -5077,6 +5308,7 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
 static CORE_ADDR
 mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
   char *name;
   CORE_ADDR start_addr;
 
@@ -5135,7 +5367,7 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                 instructions.  FIXME.  */
              for (i = 0, pc = 0; i < 20; i++, target_pc += MIPS_INSN32_SIZE)
                {
-                 inst = mips_fetch_instruction (target_pc);
+                 inst = mips_fetch_instruction (gdbarch, target_pc);
                  if ((inst & 0xffff0000) == 0x3c010000)        /* lui $at */
                    pc = (inst << 16) & 0xffff0000;     /* high word */
                  else if ((inst & 0xffff0000) == 0x24210000)   /* addiu $at */
@@ -5161,6 +5393,8 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 static CORE_ADDR
 mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct minimal_symbol *msym;
   int i;
   gdb_byte stub_code[16];
@@ -5186,7 +5420,8 @@ mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
       if (target_read_memory (pc, stub_code, 16) != 0)
        return 0;
       for (i = 0; i < 4; i++)
-       stub_words[i] = extract_unsigned_integer (stub_code + i * 4, 4);
+       stub_words[i] = extract_unsigned_integer (stub_code + i * 4,
+                                                 4, byte_order);
 
       /* A stub contains these instructions:
         lui    t9, %hi(target)
@@ -5298,7 +5533,8 @@ static CORE_ADDR
 mips_integer_to_address (struct gdbarch *gdbarch,
                         struct type *type, const gdb_byte *buf)
 {
-  return (CORE_ADDR) extract_signed_integer (buf, TYPE_LENGTH (type));
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order);
 }
 
 /* Dummy virtual frame pointer method.  This is no more or less accurate
@@ -5710,6 +5946,10 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->mips_fpu_type = fpu_type;
   tdep->register_size_valid_p = 0;
   tdep->register_size = 0;
+  tdep->gregset = NULL;
+  tdep->gregset64 = NULL;
+  tdep->fpregset = NULL;
+  tdep->fpregset64 = NULL;
 
   if (info.target_desc)
     {
@@ -5736,6 +5976,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
   set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
 
+  set_gdbarch_ax_pseudo_register_collect (gdbarch,
+                                         mips_ax_pseudo_register_collect);
+  set_gdbarch_ax_pseudo_register_push_stack
+      (gdbarch, mips_ax_pseudo_register_push_stack);
+
   set_gdbarch_elf_make_msymbol_special (gdbarch,
                                        mips_elf_make_msymbol_special);
 
@@ -6280,7 +6525,7 @@ search.  The only need to set it is when debugging a stripped executable."),
                                &mask_address_var, _("\
 Set zeroing of upper 32 bits of 64-bit addresses."), _("\
 Show zeroing of upper 32 bits of 64-bit addresses."), _("\
-Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\
+Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to\n\
 allow GDB to determine the correct value."),
                                NULL, show_mask_address,
                                &setmipscmdlist, &showmipscmdlist);
This page took 0.039524 seconds and 4 git commands to generate.