2012-03-01 Pedro Alves <palves@redhat.com>
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 27488050a443abfec1adddf04e141cc8c0ef5867..67ead3c0d2d90f980f8e8c352db4e68916b84e23 100644 (file)
@@ -1,8 +1,6 @@
 /* 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,
-   2010 Free Software Foundation, Inc.
+   Copyright (C) 1988-2012 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 +56,7 @@
 #include "dwarf2-frame.h"
 #include "user-regs.h"
 #include "valprint.h"
+#include "ax.h"
 
 static const struct objfile_data *mips_pdr_data;
 
@@ -83,7 +82,7 @@ enum
 
 static const char *mips_abi_string;
 
-static const char *mips_abi_strings[] = {
+static const char *const mips_abi_strings[] = {
   "auto",
   "n32",
   "o32",
@@ -184,9 +183,11 @@ mips_fpa0_regnum (struct gdbarch *gdbarch)
                     == MIPS_ABI_EABI32 \
                   || gdbarch_tdep (gdbarch)->mips_abi == MIPS_ABI_EABI64)
 
-#define MIPS_LAST_FP_ARG_REGNUM(gdbarch) (gdbarch_tdep (gdbarch)->mips_last_fp_arg_regnum)
+#define MIPS_LAST_FP_ARG_REGNUM(gdbarch) \
+  (gdbarch_tdep (gdbarch)->mips_last_fp_arg_regnum)
 
-#define MIPS_LAST_ARG_REGNUM(gdbarch) (gdbarch_tdep (gdbarch)->mips_last_arg_regnum)
+#define MIPS_LAST_ARG_REGNUM(gdbarch) \
+  (gdbarch_tdep (gdbarch)->mips_last_arg_regnum)
 
 #define MIPS_FPU_TYPE(gdbarch) (gdbarch_tdep (gdbarch)->mips_fpu_type)
 
@@ -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)
@@ -226,7 +233,7 @@ mips_isa_regsize (struct gdbarch *gdbarch)
          / gdbarch_bfd_arch_info (gdbarch)->bits_per_byte);
 }
 
-/* Return the currently configured (or set) saved register size. */
+/* Return the currently configured (or set) saved register size.  */
 
 unsigned int
 mips_abi_regsize (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;
     }
 }
 
@@ -364,7 +370,7 @@ static CORE_ADDR heuristic_proc_start (struct gdbarch *, CORE_ADDR);
 
 static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
-/* The list of available "set mips " and "show mips " commands */
+/* The list of available "set mips " and "show mips " commands */
 
 static struct cmd_list_element *setmipscmdlist = NULL;
 static struct cmd_list_element *showmipscmdlist = NULL;
@@ -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 "";
@@ -547,7 +562,7 @@ mips_tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
    gdbarch_num_regs .. 2 * gdbarch_num_regs) back onto the corresponding raw
    registers.  Take care of alignment and size problems.  */
 
-static void
+static enum register_status
 mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
                           int cookednum, gdb_byte *buf)
 {
@@ -555,15 +570,23 @@ mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
   gdb_assert (cookednum >= gdbarch_num_regs (gdbarch)
              && cookednum < 2 * gdbarch_num_regs (gdbarch));
   if (register_size (gdbarch, rawnum) == register_size (gdbarch, cookednum))
-    regcache_raw_read (regcache, rawnum, buf);
+    return regcache_raw_read (regcache, rawnum, buf);
   else if (register_size (gdbarch, rawnum) >
           register_size (gdbarch, cookednum))
     {
-      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p
-         || gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
-       regcache_raw_read_part (regcache, rawnum, 0, 4, buf);
+      if (gdbarch_tdep (gdbarch)->mips64_transfers_32bit_regs_p)
+       return 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;
+         enum register_status status;
+
+         status = regcache_raw_read_signed (regcache, rawnum, &regval);
+         if (status == REG_VALID)
+           store_signed_integer (buf, 4, byte_order, regval);
+         return status;
+       }
     }
   else
     internal_error (__FILE__, __LINE__, _("bad register size"));
@@ -582,16 +605,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 +696,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 +713,116 @@ mips_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
          && TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
 }
 
-static void
+/* 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 int
 mips_register_to_value (struct frame_info *frame, int regnum,
-                       struct type *type, gdb_byte *to)
+                       struct type *type, gdb_byte *to,
+                       int *optimizedp, int *unavailablep)
 {
-  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);
+
+      if (!get_frame_register_bytes (frame, regnum + 0, 0, 4, to + 4,
+                                    optimizedp, unavailablep))
+       return 0;
+
+      if (!get_frame_register_bytes (frame, regnum + 1, 0, 4, to + 0,
+                                    optimizedp, unavailablep))
+       return 0;
+      *optimizedp = *unavailablep = 0;
+      return 1;
+    }
+  else if (mips_convert_register_gpreg_case_p (gdbarch, regnum, type))
+    {
+      int len = TYPE_LENGTH (type);
+      CORE_ADDR offset;
+
+      offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 8 - len : 0;
+      if (!get_frame_register_bytes (frame, regnum, offset, len, to,
+                                    optimizedp, unavailablep))
+       return 0;
+
+      *optimizedp = *unavailablep = 0;
+      return 1;
+    }
+  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
@@ -760,7 +932,7 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
   return rawtype;
 }
 
-/* Should the upper word of 64-bit addresses be zeroed? */
+/* Should the upper word of 64-bit addresses be zeroed?  */
 enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
 
 static int
@@ -776,7 +948,8 @@ mips_mask_address_p (struct gdbarch_tdep *tdep)
     case AUTO_BOOLEAN_AUTO:
       return tdep->default_mask_address_p;
     default:
-      internal_error (__FILE__, __LINE__, _("mips_mask_address_p: bad switch"));
+      internal_error (__FILE__, __LINE__,
+                     _("mips_mask_address_p: bad switch"));
       return -1;
     }
 }
@@ -814,22 +987,19 @@ mips_pc_is_mips16 (CORE_ADDR memaddr)
 {
   struct minimal_symbol *sym;
 
-  /* If bit 0 of the address is set, assume this is a MIPS16 address. */
-  if (is_mips16_addr (memaddr))
-    return 1;
-
-  /* A flag indicating that this is a MIPS16 function is stored by elfread.c in
-     the high bit of the info field.  Use this to decide if the function is
-     MIPS16 or normal MIPS.  */
+  /* A flag indicating that this is a MIPS16 function is stored by
+     elfread.c in the high bit of the info field.  Use this to decide
+     if the function is MIPS16 or normal MIPS.  Otherwise if bit 0 of
+     the address is set, assume this is a MIPS16 address.  */
   sym = lookup_minimal_symbol_by_pc (memaddr);
   if (sym)
     return msymbol_is_special (sym);
   else
-    return 0;
+    return is_mips16_addr (memaddr);
 }
 
 /* MIPS believes that the PC has a sign extended value.  Perhaps the
-   all registers should be sign extended for simplicity? */
+   all registers should be sign extended for simplicity?  */
 
 static CORE_ADDR
 mips_read_pc (struct regcache *regcache)
@@ -837,14 +1007,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,7 +1050,10 @@ 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
@@ -900,7 +1080,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch, CORE_ADDR addr)
   return extract_unsigned_integer (buf, instlen, byte_order);
 }
 
-/* These the fields of 32 bit mips instructions */
+/* These are the fields of 32 bit mips instructions.  */
 #define mips32_op(x) (x >> 26)
 #define itype_op(x) (x >> 26)
 #define itype_rs(x) ((x >> 21) & 0x1f)
@@ -932,7 +1112,8 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
   unsigned long inst;
   int op;
   inst = mips_fetch_instruction (gdbarch, pc);
-  if ((inst & 0xe0000000) != 0)        /* Not a special, jump or branch instruction */
+  if ((inst & 0xe0000000) != 0)                /* Not a special, jump or branch
+                                          instruction.  */
     {
       if (itype_op (inst) >> 2 == 5)
        /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
@@ -961,7 +1142,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
            get_frame_register_signed (frame,
                                       mips_regnum (get_frame_arch (frame))->
                                                fp_control_status);
-         int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
+         int cond = ((fcrcs >> 24) & 0xfe) | ((fcrcs >> 23) & 0x01);
 
          if (((cond >> cnum) & 0x01) == tf)
            pc += mips32_relative_offset (inst) + 4;
@@ -969,13 +1150,13 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
            pc += 8;
        }
       else
-       pc += 4;                /* Not a branch, next instruction is easy */
+       pc += 4;                /* Not a branch, next instruction is easy */
     }
   else
-    {                          /* This gets way messy */
+    {                          /* This gets way messy */
 
-      /* Further subdivide into SPECIAL, REGIMM and other */
-      switch (op = itype_op (inst) & 0x07)     /* extract bits 28,27,26 */
+      /* Further subdivide into SPECIAL, REGIMM and other */
+      switch (op = itype_op (inst) & 0x07)     /* Extract bits 28,27,26.  */
        {
        case 0:         /* SPECIAL */
          op = rtype_funct (inst);
@@ -983,7 +1164,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
            {
            case 8:             /* JR */
            case 9:             /* JALR */
-             /* Set PC to that address */
+             /* Set PC to that address */
              pc = get_frame_register_signed (frame, rtype_rs (inst));
              break;
            case 12:            /* SYSCALL */
@@ -1002,7 +1183,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
            }
 
          break;                /* end SPECIAL */
-       case 1:         /* REGIMM */
+       case 1:                 /* REGIMM */
          {
            op = itype_rt (inst);       /* branch condition */
            switch (op)
@@ -1037,7 +1218,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
-           /* Upper four bits get never changed... */
+           /* Upper four bits get never changed...  */
            pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff);
          }
          break;
@@ -1045,7 +1226,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
-           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + 1;        /* yes, +1 */
+           pc = reg + ((pc + 4) & ~(CORE_ADDR) 0x0fffffff) + 1;  /* yes, +1 */
            /* Add 1 to indicate 16 bit mode - Invert ISA mode */
          }
          break;                /* The new PC will be alternate mode */
@@ -1085,16 +1266,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc)
 }                              /* mips32_next_pc */
 
 /* Decoding the next place to set a breakpoint is irregular for the
-   mips 16 variant, but fortunately, there fewer instructions. We have to cope
-   ith extensions for 16 bit instructions and a pair of actual 32 bit instructions.
-   We dont want to set a single step instruction on the extend instruction
-   either.
- */
+   mips 16 variant, but fortunately, there fewer instructions.  We have
+   to cope ith extensions for 16 bit instructions and a pair of actual
+   32 bit instructions.  We dont want to set a single step instruction
+   on the extend instruction either.  */
 
 /* Lots of mips16 instruction formats */
 /* Predicting jumps requires itype,ritype,i8type
-   and their extensions      extItype,extritype,extI8type
- */
+   and their extensions      extItype,extritype,extI8type.  */
 enum mips16_inst_fmts
 {
   itype,                       /* 0  immediate 5,10 */
@@ -1121,11 +1300,11 @@ enum mips16_inst_fmts
   extshift64type               /* 21  5,5,1,1,1,1,1,1,5,1,1,1,3,5 */
 };
 /* I am heaping all the fields of the formats into one structure and
-   then, only the fields which are involved in instruction extension */
+   then, only the fields which are involved in instruction extension */
 struct upk_mips16
 {
   CORE_ADDR offset;
-  unsigned int regx;           /* Function in i8 type */
+  unsigned int regx;           /* Function in i8 type */
   unsigned int regy;
 };
 
@@ -1137,11 +1316,13 @@ static CORE_ADDR
 extended_offset (unsigned int extension)
 {
   CORE_ADDR value;
-  value = (extension >> 21) & 0x3f;    /* * extract 15:11 */
+
+  value = (extension >> 16) & 0x1f;    /* Extract 15:11.  */
   value = value << 6;
-  value |= (extension >> 16) & 0x1f;   /* extrace 10:5 */
+  value |= (extension >> 21) & 0x3f;   /* Extract 10:5.  */
   value = value << 5;
-  value |= extension & 0x01f;  /* extract 4:0 */
+  value |= extension & 0x1f;           /* Extract 4:0.  */
+
   return value;
 }
 
@@ -1157,7 +1338,7 @@ 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 */
+  pc &= 0xfffffffe;            /* Clear the low order bit.  */
   target_read_memory (pc, buf, 2);
   return extract_unsigned_integer (buf, 2, byte_order);
 }
@@ -1178,14 +1359,13 @@ unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc,
        CORE_ADDR value;
        if (extension)
          {
-           value = extended_offset (extension);
-           value = value << 11;        /* rom for the original value */
-           value |= inst & 0x7ff;      /* eleven bits from instruction */
+           value = extended_offset ((extension << 16) | inst);
+           value = (value ^ 0x8000) - 0x8000;          /* Sign-extend.  */
          }
        else
          {
            value = inst & 0x7ff;
-           /* FIXME : Consider sign extension */
+           value = (value ^ 0x400) - 0x400;            /* Sign-extend.  */
          }
        offset = value;
        regx = -1;
@@ -1194,34 +1374,22 @@ unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc,
       break;
     case ritype:
     case i8type:
-      {                                /* A register identifier and an offset */
+      {                                /* A register identifier and an offset */
        /* Most of the fields are the same as I type but the
-          immediate value is of a different length */
+          immediate value is of a different length */
        CORE_ADDR value;
        if (extension)
          {
-           value = extended_offset (extension);
-           value = value << 8; /* from the original instruction */
-           value |= inst & 0xff;       /* eleven bits from instruction */
-           regx = (extension >> 8) & 0x07;     /* or i8 funct */
-           if (value & 0x4000) /* test the sign bit , bit 26 */
-             {
-               value &= ~0x3fff;       /* remove the sign bit */
-               value = -value;
-             }
+           value = extended_offset ((extension << 16) | inst);
+           value = (value ^ 0x8000) - 0x8000;          /* Sign-extend.  */
          }
        else
          {
-           value = inst & 0xff;        /* 8 bits */
-           regx = (inst >> 8) & 0x07;  /* or i8 funct */
-           /* FIXME: Do sign extension , this format needs it */
-           if (value & 0x80)   /* THIS CONFUSES ME */
-             {
-               value &= 0xef;  /* remove the sign bit */
-               value = -value;
-             }
+           value = inst & 0xff;                        /* 8 bits */
+           value = (value ^ 0x80) - 0x80;              /* Sign-extend.  */
          }
        offset = value;
+       regx = (inst >> 8) & 0x07;                      /* i8 funct */
        regy = -1;
        break;
       }
@@ -1231,7 +1399,8 @@ unpack_mips16 (struct gdbarch *gdbarch, CORE_ADDR pc,
        unsigned int nexthalf;
        value = ((inst & 0x1f) << 5) | ((inst >> 5) & 0x1f);
        value = value << 16;
-       nexthalf = mips_fetch_instruction (gdbarch, pc + 2);    /* low bit still set */
+       nexthalf = mips_fetch_instruction (gdbarch, pc + 2);  /* low bit
+                                                                still set.  */
        value |= nexthalf;
        offset = value;
        regx = -1;
@@ -1266,22 +1435,17 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
        CORE_ADDR offset;
        struct upk_mips16 upk;
        unpack_mips16 (gdbarch, pc, extension, insn, itype, &upk);
-       offset = upk.offset;
-       if (offset & 0x800)
-         {
-           offset &= 0xeff;
-           offset = -offset;
-         }
-       pc += (offset << 1) + 2;
+       pc += (upk.offset << 1) + 2;
        break;
       }
-    case 3:                    /* JAL , JALX - Watch out, these are 32 bit instruction */
+    case 3:                    /* JAL , JALX - Watch out, these are 32 bit
+                                  instructions.  */
       {
        struct upk_mips16 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 */
+         pc = pc & ~0x01;      /* Clear low bit, indicate 32 bit mode */
        else
          pc |= 0x01;
        break;
@@ -1291,7 +1455,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
        struct upk_mips16 upk;
        int reg;
        unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
-       reg = get_frame_register_signed (frame, upk.regx);
+       reg = get_frame_register_signed (frame, mips16_to_32_reg[upk.regx]);
        if (reg == 0)
          pc += (upk.offset << 1) + 2;
        else
@@ -1303,7 +1467,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
        struct upk_mips16 upk;
        int reg;
        unpack_mips16 (gdbarch, pc, extension, insn, ritype, &upk);
-       reg = get_frame_register_signed (frame, upk.regx);
+       reg = get_frame_register_signed (frame, mips16_to_32_reg[upk.regx]);
        if (reg != 0)
          pc += (upk.offset << 1) + 2;
        else
@@ -1335,21 +1499,10 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
            int reg;
            upk.regx = (insn >> 8) & 0x07;
            upk.regy = (insn >> 5) & 0x07;
-           switch (upk.regy)
-             {
-             case 0:
-               reg = upk.regx;
-               break;
-             case 1:
-               reg = 31;
-               break;          /* Function return instruction */
-             case 2:
-               reg = upk.regx;
-               break;
-             default:
-               reg = 31;
-               break;          /* BOGUS Guess */
-             }
+           if ((upk.regy & 1) == 0)
+             reg = mips16_to_32_reg[upk.regx];
+           else
+             reg = 31;         /* Function return instruction.  */
            pc = get_frame_register_signed (frame, reg);
          }
        else
@@ -1359,7 +1512,7 @@ extended_mips16_next_pc (struct frame_info *frame, CORE_ADDR pc,
     case 30:
       /* This is an instruction extension.  Fetch the real instruction
          (which follows the extension) and decode things based on
-         that. */
+         that.  */
       {
        pc += 2;
        pc = extended_mips16_next_pc (frame, pc, insn,
@@ -1386,12 +1539,12 @@ mips16_next_pc (struct frame_info *frame, CORE_ADDR pc)
 /* 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.
+   branch will go.  This isnt hard because all the data is available.
    The MIPS32 and MIPS16 variants are quite different.  */
 static CORE_ADDR
 mips_next_pc (struct frame_info *frame, CORE_ADDR pc)
 {
-  if (is_mips16_addr (pc))
+  if (mips_pc_is_mips16 (pc))
     return mips16_next_pc (frame, pc);
   else
     return mips32_next_pc (frame, pc);
@@ -1439,7 +1592,7 @@ mips16_get_imm (unsigned short prev_inst, /* previous instruction */
                unsigned short inst,    /* current instruction */
                int nbits,      /* number of bits in imm field */
                int scale,      /* scale factor to be applied to imm */
-               int is_signed)  /* is the imm field signed? */
+               int is_signed)  /* is the imm field signed?  */
 {
   int offset;
 
@@ -1475,12 +1628,12 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
                       struct mips_frame_cache *this_cache)
 {
   CORE_ADDR cur_pc;
-  CORE_ADDR frame_addr = 0;    /* Value of $r17, used as frame pointer */
+  CORE_ADDR frame_addr = 0;    /* Value of $r17, used as frame pointer */
   CORE_ADDR sp;
   long frame_offset = 0;        /* Size of stack frame.  */
   long frame_adjust = 0;        /* Offset of FP from SP.  */
   int frame_reg = MIPS_SP_REGNUM;
-  unsigned short prev_inst = 0;        /* saved copy of previous instruction */
+  unsigned short prev_inst = 0;        /* saved copy of previous instruction */
   unsigned inst = 0;           /* current instruction */
   unsigned entry_inst = 0;     /* the entry instruction */
   unsigned save_inst = 0;      /* the save instruction */
@@ -1508,7 +1661,7 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
          the immediate offset extension from it in mips16_get_imm.  */
       prev_inst = inst;
 
-      /* Fetch and decode the instruction.   */
+      /* Fetch and decode the instruction.  */
       inst = (unsigned short) mips_fetch_instruction (gdbarch, cur_pc);
 
       /* Normally we ignore extend instructions.  However, if it is
@@ -1529,7 +1682,7 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
          || (inst & 0xff00) == 0xfb00) /* daddiu sp */
        {
          offset = mips16_get_imm (prev_inst, inst, 8, 8, 1);
-         if (offset < 0)       /* negative stack adjustment? */
+         if (offset < 0)       /* Negative stack adjustment?  */
            frame_offset -= offset;
          else
            /* Exit loop if a positive stack adjustment is found, which
@@ -1585,10 +1738,10 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
        }
       else if ((inst & 0xf81f) == 0xe809
                && (inst & 0x700) != 0x700)     /* entry */
-       entry_inst = inst;      /* save for later processing */
+       entry_inst = inst;      /* Save for later processing.  */
       else if ((inst & 0xff80) == 0x6480)      /* save */
        {
-         save_inst = inst;     /* save for later processing */
+         save_inst = inst;     /* Save for later processing.  */
          if (prev_extend_bytes)                /* extend */
            save_inst |= prev_inst << 16;
        }
@@ -1614,7 +1767,7 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
      (before the prologue).  But the value of the sp parameter to this
      function is the new SP (after the prologue has been executed).  So we
      can't calculate those offsets until we've seen the entire prologue,
-     and can calculate what the old SP must have been. */
+     and can calculate what the old SP must have been.  */
   if (entry_inst != 0)
     {
       int areg_count = (entry_inst >> 8) & 7;
@@ -1752,7 +1905,7 @@ mips16_scan_prologue (struct gdbarch *gdbarch,
                                    gdbarch_num_regs (gdbarch) + frame_reg)
          + frame_offset - frame_adjust);
       /* FIXME: brobecker/2004-10-10: Just as in the mips32 case, we should
-         be able to get rid of the assignment below, evetually. But it's
+         be able to get rid of the assignment below, evetually.  But it's
          still needed for now.  */
       this_cache->saved_regs[gdbarch_num_regs (gdbarch)
                             + mips_regnum (gdbarch)->pc]
@@ -1842,6 +1995,7 @@ mips_insn16_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind mips_insn16_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   mips_insn16_frame_this_id,
   mips_insn16_frame_prev_register,
   NULL,
@@ -1895,7 +2049,7 @@ reset_saved_regs (struct gdbarch *gdbarch, struct mips_frame_cache *this_cache)
   }
 }
 
-/* Analyze the function prologue from START_PC to LIMIT_PC. Builds
+/* Analyze the function prologue from START_PC to LIMIT_PC.  Builds
    the associated FRAME_CACHE if not null.  
    Return the address of the first instruction past the prologue.  */
 
@@ -1906,7 +2060,8 @@ mips32_scan_prologue (struct gdbarch *gdbarch,
                       struct mips_frame_cache *this_cache)
 {
   CORE_ADDR cur_pc;
-  CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
+  CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for
+                              frame-pointer.  */
   CORE_ADDR sp;
   long frame_offset;
   int  frame_reg = MIPS_SP_REGNUM;
@@ -1937,7 +2092,7 @@ restart:
       unsigned long inst, high_word, low_word;
       int reg;
 
-      /* Fetch the instruction.   */
+      /* Fetch the instruction.  */
       inst = (unsigned long) mips_fetch_instruction (gdbarch, cur_pc);
 
       /* Save some code by pre-extracting some useful fields.  */
@@ -1945,11 +2100,11 @@ restart:
       low_word = inst & 0xffff;
       reg = high_word & 0x1f;
 
-      if (high_word == 0x27bd  /* addiu $sp,$sp,-i */
+      if (high_word == 0x27bd          /* addiu $sp,$sp,-i */
          || high_word == 0x23bd        /* addi $sp,$sp,-i */
          || high_word == 0x67bd)       /* daddiu $sp,$sp,-i */
        {
-         if (low_word & 0x8000)        /* negative stack adjustment? */
+         if (low_word & 0x8000)        /* Negative stack adjustment?  */
             frame_offset += 0x10000 - low_word;
          else
            /* Exit loop if a positive stack adjustment is found, which
@@ -1985,7 +2140,7 @@ restart:
              alloca_adjust = (unsigned) (frame_addr - (sp + low_word));
              if (alloca_adjust > 0)
                {
-                  /* FP > SP + frame_size. This may be because of
+                  /* FP > SP + frame_size.  This may be because of
                      an alloca or somethings similar.  Fix sp to
                      "pre-alloca" value, and try again.  */
                  sp += alloca_adjust;
@@ -2015,7 +2170,7 @@ restart:
              alloca_adjust = (unsigned) (frame_addr - sp);
              if (alloca_adjust > 0)
                {
-                  /* FP > SP + frame_size. This may be because of
+                  /* FP > SP + frame_size.  This may be because of
                      an alloca or somethings similar.  Fix sp to
                      "pre-alloca" value, and try again.  */
                  sp = frame_addr;
@@ -2047,7 +2202,7 @@ restart:
        }
       /* The instructions below load $at or $t0 with an immediate
          value in preparation for a stack adjustment via
-         subu $sp,$sp,[$at,$t0]. These instructions could also
+         subu $sp,$sp,[$at,$t0].  These instructions could also
          initialize a local variable, so we accept them only before
          a stack adjustment instruction was seen.  */
       else if (!seen_sp_adjust
@@ -2059,7 +2214,8 @@ restart:
                    || high_word == 0x3408 /* ori $t0,$zero,n */
                   ))
        {
-          load_immediate_bytes += MIPS_INSN32_SIZE;            /* FIXME!  */
+        if (end_prologue_addr == 0)
+          load_immediate_bytes += MIPS_INSN32_SIZE;            /* FIXME!  */
        }
       else
        {
@@ -2110,7 +2266,7 @@ restart:
     end_prologue_addr = cur_pc;
      
   /* In a frameless function, we might have incorrectly
-     skipped some load immediate instructions. Undo the skipping
+     skipped some load immediate instructions.  Undo the skipping
      if the load immediate was not followed by a stack adjustment.  */
   if (load_immediate_bytes && !seen_sp_adjust)
     end_prologue_addr -= load_immediate_bytes;
@@ -2194,6 +2350,7 @@ mips_insn32_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind mips_insn32_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   mips_insn32_frame_this_id,
   mips_insn32_frame_prev_register,
   NULL,
@@ -2318,6 +2475,7 @@ mips_stub_frame_sniffer (const struct frame_unwind *self,
 static const struct frame_unwind mips_stub_frame_unwind =
 {
   NORMAL_FRAME,
+  default_frame_unwind_stop_reason,
   mips_stub_frame_this_id,
   mips_stub_frame_prev_register,
   NULL,
@@ -2356,6 +2514,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
@@ -2424,14 +2586,14 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch,
        {
        case 0: /* SPECIAL */
          if (rtype_funct (insn) >> 1 == 4) /* JR, JALR */
-           return 0; /* fallback to the standard single-step code. */
+           return 0; /* fallback to the standard single-step code.  */
          break;
        case 1: /* REGIMM */
-         is_branch = ((itype_rt (insn) & 0xc0) == 0); /* B{LT,GE}Z* */
+         is_branch = ((itype_rt (insn) & 0xc) == 0); /* B{LT,GE}Z* */
          break;
        case 2: /* J */
        case 3: /* JAL */
-         return 0; /* fallback to the standard single-step code. */
+         return 0; /* fallback to the standard single-step code.  */
        case 4: /* BEQ */
        case 5: /* BNE */
        case 6: /* BLEZ */
@@ -2472,7 +2634,7 @@ deal_with_atomic_sequence (struct gdbarch *gdbarch,
   breaks[0] = loc;
 
   /* Check for duplicated breakpoints.  Check also for a breakpoint
-     placed (branch instruction's destination) in the atomic sequence */
+     placed (branch instruction's destination) in the atomic sequence */
   if (last_breakpoint && pc <= breaks[1] && breaks[1] <= breaks[0])
     last_breakpoint = 0;
 
@@ -2506,7 +2668,7 @@ mips_software_single_step (struct frame_info *frame)
 }
 
 /* Test whether the PC points to the return instruction at the
-   end of a function. */
+   end of a function.  */
 
 static int
 mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc)
@@ -2550,7 +2712,7 @@ heuristic_proc_start (struct gdbarch *gdbarch, CORE_ADDR pc)
 
   inf = current_inferior ();
 
-  /* search back for previous return */
+  /* Search back for previous return.  */
   for (start_pc -= instlen;; start_pc -= instlen)
     if (start_pc < fence)
       {
@@ -2558,7 +2720,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;
 
@@ -2602,7 +2764,7 @@ heuristic-fence-post' command.\n",
           entry
           addiu sp,-n
           daddiu sp,-n
-          extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'  */
+          extend -n followed by 'addiu sp,+n' or 'daddiu sp,+n'.  */
        inst = mips_fetch_instruction (gdbarch, start_pc);
        if ((inst & 0xff80) == 0x6480)          /* save */
          {
@@ -2646,7 +2808,7 @@ struct mips_objfile_private
    floating-point register (assuming that there is space)?  When there
    is no FPU, FP are not even considered as possible candidates for
    FP registers and, consequently this returns false - forces FP
-   arguments into integer registers. */
+   arguments into integer registers.  */
 
 static int
 fp_register_arg_p (struct gdbarch *gdbarch, enum type_code typecode,
@@ -2663,7 +2825,7 @@ fp_register_arg_p (struct gdbarch *gdbarch, enum type_code typecode,
 }
 
 /* On o32, argument passing in GPRs depends on the alignment of the type being
-   passed.  Return 1 if this type must be aligned to a doubleword boundary. */
+   passed.  Return 1 if this type must be aligned to a doubleword boundary.  */
 
 static int
 mips_type_needs_double_align (struct type *type)
@@ -2753,7 +2915,8 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_eabi_push_dummy_call: struct_return reg=%d %s\n",
+                           "mips_eabi_push_dummy_call: "
+                           "struct_return reg=%d %s\n",
                            argreg, paddress (gdbarch, struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
     }
@@ -2775,9 +2938,25 @@ 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, byte_order,
@@ -2826,23 +3005,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, byte_order);
+             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, byte_order);
+             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
            {
@@ -2850,11 +3029,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, byte_order);
+             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
@@ -2887,7 +3066,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  || fp_register_arg_p (gdbarch, typecode, arg_type))
                {
                  /* Should shorter than int integer values be
-                    promoted to int before being stored? */
+                    promoted to int before being stored?  */
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
@@ -2937,21 +3116,21 @@ 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, byte_order);
+                   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++;
                }
 
              len -= partial_len;
              val += partial_len;
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+             /* Compute the offset into the stack at which we will
+                copy the next parameter.
 
                 In the new EABI (and the NABI32), the stack_offset
                 only needs to be adjusted when it has been used.  */
@@ -3141,7 +3320,8 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_n32n64_push_dummy_call: struct_return reg=%d %s\n",
+                           "mips_n32n64_push_dummy_call: "
+                           "struct_return reg=%d %s\n",
                            argreg, paddress (gdbarch, struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
     }
@@ -3241,7 +3421,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (argreg > MIPS_LAST_ARG_REGNUM (gdbarch))
                {
                  /* Should shorter than int integer values be
-                    promoted to int before being stored? */
+                    promoted to int before being stored?  */
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
@@ -3341,8 +3521,8 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              len -= partial_len;
              val += partial_len;
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+             /* Compute the offset into the stack at which we will
+                copy the next parameter.
 
                 In N32 (N64?), the stack_offset only needs to be
                 adjusted when it has been used.  */
@@ -3379,7 +3559,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
@@ -3390,8 +3570,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
@@ -3481,9 +3660,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;
@@ -3592,7 +3772,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_o32_push_dummy_call: struct_return reg=%d %s\n",
+                           "mips_o32_push_dummy_call: "
+                           "struct_return reg=%d %s\n",
                            argreg, paddress (gdbarch, struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
       stack_offset += MIPS32_REGSIZE;
@@ -3652,7 +3833,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              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_unsigned (regcache,
+                                             float_argreg++, regval);
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
                                    argreg, phex (regval, 4));
@@ -3664,7 +3846,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              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_unsigned (regcache,
+                                             float_argreg++, regval);
 
              if (mips_debug)
                fprintf_unfiltered (gdb_stdlog, " - reg=%d val=%s",
@@ -3681,7 +3864,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              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_unsigned (regcache,
+                                             float_argreg++, regval);
              /* Although two FP registers are reserved for each
                 argument, only one corresponding integer register is
                 reserved.  */
@@ -3730,7 +3914,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  || odd_sized_struct)
                {
                  /* Should shorter than int integer values be
-                    promoted to int before being stored? */
+                    promoted to int before being stored?  */
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
@@ -3817,8 +4001,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              len -= partial_len;
              val += partial_len;
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+             /* Compute the offset into the stack at which we will
+                copy the next parameter.
 
                 In older ABIs, the caller reserved space for
                 registers that contained arguments.  This was loosely
@@ -4053,7 +4237,8 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
     {
       if (mips_debug)
        fprintf_unfiltered (gdb_stdlog,
-                           "mips_o64_push_dummy_call: struct_return reg=%d %s\n",
+                           "mips_o64_push_dummy_call: "
+                           "struct_return reg=%d %s\n",
                            argreg, paddress (gdbarch, struct_addr));
       regcache_cooked_write_unsigned (regcache, argreg++, struct_addr);
       stack_offset += MIPS64_REGSIZE;
@@ -4065,6 +4250,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);
@@ -4077,6 +4263,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
@@ -4129,7 +4330,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                  || odd_sized_struct)
                {
                  /* Should shorter than int integer values be
-                    promoted to int before being stored? */
+                    promoted to int before being stored?  */
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
@@ -4184,7 +4385,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     big endian targets.
 
                     It does not seem to be necessary to do the
-                    same for integral types. */
+                    same for integral types.  */
 
                  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
                      && partial_len < MIPS64_REGSIZE
@@ -4208,8 +4409,8 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              len -= partial_len;
              val += partial_len;
 
-             /* Compute the the offset into the stack at which we
-                will copy the next parameter.
+             /* Compute the offset into the stack at which we will
+                copy the next parameter.
 
                 In older ABIs, the caller reserved space for
                 registers that contained arguments.  This was loosely
@@ -4257,7 +4458,7 @@ mips_o64_return_value (struct gdbarch *gdbarch, struct type *func_type,
   else
     {
       /* A scalar extract each part but least-significant-byte
-         justified. */
+         justified.  */
       int offset;
       int regnum;
       for (offset = 0, regnum = MIPS_V0_REGNUM;
@@ -4304,7 +4505,7 @@ mips_o64_return_value (struct gdbarch *gdbarch, struct type *func_type,
 
    Note that this code only deals with "live" registers at the top of the
    stack.  We will attempt to deal with saved registers later, when
-   the raw/cooked register interface is in place. (We need a general
+   the raw/cooked register interface is in place.  (We need a general
    interface that can deal with dynamic saved register sizes -- fp
    regs could be 32 bits wide in one frame and 64 on the frame above
    and below).  */
@@ -4388,13 +4589,14 @@ mips_read_fp_register_double (struct frame_info *frame, int regno,
 static void
 mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
                        int regnum)
-{                              /* do values for FP (float) regs */
+{                              /* Do values for FP (float) regs.  */
   struct gdbarch *gdbarch = get_frame_arch (frame);
   gdb_byte *raw_buffer;
-  double doub, flt1;   /* doubles extracted from raw hex data */
+  double doub, flt1;   /* Doubles extracted from raw hex data.  */
   int inv1, inv2;
 
-  raw_buffer = alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0));
+  raw_buffer = alloca (2 * register_size (gdbarch,
+                                         mips_regnum (gdbarch)->fp0));
 
   fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
   fprintf_filtered (file, "%*s",
@@ -4408,7 +4610,8 @@ mips_print_fp_register (struct ui_file *file, struct frame_info *frame,
       /* 4-byte registers: Print hex and floating.  Also print even
          numbered registers as doubles.  */
       mips_read_fp_register_single (frame, regnum, raw_buffer);
-      flt1 = unpack_double (builtin_type (gdbarch)->builtin_float, raw_buffer, &inv1);
+      flt1 = unpack_double (builtin_type (gdbarch)->builtin_float,
+                           raw_buffer, &inv1);
 
       get_formatted_print_options (&opts, 'x');
       print_scalar_formatted (raw_buffer,
@@ -4471,9 +4674,9 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
                     int regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  gdb_byte raw_buffer[MAX_REGISTER_SIZE];
   int offset;
   struct value_print_options opts;
+  struct value *val;
 
   if (TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
     {
@@ -4481,8 +4684,8 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
       return;
     }
 
-  /* Get the data in raw format.  */
-  if (!frame_register_read (frame, regnum, raw_buffer))
+  val = get_frame_register_value (frame, regnum);
+  if (value_optimized_out (val))
     {
       fprintf_filtered (file, "%s: [Invalid]",
                        gdbarch_register_name (gdbarch, regnum));
@@ -4500,16 +4703,12 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
   else
     fprintf_filtered (file, ": ");
 
-  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
-    offset =
-      register_size (gdbarch, regnum) - register_size (gdbarch, regnum);
-  else
-    offset = 0;
-
   get_formatted_print_options (&opts, 'x');
-  print_scalar_formatted (raw_buffer + offset,
-                         register_type (gdbarch, regnum), &opts, 0,
-                         file);
+  val_print_scalar_formatted (value_type (val),
+                             value_contents_for_printing (val),
+                             value_embedded_offset (val),
+                             val,
+                             &opts, 0, file);
 }
 
 /* Replacement for generic do_registers_info.
@@ -4526,20 +4725,21 @@ print_fp_register_row (struct ui_file *file, struct frame_info *frame,
 }
 
 
-/* Print a row's worth of GP (int) registers, with name labels above */
+/* Print a row's worth of GP (int) registers, with name labels above */
 
 static int
 print_gp_register_row (struct ui_file *file, struct frame_info *frame,
                       int start_regnum)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  /* do values for GP (int) regs */
+  /* Do values for GP (int) regs.  */
   gdb_byte raw_buffer[MAX_REGISTER_SIZE];
-  int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8);       /* display cols per row */
+  int ncols = (mips_abi_regsize (gdbarch) == 8 ? 4 : 8);    /* display cols
+                                                              per row.  */
   int col, byte;
   int regnum;
 
-  /* For GP registers, we print a separate row of names above the vals */
+  /* For GP registers, we print a separate row of names above the vals */
   for (col = 0, regnum = start_regnum;
        col < ncols && regnum < gdbarch_num_regs (gdbarch)
                               + gdbarch_num_pseudo_regs (gdbarch);
@@ -4549,7 +4749,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
        continue;               /* unused register */
       if (TYPE_CODE (register_type (gdbarch, regnum)) ==
          TYPE_CODE_FLT)
-       break;                  /* end the row: reached FP register */
+       break;                  /* End the row: reached FP register.  */
       /* Large registers are handled separately.  */
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
        {
@@ -4572,14 +4772,14 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
   if (col == 0)
     return regnum;
 
-  /* print the R0 to R31 names */
+  /* Print the R0 to R31 names.  */
   if ((start_regnum % gdbarch_num_regs (gdbarch)) < MIPS_NUMREGS)
     fprintf_filtered (file, "\n R%-4d",
                      start_regnum % gdbarch_num_regs (gdbarch));
   else
     fprintf_filtered (file, "\n      ");
 
-  /* now print the values in hex, 4 or 8 to the row */
+  /* Now print the values in hex, 4 or 8 to the row.  */
   for (col = 0, regnum = start_regnum;
        col < ncols && regnum < gdbarch_num_regs (gdbarch)
                               + gdbarch_num_pseudo_regs (gdbarch);
@@ -4589,7 +4789,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
        continue;               /* unused register */
       if (TYPE_CODE (register_type (gdbarch, regnum)) ==
          TYPE_CODE_FLT)
-       break;                  /* end row: reached FP register */
+       break;                  /* End row: reached FP register.  */
       if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
        break;                  /* End row: large register.  */
 
@@ -4602,7 +4802,7 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
           byte < (mips_abi_regsize (gdbarch)
                   - register_size (gdbarch, regnum)); byte++)
        printf_filtered ("  ");
-      /* Now print the register value in hex, endian order. */
+      /* Now print the register value in hex, endian order.  */
       if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
        for (byte =
             register_size (gdbarch, regnum) - register_size (gdbarch, regnum);
@@ -4615,19 +4815,19 @@ print_gp_register_row (struct ui_file *file, struct frame_info *frame,
       fprintf_filtered (file, " ");
       col++;
     }
-  if (col > 0)                 /* ie. if we actually printed anything... */
+  if (col > 0)                 /* ie. if we actually printed anything...  */
     fprintf_filtered (file, "\n");
 
   return regnum;
 }
 
-/* MIPS_DO_REGISTERS_INFO(): called by "info register" command */
+/* MIPS_DO_REGISTERS_INFO(): called by "info register" command */
 
 static void
 mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
                           struct frame_info *frame, int regnum, int all)
 {
-  if (regnum != -1)            /* do one specified register */
+  if (regnum != -1)            /* Do one specified register.  */
     {
       gdb_assert (regnum >= gdbarch_num_regs (gdbarch));
       if (*(gdbarch_register_name (gdbarch, regnum)) == '\0')
@@ -4637,7 +4837,7 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
       fprintf_filtered (file, "\n");
     }
   else
-    /* do all (or most) registers */
+    /* Do all (or most) registers.  */
     {
       regnum = gdbarch_num_regs (gdbarch);
       while (regnum < gdbarch_num_regs (gdbarch)
@@ -4646,10 +4846,10 @@ mips_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
          if (TYPE_CODE (register_type (gdbarch, regnum)) ==
              TYPE_CODE_FLT)
            {
-             if (all)          /* true for "INFO ALL-REGISTERS" command */
+             if (all)          /* True for "INFO ALL-REGISTERS" command.  */
                regnum = print_fp_register_row (file, frame, regnum);
              else
-               regnum += MIPS_NUMREGS; /* skip floating point regs */
+               regnum += MIPS_NUMREGS; /* Skip floating point regs.  */
            }
          else
            regnum = print_gp_register_row (file, frame, regnum);
@@ -4826,7 +5026,7 @@ mips_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
     return mips32_in_function_epilogue_p (gdbarch, pc);
 }
 
-/* Root of all "set mips "/"show mips " commands. This will eventually be
+/* Root of all "set mips "/"show mips " commands.  This will eventually be
    used for all MIPS-specific commands.  */
 
 static void
@@ -4873,9 +5073,9 @@ show_mipsfpu_command (char *args, int from_tty)
       internal_error (__FILE__, __LINE__, _("bad switch"));
     }
   if (mips_fpu_type_auto)
-    printf_unfiltered
-      ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
-       fpu);
+    printf_unfiltered ("The MIPS floating-point coprocessor "
+                      "is set automatically (currently %s)\n",
+                      fpu);
   else
     printf_unfiltered
       ("The MIPS floating-point coprocessor is assumed to be %s\n", fpu);
@@ -4885,8 +5085,8 @@ show_mipsfpu_command (char *args, int from_tty)
 static void
 set_mipsfpu_command (char *args, int from_tty)
 {
-  printf_unfiltered
-    ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
+  printf_unfiltered ("\"set mipsfpu\" must be followed by \"double\", "
+                    "\"single\",\"none\" or \"auto\".\n");
   show_mipsfpu_command (args, from_tty);
 }
 
@@ -5018,15 +5218,16 @@ gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info)
   return gdb_print_insn_mips (memaddr, info);
 }
 
-/* This function implements gdbarch_breakpoint_from_pc.  It uses the program
-   counter value to determine whether a 16- or 32-bit breakpoint should be used.
-   It returns a pointer to a string of bytes that encode a breakpoint
-   instruction, stores the length of the string to *lenptr, and adjusts pc (if
-   necessary) to point to the actual memory location where the breakpoint
-   should be inserted.  */
+/* This function implements gdbarch_breakpoint_from_pc.  It uses the
+   program counter value to determine whether a 16- or 32-bit breakpoint
+   should be used.  It returns a pointer to a string of bytes that encode a
+   breakpoint instruction, stores the length of the string to *lenptr, and
+   adjusts pc (if necessary) to point to the actual memory location where
+   the breakpoint should be inserted.  */
 
 static const gdb_byte *
-mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
+mips_breakpoint_from_pc (struct gdbarch *gdbarch,
+                        CORE_ADDR *pcptr, int *lenptr)
 {
   if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
     {
@@ -5045,6 +5246,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);
 
@@ -5054,6 +5258,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;
        }
@@ -5087,6 +5293,236 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
     }
 }
 
+/* Return non-zero if the ADDR instruction has a branch delay slot
+   (i.e. it is a jump or branch instruction).  This function is based
+   on mips32_next_pc.  */
+
+static int
+mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr)
+{
+  gdb_byte buf[MIPS_INSN32_SIZE];
+  unsigned long inst;
+  int status;
+  int op;
+
+  status = target_read_memory (addr, buf, MIPS_INSN32_SIZE);
+  if (status)
+    return 0;
+
+  inst = mips_fetch_instruction (gdbarch, addr);
+  op = itype_op (inst);
+  if ((inst & 0xe0000000) != 0)
+    return (op >> 2 == 5       /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx  */
+           || op == 29         /* JALX: bits 011101  */
+           || (op == 17 && itype_rs (inst) == 8));
+                               /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000  */
+  else
+    switch (op & 0x07)         /* extract bits 28,27,26  */
+      {
+      case 0:                  /* SPECIAL  */
+       op = rtype_funct (inst);
+       return (op == 8         /* JR  */
+               || op == 9);    /* JALR  */
+       break;                  /* end SPECIAL  */
+      case 1:                  /* REGIMM  */
+       op = itype_rt (inst);   /* branch condition  */
+       return (op & 0xc) == 0;
+                               /* BLTZ, BLTZL, BGEZ, BGEZL: bits 000xx  */
+                               /* BLTZAL, BLTZALL, BGEZAL, BGEZALL: 100xx  */
+       break;                  /* end REGIMM  */
+      default:                 /* J, JAL, BEQ, BNE, BLEZ, BGTZ  */
+       return 1;
+       break;
+      }
+}
+
+/* Return non-zero if the ADDR instruction, which must be a 32-bit
+   instruction if MUSTBE32 is set or can be any instruction otherwise,
+   has a branch delay slot (i.e. it is a non-compact jump instruction).  */
+
+static int
+mips16_instruction_has_delay_slot (struct gdbarch *gdbarch, CORE_ADDR addr,
+                                  int mustbe32)
+{
+  gdb_byte buf[MIPS_INSN16_SIZE];
+  unsigned short inst;
+  int status;
+
+  status = target_read_memory (addr, buf, MIPS_INSN16_SIZE);
+  if (status)
+    return 0;
+
+  inst = mips_fetch_instruction (gdbarch, addr);
+  if (!mustbe32)
+    return (inst & 0xf89f) == 0xe800;  /* JR/JALR (16-bit instruction)  */
+  return (inst & 0xf800) == 0x1800;    /* JAL/JALX (32-bit instruction)  */
+}
+
+/* Calculate the starting address of the MIPS memory segment BPADDR is in.
+   This assumes KSSEG exists.  */
+
+static CORE_ADDR
+mips_segment_boundary (CORE_ADDR bpaddr)
+{
+  CORE_ADDR mask = CORE_ADDR_MAX;
+  int segsize;
+
+  if (sizeof (CORE_ADDR) == 8)
+    /* Get the topmost two bits of bpaddr in a 32-bit safe manner (avoid
+       a compiler warning produced where CORE_ADDR is a 32-bit type even
+       though in that case this is dead code).  */
+    switch (bpaddr >> ((sizeof (CORE_ADDR) << 3) - 2) & 3)
+      {
+      case 3:
+       if (bpaddr == (bfd_signed_vma) (int32_t) bpaddr)
+         segsize = 29;                 /* 32-bit compatibility segment  */
+       else
+         segsize = 62;                 /* xkseg  */
+       break;
+      case 2:                          /* xkphys  */
+       segsize = 59;
+       break;
+      default:                         /* xksseg (1), xkuseg/kuseg (0)  */
+       segsize = 62;
+       break;
+      }
+  else if (bpaddr & 0x80000000)                /* kernel segment  */
+    segsize = 29;
+  else
+    segsize = 31;                      /* user segment  */
+  mask <<= segsize;
+  return bpaddr & mask;
+}
+
+/* Move the breakpoint at BPADDR out of any branch delay slot by shifting
+   it backwards if necessary.  Return the address of the new location.  */
+
+static CORE_ADDR
+mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
+{
+  CORE_ADDR prev_addr, next_addr;
+  CORE_ADDR boundary;
+  CORE_ADDR func_addr;
+
+  /* If a breakpoint is set on the instruction in a branch delay slot,
+     GDB gets confused.  When the breakpoint is hit, the PC isn't on
+     the instruction in the branch delay slot, the PC will point to
+     the branch instruction.  Since the PC doesn't match any known
+     breakpoints, GDB reports a trap exception.
+
+     There are two possible fixes for this problem.
+
+     1) When the breakpoint gets hit, see if the BD bit is set in the
+     Cause register (which indicates the last exception occurred in a
+     branch delay slot).  If the BD bit is set, fix the PC to point to
+     the instruction in the branch delay slot.
+
+     2) When the user sets the breakpoint, don't allow him to set the
+     breakpoint on the instruction in the branch delay slot.  Instead
+     move the breakpoint to the branch instruction (which will have
+     the same result).
+
+     The problem with the first solution is that if the user then
+     single-steps the processor, the branch instruction will get
+     skipped (since GDB thinks the PC is on the instruction in the
+     branch delay slot).
+
+     So, we'll use the second solution.  To do this we need to know if
+     the instruction we're trying to set the breakpoint on is in the
+     branch delay slot.  */
+
+  boundary = mips_segment_boundary (bpaddr);
+
+  /* Make sure we don't scan back before the beginning of the current
+     function, since we may fetch constant data or insns that look like
+     a jump.  Of course we might do that anyway if the compiler has
+     moved constants inline. :-(  */
+  if (find_pc_partial_function (bpaddr, NULL, &func_addr, NULL)
+      && func_addr > boundary && func_addr <= bpaddr)
+    boundary = func_addr;
+
+  if (!mips_pc_is_mips16 (bpaddr))
+    {
+      if (bpaddr == boundary)
+       return bpaddr;
+
+      /* If the previous instruction has a branch delay slot, we have
+         to move the breakpoint to the branch instruction. */
+      prev_addr = bpaddr - 4;
+      if (mips32_instruction_has_delay_slot (gdbarch, prev_addr))
+       bpaddr = prev_addr;
+    }
+  else
+    {
+      struct minimal_symbol *sym;
+      CORE_ADDR addr, jmpaddr;
+      int i;
+
+      boundary = unmake_mips16_addr (boundary);
+
+      /* The only MIPS16 instructions with delay slots are JAL, JALX,
+         JALR and JR.  An absolute JAL/JALX is always 4 bytes long,
+         so try for that first, then try the 2 byte JALR/JR.
+         FIXME: We have to assume that bpaddr is not the second half
+         of an extended instruction.  */
+
+      jmpaddr = 0;
+      addr = bpaddr;
+      for (i = 1; i < 4; i++)
+       {
+         if (unmake_mips16_addr (addr) == boundary)
+           break;
+         addr -= 2;
+         if (i == 1 && mips16_instruction_has_delay_slot (gdbarch, addr, 0))
+           /* Looks like a JR/JALR at [target-1], but it could be
+              the second word of a previous JAL/JALX, so record it
+              and check back one more.  */
+           jmpaddr = addr;
+         else if (i > 1
+                  && mips16_instruction_has_delay_slot (gdbarch, addr, 1))
+           {
+             if (i == 2)
+               /* Looks like a JAL/JALX at [target-2], but it could also
+                  be the second word of a previous JAL/JALX, record it,
+                  and check back one more.  */
+               jmpaddr = addr;
+             else
+               /* Looks like a JAL/JALX at [target-3], so any previously
+                  recorded JAL/JALX or JR/JALR must be wrong, because:
+
+                  >-3: JAL
+                   -2: JAL-ext (can't be JAL/JALX)
+                   -1: bdslot (can't be JR/JALR)
+                    0: target insn
+
+                  Of course it could be another JAL-ext which looks
+                  like a JAL, but in that case we'd have broken out
+                  of this loop at [target-2]:
+
+                   -4: JAL
+                  >-3: JAL-ext
+                   -2: bdslot (can't be jmp)
+                   -1: JR/JALR
+                    0: target insn  */
+               jmpaddr = 0;
+           }
+         else
+           {
+             /* Not a jump instruction: if we're at [target-1] this
+                could be the second word of a JAL/JALX, so continue;
+                otherwise we're done.  */
+             if (i > 1)
+               break;
+           }
+       }
+
+      if (jmpaddr)
+       bpaddr = jmpaddr;
+    }
+
+  return bpaddr;
+}
+
 /* If PC is in a mips16 call or return stub, return the address of the target
    PC, which is either the callee or the caller.  There are several
    cases which must be handled:
@@ -5097,7 +5533,7 @@ mips_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
    and the target PC is in $2.
    * If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
    before the jal instruction, this is effectively a call stub
-   and the the target PC is in $2.  Otherwise this is effectively
+   and the target PC is in $2.  Otherwise this is effectively
    a return stub and the target PC is in $18.
 
    See the source code for the stubs in gcc/config/mips/mips16.S for
@@ -5107,7 +5543,7 @@ static CORE_ADDR
 mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  char *name;
+  const char *name;
   CORE_ADDR start_addr;
 
   /* Find the starting address and name of the function containing the PC.  */
@@ -5129,7 +5565,7 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
 
       /* If the PC at the start of __mips16_call_stub_{s,d}f_{0..10}, i.e.
          before the jal instruction, this is effectively a call stub
-         and the the target PC is in $2.  Otherwise this is effectively
+         and the target PC is in $2.  Otherwise this is effectively
          a return stub and the target PC is in $18.  */
       else if (name[19] == 's' || name[19] == 'd')
        {
@@ -5148,7 +5584,6 @@ mips_skip_mips16_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
                 address from those two instructions.  */
 
              CORE_ADDR target_pc = get_frame_register_signed (frame, 2);
-             ULONGEST inst;
              int i;
 
              /* See if the name of the target function is  __fn_stub_*.  */
@@ -5165,11 +5600,15 @@ 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 (gdbarch, target_pc);
+                 ULONGEST inst = mips_fetch_instruction (gdbarch, target_pc);
+                 CORE_ADDR addr = inst;
+
                  if ((inst & 0xffff0000) == 0x3c010000)        /* lui $at */
-                   pc = (inst << 16) & 0xffff0000;     /* high word */
+                   pc = (((addr & 0xffff) ^ 0x8000) - 0x8000) << 16;
+                                                               /* high word */
                  else if ((inst & 0xffff0000) == 0x24210000)   /* addiu $at */
-                   return pc | (inst & 0xffff);        /* low word */
+                   return pc + ((addr & 0xffff) ^ 0x8000) - 0x8000;
+                                                               /* low word */
                }
 
              /* Couldn't find the lui/addui pair, so return stub address.  */
@@ -5317,7 +5756,8 @@ mips_register_sim_regno (struct gdbarch *gdbarch, int regnum)
   if (gdbarch_register_name (gdbarch,
                             gdbarch_num_regs (gdbarch) + regnum) != NULL
       && gdbarch_register_name (gdbarch,
-                               gdbarch_num_regs (gdbarch) + regnum)[0] != '\0')
+                               gdbarch_num_regs (gdbarch)
+                               + regnum)[0] != '\0')
     return regnum;
   else
     return LEGACY_SIM_REGNO_IGNORE;
@@ -5640,7 +6080,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Also used when doing an architecture lookup.  */
   if (gdbarch_debug)
     fprintf_unfiltered (gdb_stdlog,
-                       "mips_gdbarch_init: mips64_transfers_32bit_regs_p = %d\n",
+                       "mips_gdbarch_init: "
+                       "mips64_transfers_32bit_regs_p = %d\n",
                        mips64_transfers_32bit_regs_p);
 
   /* Determine the MIPS FPU type.  */
@@ -5709,7 +6150,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       return NULL;
     }
 
-  /* try to find a pre-existing architecture */
+  /* Try to find a pre-existing architecture.  */
   for (arches = gdbarch_list_lookup_by_info (arches, &info);
        arches != NULL;
        arches = gdbarch_list_lookup_by_info (arches->next, &info))
@@ -5744,6 +6185,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)
     {
@@ -5770,6 +6215,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);
 
@@ -5928,8 +6378,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
     Note that for o32 and eabi32, pointers are always 32 bits
     regardless of any -mlongXX option.  For all others, pointers and
-    longs are the same, as set by -mlongXX or set by defaults.
- */
+    longs are the same, as set by -mlongXX or set by defaults.  */
 
   if (info.abfd != NULL)
     {
@@ -5997,7 +6446,7 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                    mips_dwarf_dwarf2_ecoff_reg_to_regnum);
   set_gdbarch_register_sim_regno (gdbarch, mips_register_sim_regno);
 
-  /* MIPS version of CALL_DUMMY */
+  /* MIPS version of CALL_DUMMY */
 
   /* NOTE: cagney/2003-08-05: Eventually call dummy location will be
      replaced by a command, and all targets will default to on stack
@@ -6011,6 +6460,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
+  set_gdbarch_adjust_breakpoint_address (gdbarch,
+                                        mips_adjust_breakpoint_address);
 
   set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
 
@@ -6041,7 +6492,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_skip_trampoline_code (gdbarch, mips_skip_trampoline_code);
 
-  set_gdbarch_single_step_through_delay (gdbarch, mips_single_step_through_delay);
+  set_gdbarch_single_step_through_delay (gdbarch,
+                                        mips_single_step_through_delay);
 
   /* Virtual tables.  */
   set_gdbarch_vbit_in_delta (gdbarch, 1);
@@ -6070,7 +6522,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* Override the normal target description methods to handle our
         dual real and pseudo registers.  */
       set_gdbarch_register_name (gdbarch, mips_register_name);
-      set_gdbarch_register_reggroup_p (gdbarch, mips_tdesc_register_reggroup_p);
+      set_gdbarch_register_reggroup_p (gdbarch,
+                                      mips_tdesc_register_reggroup_p);
 
       num_regs = gdbarch_num_regs (gdbarch);
       set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
@@ -6144,9 +6597,9 @@ show_mips_abi (struct ui_file *file,
       else
        {
          /* Probably shouldn't happen...  */
-         fprintf_filtered
-           (file,
-            "The (auto detected) MIPS ABI \"%s\" is in use even though the user setting was \"%s\".\n",
+         fprintf_filtered (file,
+                           "The (auto detected) MIPS ABI \"%s\" is in use "
+                           "even though the user setting was \"%s\".\n",
             actual_abi_str, mips_abi_strings[global_abi]);
        }
     }
@@ -6194,7 +6647,8 @@ mips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
                          "mips_dump_tdep: tdep->mips_abi = %d (%s)\n",
                          tdep->mips_abi, mips_abi_strings[tdep->mips_abi]);
       fprintf_unfiltered (file,
-                         "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
+                         "mips_dump_tdep: "
+                         "mips_mask_address_p() %d (default %d)\n",
                          mips_mask_address_p (tdep),
                          tdep->default_mask_address_p);
     }
@@ -6216,7 +6670,7 @@ mips_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
                       : "???"));
 }
 
-extern initialize_file_ftype _initialize_mips_tdep;    /* -Wmissing-prototypes */
+extern initialize_file_ftype _initialize_mips_tdep; /* -Wmissing-prototypes */
 
 void
 _initialize_mips_tdep (void)
@@ -6241,7 +6695,7 @@ _initialize_mips_tdep (void)
   mips_tdesc_gp64 = allocate_target_description ();
   set_tdesc_property (mips_tdesc_gp64, PROPERTY_GP64, "");
 
-  /* Add root prefix command for all "set mips"/"show mips" commands */
+  /* Add root prefix command for all "set mips"/"show mips" commands */
   add_prefix_cmd ("mips", no_class, set_mips_command,
                  _("Various MIPS specific commands."),
                  &setmipscmdlist, "set mips ", 0, &setlist);
@@ -6250,7 +6704,7 @@ _initialize_mips_tdep (void)
                  _("Various MIPS specific commands."),
                  &showmipscmdlist, "show mips ", 0, &showlist);
 
-  /* Allow the user to override the ABI. */
+  /* Allow the user to override the ABI.  */
   add_setshow_enum_cmd ("abi", class_obscure, mips_abi_strings,
                        &mips_abi_string, _("\
 Set the MIPS ABI used by this program."), _("\
@@ -6305,7 +6759,8 @@ If you are debugging a stripped executable, GDB needs to search through the\n\
 program for the start of a function.  This command sets the distance of the\n\
 search.  The only need to set it is when debugging a stripped executable."),
                            reinit_frame_cache_sfunc,
-                           NULL, /* FIXME: i18n: The distance searched for the start of a function is %s.  */
+                           NULL, /* FIXME: i18n: The distance searched for
+                                    the start of a function is %s.  */
                            &setlist, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
@@ -6314,7 +6769,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);
@@ -6331,16 +6786,19 @@ 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, /* FIXME: i18n: Compatibility with 64-bit MIPS target that transfers 32-bit quantities is %s.  */
+                          NULL, /* FIXME: i18n: Compatibility with 64-bit
+                                   MIPS target that transfers 32-bit
+                                   quantities is %s.  */
                           &setlist, &showlist);
 
-  /* Debug this files internals. */
+  /* Debug this files internals.  */
   add_setshow_zinteger_cmd ("mips", class_maintenance,
                            &mips_debug, _("\
 Set mips debugging."), _("\
 Show mips debugging."), _("\
 When non-zero, mips specific debugging is enabled."),
                            NULL,
-                           NULL, /* FIXME: i18n: Mips debugging is currently %s.  */
+                           NULL, /* FIXME: i18n: Mips debugging is
+                                    currently %s.  */
                            &setdebuglist, &showdebuglist);
 }
This page took 0.051727 seconds and 4 git commands to generate.