* macrotab.h: Do not include "obstack.h" or "bcache.h".
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 277eb358dc2b663a41fedfed3cd8e56f4be60b30..fb46b0262ac3f05107b2bb35f3bf8b417b567f9e 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
 
    Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
-   1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   1997, 1998, 1999, 2000, 2001, 2002 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.
 
    Contributed by Alessandro Forin(af@cs.cmu.edu) at CMU
    and by Per Bothner(bothner@cs.wisc.edu) at U.Wisconsin.
 #include "gdbtypes.h"
 #include "target.h"
 #include "arch-utils.h"
 #include "gdbtypes.h"
 #include "target.h"
 #include "arch-utils.h"
+#include "regcache.h"
+#include "osabi.h"
 
 #include "opcode/mips.h"
 #include "elf/mips.h"
 #include "elf-bfd.h"
 #include "symcat.h"
 
 
 #include "opcode/mips.h"
 #include "elf/mips.h"
 #include "elf-bfd.h"
 #include "symcat.h"
 
+/* A useful bit in the CP0 status register (PS_REGNUM).  */
+/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip.  */
+#define ST0_FR (1 << 26)
+
 /* The sizes of floating point registers.  */
 
 enum
 /* The sizes of floating point registers.  */
 
 enum
@@ -55,14 +61,27 @@ enum
 
 enum mips_abi
   {
 
 enum mips_abi
   {
-    MIPS_ABI_UNKNOWN,
+    MIPS_ABI_UNKNOWN = 0,
     MIPS_ABI_N32,
     MIPS_ABI_O32,
     MIPS_ABI_O64,
     MIPS_ABI_EABI32,
     MIPS_ABI_N32,
     MIPS_ABI_O32,
     MIPS_ABI_O64,
     MIPS_ABI_EABI32,
-    MIPS_ABI_EABI64
+    MIPS_ABI_EABI64,
+    MIPS_ABI_LAST
   };
 
   };
 
+static const char *mips_abi_string;
+
+static const char *mips_abi_strings[] = {
+  "auto",
+  "n32",
+  "o32",
+  "o64",
+  "eabi32",
+  "eabi64",
+  NULL
+};
+
 struct frame_extra_info
   {
     mips_extra_func_info_t proc_desc;
 struct frame_extra_info
   {
     mips_extra_func_info_t proc_desc;
@@ -100,12 +119,6 @@ enum mips_fpu_type
 #endif
 static int mips_fpu_type_auto = 1;
 static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
 #endif
 static int mips_fpu_type_auto = 1;
 static enum mips_fpu_type mips_fpu_type = MIPS_DEFAULT_FPU_TYPE;
-#define MIPS_FPU_TYPE mips_fpu_type
-
-/* Do not use "TARGET_IS_MIPS64" to test the size of floating point registers */
-#ifndef FP_REGISTER_DOUBLE
-#define FP_REGISTER_DOUBLE (REGISTER_VIRTUAL_SIZE(FP0_REGNUM) == 8)
-#endif
 
 static int mips_debug = 0;
 
 
 static int mips_debug = 0;
 
@@ -114,9 +127,10 @@ struct gdbarch_tdep
   {
     /* from the elf header */
     int elf_flags;
   {
     /* from the elf header */
     int elf_flags;
+
     /* mips options */
     enum mips_abi mips_abi;
     /* mips options */
     enum mips_abi mips_abi;
-    const char *mips_abi_string;
+    enum mips_abi found_abi;
     enum mips_fpu_type mips_fpu_type;
     int mips_last_arg_regnum;
     int mips_last_fp_arg_regnum;
     enum mips_fpu_type mips_fpu_type;
     int mips_last_arg_regnum;
     int mips_last_fp_arg_regnum;
@@ -126,37 +140,22 @@ struct gdbarch_tdep
     int mips_default_stack_argsize;
     int gdb_target_is_mips64;
     int default_mask_address_p;
     int mips_default_stack_argsize;
     int gdb_target_is_mips64;
     int default_mask_address_p;
+
+    enum gdb_osabi osabi;
   };
 
   };
 
-#if GDB_MULTI_ARCH
-#undef MIPS_EABI
 #define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
                   || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
 #define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
                   || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
-#endif
 
 
-#if GDB_MULTI_ARCH
-#undef MIPS_LAST_FP_ARG_REGNUM
 #define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
 #define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
-#endif
 
 
-#if GDB_MULTI_ARCH
-#undef MIPS_LAST_ARG_REGNUM
 #define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum)
 #define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum)
-#endif
 
 
-#if GDB_MULTI_ARCH
-#undef MIPS_FPU_TYPE
 #define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->mips_fpu_type)
 #define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->mips_fpu_type)
-#endif
 
 /* Return the currently configured (or set) saved register size. */
 
 
 /* Return the currently configured (or set) saved register size. */
 
-#if GDB_MULTI_ARCH
-#undef MIPS_DEFAULT_SAVED_REGSIZE
 #define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize)
 #define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize)
-#elif !defined (MIPS_DEFAULT_SAVED_REGSIZE)
-#define MIPS_DEFAULT_SAVED_REGSIZE MIPS_REGSIZE
-#endif
 
 static const char *mips_saved_regsize_string = size_auto;
 
 
 static const char *mips_saved_regsize_string = size_auto;
 
@@ -173,36 +172,48 @@ mips_saved_regsize (void)
     return 4;
 }
 
     return 4;
 }
 
+/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
+   compatiblity mode.  A return value of 1 means that we have
+   physical 64-bit registers, but should treat them as 32-bit registers.  */
+
+static int
+mips2_fp_compat (void)
+{
+  /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
+     meaningful.  */
+  if (REGISTER_RAW_SIZE (FP0_REGNUM) == 4)
+    return 0;
+
+#if 0
+  /* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
+     in all the places we deal with FP registers.  PR gdb/413.  */
+  /* Otherwise check the FR bit in the status register - it controls
+     the FP compatiblity mode.  If it is clear we are in compatibility
+     mode.  */
+  if ((read_register (PS_REGNUM) & ST0_FR) == 0)
+    return 1;
+#endif
+
+  return 0;
+}
+
 /* Indicate that the ABI makes use of double-precision registers
    provided by the FPU (rather than combining pairs of registers to
    form double-precision values).  Do not use "TARGET_IS_MIPS64" to
    determine if the ABI is using double-precision registers.  See also
    MIPS_FPU_TYPE. */
 /* Indicate that the ABI makes use of double-precision registers
    provided by the FPU (rather than combining pairs of registers to
    form double-precision values).  Do not use "TARGET_IS_MIPS64" to
    determine if the ABI is using double-precision registers.  See also
    MIPS_FPU_TYPE. */
-#if GDB_MULTI_ARCH
-#undef FP_REGISTER_DOUBLE
 #define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
 #define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
-#endif
 
 /* Does the caller allocate a ``home'' for each register used in the
    function call?  The N32 ABI and MIPS_EABI do not, the others do. */
 
 
 /* Does the caller allocate a ``home'' for each register used in the
    function call?  The N32 ABI and MIPS_EABI do not, the others do. */
 
-#if GDB_MULTI_ARCH
-#undef MIPS_REGS_HAVE_HOME_P
 #define MIPS_REGS_HAVE_HOME_P (gdbarch_tdep (current_gdbarch)->mips_regs_have_home_p)
 #define MIPS_REGS_HAVE_HOME_P (gdbarch_tdep (current_gdbarch)->mips_regs_have_home_p)
-#elif !defined (MIPS_REGS_HAVE_HOME_P)
-#define MIPS_REGS_HAVE_HOME_P (!MIPS_EABI)
-#endif
 
 /* The amount of space reserved on the stack for registers. This is
    different to MIPS_SAVED_REGSIZE as it determines the alignment of
    data allocated after the registers have run out. */
 
 
 /* The amount of space reserved on the stack for registers. This is
    different to MIPS_SAVED_REGSIZE as it determines the alignment of
    data allocated after the registers have run out. */
 
-#if GDB_MULTI_ARCH
-#undef MIPS_DEFAULT_STACK_ARGSIZE
 #define MIPS_DEFAULT_STACK_ARGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_stack_argsize)
 #define MIPS_DEFAULT_STACK_ARGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_stack_argsize)
-#elif !defined (MIPS_DEFAULT_STACK_ARGSIZE)
-#define MIPS_DEFAULT_STACK_ARGSIZE (MIPS_DEFAULT_SAVED_REGSIZE)
-#endif
 
 #define MIPS_STACK_ARGSIZE (mips_stack_argsize ())
 
 
 #define MIPS_STACK_ARGSIZE (mips_stack_argsize ())
 
@@ -219,17 +230,9 @@ mips_stack_argsize (void)
     return 4;
 }
 
     return 4;
 }
 
-#if GDB_MULTI_ARCH
-#undef GDB_TARGET_IS_MIPS64
 #define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0)
 #define GDB_TARGET_IS_MIPS64 (gdbarch_tdep (current_gdbarch)->gdb_target_is_mips64 + 0)
-#endif
 
 
-#if GDB_MULTI_ARCH
-#undef MIPS_DEFAULT_MASK_ADDRESS_P
 #define MIPS_DEFAULT_MASK_ADDRESS_P (gdbarch_tdep (current_gdbarch)->default_mask_address_p)
 #define MIPS_DEFAULT_MASK_ADDRESS_P (gdbarch_tdep (current_gdbarch)->default_mask_address_p)
-#elif !defined (MIPS_DEFAULT_MASK_ADDRESS_P)
-#define MIPS_DEFAULT_MASK_ADDRESS_P (0)
-#endif
 
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
 
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
@@ -238,7 +241,7 @@ int gdb_print_insn_mips (bfd_vma, disassemble_info *);
 static void mips_print_register (int, int);
 
 static mips_extra_func_info_t
 static void mips_print_register (int, int);
 
 static mips_extra_func_info_t
-heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *);
+heuristic_proc_desc (CORE_ADDR, CORE_ADDR, struct frame_info *, int);
 
 static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
 
 static CORE_ADDR heuristic_proc_start (CORE_ADDR);
 
@@ -251,11 +254,17 @@ static void mips_show_processor_type_command (char *, int);
 static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
 static mips_extra_func_info_t
 static void reinit_frame_cache_sfunc (char *, int, struct cmd_list_element *);
 
 static mips_extra_func_info_t
-find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame);
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame);
 
 static CORE_ADDR after_prologue (CORE_ADDR pc,
                                 mips_extra_func_info_t proc_desc);
 
 
 static CORE_ADDR after_prologue (CORE_ADDR pc,
                                 mips_extra_func_info_t proc_desc);
 
+static void mips_read_fp_register_single (int regno, char *rare_buffer);
+static void mips_read_fp_register_double (int regno, char *rare_buffer);
+
+static struct type *mips_float_register_type (void);
+static struct type *mips_double_register_type (void);
+
 /* This value is the model of MIPS in use.  It is derived from the value
    of the PrID register.  */
 
 /* This value is the model of MIPS in use.  It is derived from the value
    of the PrID register.  */
 
@@ -274,7 +283,7 @@ static struct cmd_list_element *showmipscmdlist = NULL;
 char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
 char **mips_processor_reg_names = mips_generic_reg_names;
 
 char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
 char **mips_processor_reg_names = mips_generic_reg_names;
 
-char *
+const char *
 mips_register_name (int i)
 {
   return mips_processor_reg_names[i];
 mips_register_name (int i)
 {
   return mips_processor_reg_names[i];
@@ -385,6 +394,8 @@ static unsigned int heuristic_fence_post = 0;
 #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
 #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
 #define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
 #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
 #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
 #define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
+/* FIXME drow/2002-06-10: If a pointer on the host is bigger than a long,
+   this will corrupt pdr.iline.  Fortunately we don't use it.  */
 #define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
 #define _PROC_MAGIC_ 0x0F0F0F0F
 #define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
 #define PROC_SYMBOL(proc) (*(struct symbol**)&(proc)->pdr.isym)
 #define _PROC_MAGIC_ 0x0F0F0F0F
 #define PROC_DESC_IS_DUMMY(proc) ((proc)->pdr.isym == _PROC_MAGIC_)
@@ -409,8 +420,9 @@ mips_print_extra_frame_info (struct frame_info *fi)
                     paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
 }
 
                     paddr_d (fi->extra_info->proc_desc->pdr.frameoffset));
 }
 
-/* Convert between RAW and VIRTUAL registers.  The RAW register size
-   defines the remote-gdb packet. */
+/* Number of bytes of storage in the actual machine representation for
+   register N.  NOTE: This indirectly defines the register size
+   transfered by the GDB protocol. */
 
 static int mips64_transfers_32bit_regs_p = 0;
 
 
 static int mips64_transfers_32bit_regs_p = 0;
 
@@ -419,10 +431,18 @@ mips_register_raw_size (int reg_nr)
 {
   if (mips64_transfers_32bit_regs_p)
     return REGISTER_VIRTUAL_SIZE (reg_nr);
 {
   if (mips64_transfers_32bit_regs_p)
     return REGISTER_VIRTUAL_SIZE (reg_nr);
+  else if (reg_nr >= FP0_REGNUM && reg_nr < FP0_REGNUM + 32
+          && FP_REGISTER_DOUBLE)
+    /* For MIPS_ABI_N32 (for example) we need 8 byte floating point
+       registers.  */
+    return 8;
   else
     return MIPS_REGSIZE;
 }
 
   else
     return MIPS_REGSIZE;
 }
 
+/* Convert between RAW and VIRTUAL registers.  The RAW register size
+   defines the remote-gdb packet. */
+
 int
 mips_register_convertible (int reg_nr)
 {
 int
 mips_register_convertible (int reg_nr)
 {
@@ -436,7 +456,7 @@ void
 mips_register_convert_to_virtual (int n, struct type *virtual_type,
                                  char *raw_buf, char *virt_buf)
 {
 mips_register_convert_to_virtual (int n, struct type *virtual_type,
                                  char *raw_buf, char *virt_buf)
 {
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     memcpy (virt_buf,
            raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            TYPE_LENGTH (virtual_type));
     memcpy (virt_buf,
            raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            TYPE_LENGTH (virtual_type));
@@ -451,7 +471,7 @@ mips_register_convert_to_raw (struct type *virtual_type, int n,
                              char *virt_buf, char *raw_buf)
 {
   memset (raw_buf, 0, REGISTER_RAW_SIZE (n));
                              char *virt_buf, char *raw_buf)
 {
   memset (raw_buf, 0, REGISTER_RAW_SIZE (n));
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            virt_buf,
            TYPE_LENGTH (virtual_type));
     memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
            virt_buf,
            TYPE_LENGTH (virtual_type));
@@ -462,39 +482,39 @@ mips_register_convert_to_raw (struct type *virtual_type, int n,
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
-enum cmd_auto_boolean mask_address_var = CMD_AUTO_BOOLEAN_AUTO;
+enum auto_boolean mask_address_var = AUTO_BOOLEAN_AUTO;
 
 static int
 mips_mask_address_p (void)
 {
   switch (mask_address_var)
     {
 
 static int
 mips_mask_address_p (void)
 {
   switch (mask_address_var)
     {
-    case CMD_AUTO_BOOLEAN_TRUE:
+    case AUTO_BOOLEAN_TRUE:
       return 1;
       return 1;
-    case CMD_AUTO_BOOLEAN_FALSE:
+    case AUTO_BOOLEAN_FALSE:
       return 0;
       break;
       return 0;
       break;
-    case CMD_AUTO_BOOLEAN_AUTO:
+    case AUTO_BOOLEAN_AUTO:
       return MIPS_DEFAULT_MASK_ADDRESS_P;
     default:
       internal_error (__FILE__, __LINE__,
                      "mips_mask_address_p: bad switch");
       return -1;
       return MIPS_DEFAULT_MASK_ADDRESS_P;
     default:
       internal_error (__FILE__, __LINE__,
                      "mips_mask_address_p: bad switch");
       return -1;
-    }      
+    }
 }
 
 static void
 }
 
 static void
-show_mask_address (char *cmd, int from_tty)
+show_mask_address (char *cmd, int from_tty, struct cmd_list_element *c)
 {
   switch (mask_address_var)
     {
 {
   switch (mask_address_var)
     {
-    case CMD_AUTO_BOOLEAN_TRUE:
+    case AUTO_BOOLEAN_TRUE:
       printf_filtered ("The 32 bit mips address mask is enabled\n");
       break;
       printf_filtered ("The 32 bit mips address mask is enabled\n");
       break;
-    case CMD_AUTO_BOOLEAN_FALSE:
+    case AUTO_BOOLEAN_FALSE:
       printf_filtered ("The 32 bit mips address mask is disabled\n");
       break;
       printf_filtered ("The 32 bit mips address mask is disabled\n");
       break;
-    case CMD_AUTO_BOOLEAN_AUTO:
+    case AUTO_BOOLEAN_AUTO:
       printf_filtered ("The 32 bit address mask is set automatically.  Currently %s\n",
                       mips_mask_address_p () ? "enabled" : "disabled");
       break;
       printf_filtered ("The 32 bit address mask is set automatically.  Currently %s\n",
                       mips_mask_address_p () ? "enabled" : "disabled");
       break;
@@ -502,7 +522,7 @@ show_mask_address (char *cmd, int from_tty)
       internal_error (__FILE__, __LINE__,
                      "show_mask_address: bad switch");
       break;
       internal_error (__FILE__, __LINE__,
                      "show_mask_address: bad switch");
       break;
-    }      
+    }
 }
 
 /* Should call_function allocate stack space for a struct return?  */
 }
 
 /* Should call_function allocate stack space for a struct return?  */
@@ -540,9 +560,9 @@ pc_is_mips16 (bfd_vma memaddr)
    all registers should be sign extended for simplicity? */
 
 static CORE_ADDR
    all registers should be sign extended for simplicity? */
 
 static CORE_ADDR
-mips_read_pc (int pid)
+mips_read_pc (ptid_t ptid)
 {
 {
-  return read_signed_register_pid (PC_REGNUM, pid);
+  return read_signed_register_pid (PC_REGNUM, ptid);
 }
 
 /* This returns the PC of the first inst after the prologue.  If we can't
 }
 
 /* This returns the PC of the first inst after the prologue.  If we can't
@@ -555,8 +575,13 @@ after_prologue (CORE_ADDR pc,
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
 
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
 
+  /* Pass cur_frame == 0 to find_proc_desc.  We should not attempt
+     to read the stack pointer from the current machine state, because
+     the current machine state has nothing to do with the information
+     we need from the proc_desc; and the process may or may not exist
+     right now.  */
   if (!proc_desc)
   if (!proc_desc)
-    proc_desc = find_proc_desc (pc, NULL);
+    proc_desc = find_proc_desc (pc, NULL, 0);
 
   if (proc_desc)
     {
 
   if (proc_desc)
     {
@@ -663,21 +688,21 @@ mips_fetch_instruction (CORE_ADDR addr)
 
 
 /* These the fields of 32 bit mips instructions */
 
 
 /* These the fields of 32 bit mips instructions */
-#define mips32_op(x) (x >> 25)
-#define itype_op(x) (x >> 25)
-#define itype_rs(x) ((x >> 21)& 0x1f)
+#define mips32_op(x) (x >> 26)
+#define itype_op(x) (x >> 26)
+#define itype_rs(x) ((x >> 21) & 0x1f)
 #define itype_rt(x) ((x >> 16) & 0x1f)
 #define itype_rt(x) ((x >> 16) & 0x1f)
-#define itype_immediate(x) ( x & 0xffff)
+#define itype_immediate(x) (x & 0xffff)
 
 
-#define jtype_op(x) (x >> 25)
-#define jtype_target(x) ( x & 0x03fffff)
+#define jtype_op(x) (x >> 26)
+#define jtype_target(x) (x & 0x03ffffff)
 
 
-#define rtype_op(x) (x >>25)
-#define rtype_rs(x) ((x>>21) & 0x1f)
-#define rtype_rt(x) ((x>>16)  & 0x1f)
-#define rtype_rd(x) ((x>>11) & 0x1f)
-#define rtype_shamt(x) ((x>>6) & 0x1f)
-#define rtype_funct(x) (x & 0x3f )
+#define rtype_op(x) (x >> 26)
+#define rtype_rs(x) ((x >> 21) & 0x1f)
+#define rtype_rt(x) ((x >> 16) & 0x1f)
+#define rtype_rd(x) ((x >> 11) & 0x1f)
+#define rtype_shamt(x) ((x >> 6) & 0x1f)
+#define rtype_funct(x) (x & 0x3f)
 
 static CORE_ADDR
 mips32_relative_offset (unsigned long inst)
 
 static CORE_ADDR
 mips32_relative_offset (unsigned long inst)
@@ -700,25 +725,39 @@ mips32_next_pc (CORE_ADDR pc)
   unsigned long inst;
   int op;
   inst = mips_fetch_instruction (pc);
   unsigned long inst;
   int op;
   inst = mips_fetch_instruction (pc);
-  if ((inst & 0xe0000000) != 0)        /* Not a special, junp or branch instruction */
+  if ((inst & 0xe0000000) != 0)        /* Not a special, jump or branch instruction */
     {
     {
-      if ((inst >> 27) == 5)   /* BEQL BNEZ BLEZL BGTZE , bits 0101xx */
+      if (itype_op (inst) >> 2 == 5)
+                               /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
        {
        {
-         op = ((inst >> 25) & 0x03);
+         op = (itype_op (inst) & 0x03);
          switch (op)
            {
          switch (op)
            {
-           case 0:
-             goto equal_branch;        /* BEQL   */
-           case 1:
-             goto neq_branch;  /* BNEZ   */
-           case 2:
-             goto less_branch; /* BLEZ   */
-           case 3:
-             goto greater_branch;      /* BGTZ */
+           case 0:             /* BEQL */
+             goto equal_branch;
+           case 1:             /* BNEL */
+             goto neq_branch;
+           case 2:             /* BLEZL */
+             goto less_branch;
+           case 3:             /* BGTZ */
+             goto greater_branch;
            default:
              pc += 4;
            }
        }
            default:
              pc += 4;
            }
        }
+      else if (itype_op (inst) == 17 && itype_rs (inst) == 8)
+                               /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */
+       {
+         int tf = itype_rt (inst) & 0x01;
+         int cnum = itype_rt (inst) >> 2;
+         int fcrcs = read_signed_register (FCRCS_REGNUM);
+         int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
+
+         if (((cond >> cnum) & 0x01) == tf)
+           pc += mips32_relative_offset (inst) + 4;
+         else
+           pc += 8;
+       }
       else
        pc += 4;                /* Not a branch, next instruction is easy */
     }
       else
        pc += 4;                /* Not a branch, next instruction is easy */
     }
@@ -726,7 +765,7 @@ mips32_next_pc (CORE_ADDR pc)
     {                          /* This gets way messy */
 
       /* Further subdivide into SPECIAL, REGIMM and other */
     {                          /* This gets way messy */
 
       /* Further subdivide into SPECIAL, REGIMM and other */
-      switch (op = ((inst >> 26) & 0x07))      /* extract bits 28,27,26 */
+      switch (op = itype_op (inst) & 0x07)     /* extract bits 28,27,26 */
        {
        case 0:         /* SPECIAL */
          op = rtype_funct (inst);
        {
        case 0:         /* SPECIAL */
          op = rtype_funct (inst);
@@ -741,15 +780,15 @@ mips32_next_pc (CORE_ADDR pc)
              pc += 4;
            }
 
              pc += 4;
            }
 
-         break;                /* end special */
+         break;        /* end SPECIAL */
        case 1:         /* REGIMM */
          {
        case 1:         /* REGIMM */
          {
-           op = jtype_op (inst);       /* branch condition */
-           switch (jtype_op (inst))
+           op = itype_rt (inst);       /* branch condition */
+           switch (op)
              {
              case 0:           /* BLTZ */
              {
              case 0:           /* BLTZ */
-             case 2:           /* BLTXL */
-             case 16:          /* BLTZALL */
+             case 2:           /* BLTZL */
+             case 16:          /* BLTZAL */
              case 18:          /* BLTZALL */
              less_branch:
                if (read_signed_register (itype_rs (inst)) < 0)
              case 18:          /* BLTZALL */
              less_branch:
                if (read_signed_register (itype_rs (inst)) < 0)
@@ -757,7 +796,7 @@ mips32_next_pc (CORE_ADDR pc)
                else
                  pc += 8;      /* after the delay slot */
                break;
                else
                  pc += 8;      /* after the delay slot */
                break;
-             case 1:           /* GEZ */
+             case 1:           /* BGEZ */
              case 3:           /* BGEZL */
              case 17:          /* BGEZAL */
              case 19:          /* BGEZALL */
              case 3:           /* BGEZL */
              case 17:          /* BGEZAL */
              case 19:          /* BGEZALL */
@@ -767,19 +806,19 @@ mips32_next_pc (CORE_ADDR pc)
                else
                  pc += 8;      /* after the delay slot */
                break;
                else
                  pc += 8;      /* after the delay slot */
                break;
-               /* All of the other intructions in the REGIMM catagory */
+               /* All of the other instructions in the REGIMM category */
              default:
                pc += 4;
              }
          }
              default:
                pc += 4;
              }
          }
-         break;                /* end REGIMM */
+         break;        /* end REGIMM */
        case 2:         /* J */
        case 3:         /* JAL */
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
        case 2:         /* J */
        case 3:         /* JAL */
          {
            unsigned long reg;
            reg = jtype_target (inst) << 2;
+           /* Upper four bits get never changed... */
            pc = reg + ((pc + 4) & 0xf0000000);
            pc = reg + ((pc + 4) & 0xf0000000);
-           /* Whats this mysterious 0xf000000 adjustment ??? */
          }
          break;
          /* FIXME case JALX : */
          }
          break;
          /* FIXME case JALX : */
@@ -790,7 +829,7 @@ mips32_next_pc (CORE_ADDR pc)
            /* Add 1 to indicate 16 bit mode - Invert ISA mode */
          }
          break;                /* The new PC will be alternate mode */
            /* Add 1 to indicate 16 bit mode - Invert ISA mode */
          }
          break;                /* The new PC will be alternate mode */
-       case 4:         /* BEQ , BEQL */
+       case 4:         /* BEQ, BEQL */
        equal_branch:
          if (read_signed_register (itype_rs (inst)) ==
              read_signed_register (itype_rt (inst)))
        equal_branch:
          if (read_signed_register (itype_rs (inst)) ==
              read_signed_register (itype_rt (inst)))
@@ -798,15 +837,15 @@ mips32_next_pc (CORE_ADDR pc)
          else
            pc += 8;
          break;
          else
            pc += 8;
          break;
-       case 5:         /* BNE , BNEL */
+       case 5:         /* BNE, BNEL */
        neq_branch:
          if (read_signed_register (itype_rs (inst)) !=
        neq_branch:
          if (read_signed_register (itype_rs (inst)) !=
-             read_signed_register (itype_rs (inst)))
+             read_signed_register (itype_rt (inst)))
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
          break;
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
          break;
-       case 6:         /* BLEZ , BLEZL */
+       case 6:         /* BLEZ, BLEZL */
        less_zero_branch:
          if (read_signed_register (itype_rs (inst) <= 0))
            pc += mips32_relative_offset (inst) + 4;
        less_zero_branch:
          if (read_signed_register (itype_rs (inst) <= 0))
            pc += mips32_relative_offset (inst) + 4;
@@ -814,14 +853,13 @@ mips32_next_pc (CORE_ADDR pc)
            pc += 8;
          break;
        case 7:
            pc += 8;
          break;
        case 7:
-       greater_branch: /* BGTZ BGTZL */
+       default:
+       greater_branch: /* BGTZ, BGTZL */
          if (read_signed_register (itype_rs (inst) > 0))
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
          break;
          if (read_signed_register (itype_rs (inst) > 0))
            pc += mips32_relative_offset (inst) + 4;
          else
            pc += 8;
          break;
-       default:
-         pc += 8;
        }                       /* switch */
     }                          /* else */
   return pc;
        }                       /* switch */
     }                          /* else */
   return pc;
@@ -1334,7 +1372,7 @@ read_next_frame_reg (struct frame_info *fi, int regno)
 
 /* mips_addr_bits_remove - remove useless address bits  */
 
 
 /* mips_addr_bits_remove - remove useless address bits  */
 
-CORE_ADDR
+static CORE_ADDR
 mips_addr_bits_remove (CORE_ADDR addr)
 {
   if (GDB_TARGET_IS_MIPS64)
 mips_addr_bits_remove (CORE_ADDR addr)
 {
   if (GDB_TARGET_IS_MIPS64)
@@ -1373,7 +1411,34 @@ mips_addr_bits_remove (CORE_ADDR addr)
   return addr;
 }
 
   return addr;
 }
 
+/* mips_software_single_step() is called just before we want to resume
+   the inferior, if we want to single-step it but there is no hardware
+   or kernel single-step support (MIPS on GNU/Linux for example).  We find
+   the target of the coming instruction and breakpoint it.
+
+   single_step is also called just after the inferior stops.  If we had
+   set up a simulated single-step, we undo our damage.  */
+
 void
 void
+mips_software_single_step (enum target_signal sig, int insert_breakpoints_p)
+{
+  static CORE_ADDR next_pc;
+  typedef char binsn_quantum[BREAKPOINT_MAX];
+  static binsn_quantum break_mem;
+  CORE_ADDR pc;
+
+  if (insert_breakpoints_p)
+    {
+      pc = read_register (PC_REGNUM);
+      next_pc = mips_next_pc (pc);
+
+      target_insert_breakpoint (next_pc, break_mem);
+    }
+  else
+    target_remove_breakpoint (next_pc, break_mem);
+}
+
+static void
 mips_init_frame_pc_first (int fromleaf, struct frame_info *prev)
 {
   CORE_ADDR pc, tmp;
 mips_init_frame_pc_first (int fromleaf, struct frame_info *prev)
 {
   CORE_ADDR pc, tmp;
@@ -1812,9 +1877,14 @@ restart:
 
 static mips_extra_func_info_t
 heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
 
 static mips_extra_func_info_t
 heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
-                    struct frame_info *next_frame)
+                    struct frame_info *next_frame, int cur_frame)
 {
 {
-  CORE_ADDR sp = read_next_frame_reg (next_frame, SP_REGNUM);
+  CORE_ADDR sp;
+
+  if (cur_frame)
+    sp = read_next_frame_reg (next_frame, SP_REGNUM);
+  else
+    sp = 0;
 
   if (start_pc == 0)
     return NULL;
 
   if (start_pc == 0)
     return NULL;
@@ -1833,6 +1903,30 @@ heuristic_proc_desc (CORE_ADDR start_pc, CORE_ADDR limit_pc,
   return &temp_proc_desc;
 }
 
   return &temp_proc_desc;
 }
 
+struct mips_objfile_private
+{
+  bfd_size_type size;
+  char *contents;
+};
+
+/* Global used to communicate between non_heuristic_proc_desc and
+   compare_pdr_entries within qsort ().  */
+static bfd *the_bfd;
+
+static int
+compare_pdr_entries (const void *a, const void *b)
+{
+  CORE_ADDR lhs = bfd_get_32 (the_bfd, (bfd_byte *) a);
+  CORE_ADDR rhs = bfd_get_32 (the_bfd, (bfd_byte *) b);
+
+  if (lhs < rhs)
+    return -1;
+  else if (lhs == rhs)
+    return 0;
+  else
+    return 1;
+}
+
 static mips_extra_func_info_t
 non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
 {
 static mips_extra_func_info_t
 non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
 {
@@ -1840,23 +1934,145 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
   mips_extra_func_info_t proc_desc;
   struct block *b = block_for_pc (pc);
   struct symbol *sym;
   mips_extra_func_info_t proc_desc;
   struct block *b = block_for_pc (pc);
   struct symbol *sym;
+  struct obj_section *sec;
+  struct mips_objfile_private *priv;
+
+  if (PC_IN_CALL_DUMMY (pc, 0, 0))
+    return NULL;
 
   find_pc_partial_function (pc, NULL, &startaddr, NULL);
   if (addrptr)
     *addrptr = startaddr;
 
   find_pc_partial_function (pc, NULL, &startaddr, NULL);
   if (addrptr)
     *addrptr = startaddr;
-  if (b == NULL || PC_IN_CALL_DUMMY (pc, 0, 0))
-    sym = NULL;
-  else
+
+  priv = NULL;
+
+  sec = find_pc_section (pc);
+  if (sec != NULL)
     {
     {
-      if (startaddr > BLOCK_START (b))
-       /* This is the "pathological" case referred to in a comment in
-          print_frame_info.  It might be better to move this check into
-          symbol reading.  */
-       sym = NULL;
-      else
-       sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
+      priv = (struct mips_objfile_private *) sec->objfile->obj_private;
+
+      /* Search the ".pdr" section generated by GAS.  This includes most of
+        the information normally found in ECOFF PDRs.  */
+
+      the_bfd = sec->objfile->obfd;
+      if (priv == NULL
+         && (the_bfd->format == bfd_object
+             && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour
+             && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64))
+       {
+         /* Right now GAS only outputs the address as a four-byte sequence.
+            This means that we should not bother with this method on 64-bit
+            targets (until that is fixed).  */
+
+         priv = obstack_alloc (& sec->objfile->psymbol_obstack,
+                               sizeof (struct mips_objfile_private));
+         priv->size = 0;
+         sec->objfile->obj_private = priv;
+       }
+      else if (priv == NULL)
+       {
+         asection *bfdsec;
+
+         priv = obstack_alloc (& sec->objfile->psymbol_obstack,
+                               sizeof (struct mips_objfile_private));
+
+         bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr");
+         if (bfdsec != NULL)
+           {
+             priv->size = bfd_section_size (sec->objfile->obfd, bfdsec);
+             priv->contents = obstack_alloc (& sec->objfile->psymbol_obstack,
+                                             priv->size);
+             bfd_get_section_contents (sec->objfile->obfd, bfdsec,
+                                       priv->contents, 0, priv->size);
+
+             /* In general, the .pdr section is sorted.  However, in the
+                presence of multiple code sections (and other corner cases)
+                it can become unsorted.  Sort it so that we can use a faster
+                binary search.  */
+             qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries);
+           }
+         else
+           priv->size = 0;
+
+         sec->objfile->obj_private = priv;
+       }
+      the_bfd = NULL;
+
+      if (priv->size != 0)
+       {
+         int low, mid, high;
+         char *ptr;
+
+         low = 0;
+         high = priv->size / 32;
+
+         do
+           {
+             CORE_ADDR pdr_pc;
+
+             mid = (low + high) / 2;
+
+             ptr = priv->contents + mid * 32;
+             pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr);
+             pdr_pc += ANOFFSET (sec->objfile->section_offsets,
+                                 SECT_OFF_TEXT (sec->objfile));
+             if (pdr_pc == startaddr)
+               break;
+             if (pdr_pc > startaddr)
+               high = mid;
+             else
+               low = mid + 1;
+           }
+         while (low != high);
+
+         if (low != high)
+           {
+             struct symbol *sym = find_pc_function (pc);
+
+             /* Fill in what we need of the proc_desc.  */
+             proc_desc = (mips_extra_func_info_t)
+               obstack_alloc (&sec->objfile->psymbol_obstack,
+                              sizeof (struct mips_extra_func_info));
+             PROC_LOW_ADDR (proc_desc) = startaddr;
+
+             /* Only used for dummy frames.  */
+             PROC_HIGH_ADDR (proc_desc) = 0;
+
+             PROC_FRAME_OFFSET (proc_desc)
+               = bfd_get_32 (sec->objfile->obfd, ptr + 20);
+             PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
+                                                      ptr + 24);
+             PROC_FRAME_ADJUST (proc_desc) = 0;
+             PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
+                                                     ptr + 4);
+             PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd,
+                                                      ptr + 12);
+             PROC_REG_OFFSET (proc_desc) = bfd_get_32 (sec->objfile->obfd,
+                                                       ptr + 8);
+             PROC_FREG_OFFSET (proc_desc)
+               = bfd_get_32 (sec->objfile->obfd, ptr + 16);
+             PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd,
+                                                   ptr + 28);
+             proc_desc->pdr.isym = (long) sym;
+
+             return proc_desc;
+           }
+       }
     }
 
     }
 
+  if (b == NULL)
+    return NULL;
+
+  if (startaddr > BLOCK_START (b))
+    {
+      /* This is the "pathological" case referred to in a comment in
+        print_frame_info.  It might be better to move this check into
+        symbol reading.  */
+      return NULL;
+    }
+
+  sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_NAMESPACE, 0, NULL);
+
   /* If we never found a PDR for this function in symbol reading, then
      examine prologues to find the information.  */
   if (sym)
   /* If we never found a PDR for this function in symbol reading, then
      examine prologues to find the information.  */
   if (sym)
@@ -1873,7 +2089,7 @@ non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr)
 
 
 static mips_extra_func_info_t
 
 
 static mips_extra_func_info_t
-find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
+find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame)
 {
   mips_extra_func_info_t proc_desc;
   CORE_ADDR startaddr;
 {
   mips_extra_func_info_t proc_desc;
   CORE_ADDR startaddr;
@@ -1905,7 +2121,7 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
            {
              mips_extra_func_info_t found_heuristic =
              heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
            {
              mips_extra_func_info_t found_heuristic =
              heuristic_proc_desc (PROC_LOW_ADDR (proc_desc),
-                                  pc, next_frame);
+                                  pc, next_frame, cur_frame);
              if (found_heuristic)
                proc_desc = found_heuristic;
            }
              if (found_heuristic)
                proc_desc = found_heuristic;
            }
@@ -1929,7 +2145,7 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame)
        startaddr = heuristic_proc_start (pc);
 
       proc_desc =
        startaddr = heuristic_proc_start (pc);
 
       proc_desc =
-       heuristic_proc_desc (startaddr, pc, next_frame);
+       heuristic_proc_desc (startaddr, pc, next_frame, cur_frame);
     }
   return proc_desc;
 }
     }
   return proc_desc;
 }
@@ -1961,7 +2177,7 @@ mips_frame_chain (struct frame_info *frame)
     saved_pc = tmp;
 
   /* Look up the procedure descriptor for this PC.  */
     saved_pc = tmp;
 
   /* Look up the procedure descriptor for this PC.  */
-  proc_desc = find_proc_desc (saved_pc, frame);
+  proc_desc = find_proc_desc (saved_pc, frame, 1);
   if (!proc_desc)
     return 0;
 
   if (!proc_desc)
     return 0;
 
@@ -1987,7 +2203,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
 
   /* Use proc_desc calculated in frame_chain */
   mips_extra_func_info_t proc_desc =
 
   /* Use proc_desc calculated in frame_chain */
   mips_extra_func_info_t proc_desc =
-  fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next);
+  fci->next ? cached_proc_desc : find_proc_desc (fci->pc, fci->next, 1);
 
   fci->extra_info = (struct frame_extra_info *)
     frame_obstack_alloc (sizeof (struct frame_extra_info));
 
   fci->extra_info = (struct frame_extra_info *)
     frame_obstack_alloc (sizeof (struct frame_extra_info));
@@ -2016,7 +2232,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
             We can't use fci->signal_handler_caller, it is not yet set.  */
          find_pc_partial_function (fci->pc, &name,
                                    (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
             We can't use fci->signal_handler_caller, it is not yet set.  */
          find_pc_partial_function (fci->pc, &name,
                                    (CORE_ADDR *) NULL, (CORE_ADDR *) NULL);
-         if (!IN_SIGTRAMP (fci->pc, name))
+         if (!PC_IN_SIGTRAMP (fci->pc, name))
            {
              frame_saved_regs_zalloc (fci);
              memcpy (fci->saved_regs, temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
            {
              frame_saved_regs_zalloc (fci);
              memcpy (fci->saved_regs, temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
@@ -2043,7 +2259,7 @@ mips_init_extra_frame_info (int fromleaf, struct frame_info *fci)
    we basically have to look at symbol information for the function
    that we stopped in, which tells us *which* register (if any) is
    the base of the frame pointer, and what offset from that register
    we basically have to look at symbol information for the function
    that we stopped in, which tells us *which* register (if any) is
    the base of the frame pointer, and what offset from that register
-   the frame itself is at.  
+   the frame itself is at.
 
    This presents a problem when trying to examine a stack in memory
    (that isn't executing at the moment), using the "frame" command.  We
 
    This presents a problem when trying to examine a stack in memory
    (that isn't executing at the moment), using the "frame" command.  We
@@ -2080,9 +2296,38 @@ fp_register_arg_p (enum type_code typecode, struct type *arg_type)
           && MIPS_FPU_TYPE != MIPS_FPU_NONE);
 }
 
           && MIPS_FPU_TYPE != MIPS_FPU_NONE);
 }
 
+/* On o32, argument passing in GPRs depends on the alignment of the type being
+   passed.  Return 1 if this type must be aligned to a doubleword boundary. */
+
+static int
+mips_type_needs_double_align (struct type *type)
+{
+  enum type_code typecode = TYPE_CODE (type);
+
+  if (typecode == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8)
+    return 1;
+  else if (typecode == TYPE_CODE_STRUCT)
+    {
+      if (TYPE_NFIELDS (type) < 1)
+       return 0;
+      return mips_type_needs_double_align (TYPE_FIELD_TYPE (type, 0));
+    }
+  else if (typecode == TYPE_CODE_UNION)
+    {
+      int i, n;
+
+      n = TYPE_NFIELDS (type);
+      for (i = 0; i < n; i++)
+       if (mips_type_needs_double_align (TYPE_FIELD_TYPE (type, i)))
+         return 1;
+      return 0;
+    }
+  return 0;
+}
+
 CORE_ADDR
 mips_push_arguments (int nargs,
 CORE_ADDR
 mips_push_arguments (int nargs,
-                    value_ptr *args,
+                    struct value **args,
                     CORE_ADDR sp,
                     int struct_return,
                     CORE_ADDR struct_addr)
                     CORE_ADDR sp,
                     int struct_return,
                     CORE_ADDR struct_addr)
@@ -2140,7 +2385,7 @@ mips_push_arguments (int nargs,
     {
       char *val;
       char valbuf[MAX_REGISTER_RAW_SIZE];
     {
       char *val;
       char valbuf[MAX_REGISTER_RAW_SIZE];
-      value_ptr arg = args[argnum];
+      struct value *arg = args[argnum];
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
       struct type *arg_type = check_typedef (VALUE_TYPE (arg));
       int len = TYPE_LENGTH (arg_type);
       enum type_code typecode = TYPE_CODE (arg_type);
@@ -2187,15 +2432,15 @@ mips_push_arguments (int nargs,
          don't use float registers for arguments.  This duplication of
          arguments in general registers can't hurt non-MIPS16 functions
          because those registers are normally skipped.  */
          don't use float registers for arguments.  This duplication of
          arguments in general registers can't hurt non-MIPS16 functions
          because those registers are normally skipped.  */
-      /* MIPS_EABI squeeses a struct that contains a single floating
-         point value into an FP register instead of pusing it onto the
+      /* MIPS_EABI squeezes a struct that contains a single floating
+         point value into an FP register instead of pushing it onto the
          stack. */
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
          if (!FP_REGISTER_DOUBLE && len == 8)
            {
          stack. */
       if (fp_register_arg_p (typecode, arg_type)
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
        {
          if (!FP_REGISTER_DOUBLE && len == 8)
            {
-             int low_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
+             int low_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
              unsigned long regval;
 
              /* Write the low word of the double to the even register(s).  */
@@ -2266,6 +2511,14 @@ mips_push_arguments (int nargs,
             compatibility, we will put them in both places.  */
          int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) &&
                                  (len % MIPS_SAVED_REGSIZE != 0));
             compatibility, we will put them in both places.  */
          int odd_sized_struct = ((len > MIPS_SAVED_REGSIZE) &&
                                  (len % MIPS_SAVED_REGSIZE != 0));
+         /* Structures should be aligned to eight bytes (even arg registers)
+            on MIPS_ABI_O32 if their first member has double precision. */
+         if (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_O32
+             && mips_type_needs_double_align (arg_type))
+           {
+             if ((argreg & 1))
+               argreg++;
+           }
          /* Note: Floating-point values that didn't fit into an FP
              register are only written to memory. */
          while (len > 0)
          /* Note: Floating-point values that didn't fit into an FP
              register are only written to memory. */
          while (len > 0)
@@ -2288,7 +2541,7 @@ mips_push_arguments (int nargs,
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
                  int longword_offset = 0;
                  CORE_ADDR addr;
                  stack_used_p = 1;
-                 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+                 if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
                    {
                      if (MIPS_STACK_ARGSIZE == 8 &&
                          (typecode == TYPE_CODE_INT ||
                    {
                      if (MIPS_STACK_ARGSIZE == 8 &&
                          (typecode == TYPE_CODE_INT ||
@@ -2308,7 +2561,7 @@ mips_push_arguments (int nargs,
                      fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%lx",
                                          (long) longword_offset);
                    }
                      fprintf_unfiltered (gdb_stdlog, " longword_offset=0x%lx",
                                          (long) longword_offset);
                    }
-                   
+
                  addr = sp + stack_offset + longword_offset;
 
                  if (mips_debug)
                  addr = sp + stack_offset + longword_offset;
 
                  if (mips_debug)
@@ -2333,7 +2586,7 @@ mips_push_arguments (int nargs,
                {
                  LONGEST regval = extract_unsigned_integer (val, partial_len);
 
                {
                  LONGEST regval = extract_unsigned_integer (val, partial_len);
 
-                 /* A non-floating-point argument being passed in a 
+                 /* A non-floating-point argument being passed in a
                     general register.  If a struct or union, and if
                     the remaining length is smaller than the register
                     size, we have to adjust the register value on
                     general register.  If a struct or union, and if
                     the remaining length is smaller than the register
                     size, we have to adjust the register value on
@@ -2343,11 +2596,24 @@ mips_push_arguments (int nargs,
                     same for integral types.
 
                     Also don't do this adjustment on EABI and O64
                     same for integral types.
 
                     Also don't do this adjustment on EABI and O64
-                    binaries. */
+                    binaries.
+
+                    cagney/2001-07-23: gdb/179: Also, GCC, when
+                    outputting LE O32 with sizeof (struct) <
+                    MIPS_SAVED_REGSIZE, generates a left shift as
+                    part of storing the argument in a register a
+                    register (the left shift isn't generated when
+                    sizeof (struct) >= MIPS_SAVED_REGSIZE).  Since it
+                    is quite possible that this is GCC contradicting
+                    the LE/O32 ABI, GDB has not been adjusted to
+                    accommodate this.  Either someone needs to
+                    demonstrate that the LE/O32 ABI specifies such a
+                    left shift OR this new ABI gets identified as
+                    such and GDB gets tweaked accordingly.  */
 
                  if (!MIPS_EABI
                      && MIPS_SAVED_REGSIZE < 8
 
                  if (!MIPS_EABI
                      && MIPS_SAVED_REGSIZE < 8
-                     && TARGET_BYTE_ORDER == BIG_ENDIAN
+                     && TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                      && partial_len < MIPS_SAVED_REGSIZE
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
                      && partial_len < MIPS_SAVED_REGSIZE
                      && (typecode == TYPE_CODE_STRUCT ||
                          typecode == TYPE_CODE_UNION))
@@ -2412,7 +2678,7 @@ mips_push_register (CORE_ADDR * sp, int regno)
   if (MIPS_SAVED_REGSIZE < REGISTER_RAW_SIZE (regno))
     {
       regsize = MIPS_SAVED_REGSIZE;
   if (MIPS_SAVED_REGSIZE < REGISTER_RAW_SIZE (regno))
     {
       regsize = MIPS_SAVED_REGSIZE;
-      offset = (TARGET_BYTE_ORDER == BIG_ENDIAN
+      offset = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                ? REGISTER_RAW_SIZE (regno) - MIPS_SAVED_REGSIZE
                : 0);
     }
                ? REGISTER_RAW_SIZE (regno) - MIPS_SAVED_REGSIZE
                : 0);
     }
@@ -2452,7 +2718,7 @@ mips_push_dummy_frame (void)
    * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
    * In addition, we must save the PC, PUSH_FP_REGNUM, MMLO/-HI
    * and FP Control/Status registers.
    * procedure calls. Dest_Reg (see tm-mips.h) must also be saved.
    * In addition, we must save the PC, PUSH_FP_REGNUM, MMLO/-HI
    * and FP Control/Status registers.
-   * 
+   *
    *
    * Dummy frame layout:
    *  (high memory)
    *
    * Dummy frame layout:
    *  (high memory)
@@ -2566,34 +2832,151 @@ mips_pop_frame (void)
     }
 }
 
     }
 }
 
+/* Floating point register management.
+
+   Background: MIPS1 & 2 fp registers are 32 bits wide.  To support
+   64bit operations, these early MIPS cpus treat fp register pairs
+   (f0,f1) as a single register (d0).  Later MIPS cpu's have 64 bit fp
+   registers and offer a compatibility mode that emulates the MIPS2 fp
+   model.  When operating in MIPS2 fp compat mode, later cpu's split
+   double precision floats into two 32-bit chunks and store them in
+   consecutive fp regs.  To display 64-bit floats stored in this
+   fashion, we have to combine 32 bits from f0 and 32 bits from f1.
+   Throw in user-configurable endianness and you have a real mess.
+
+   The way this works is:
+     - If we are in 32-bit mode or on a 32-bit processor, then a 64-bit
+       double-precision value will be split across two logical registers.
+       The lower-numbered logical register will hold the low-order bits,
+       regardless of the processor's endianness.
+     - If we are on a 64-bit processor, and we are looking for a
+       single-precision value, it will be in the low ordered bits
+       of a 64-bit GPR (after mfc1, for example) or a 64-bit register
+       save slot in memory.
+     - If we are in 64-bit mode, everything is straightforward.
+
+   Note that this code only deals with "live" registers at the top of the
+   stack.  We will attempt to deal with saved registers later, when
+   the raw/cooked register interface is in place. (We need a general
+   interface that can deal with dynamic saved register sizes -- fp
+   regs could be 32 bits wide in one frame and 64 on the frame above
+   and below).  */
+
+static struct type *
+mips_float_register_type (void)
+{
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+    return builtin_type_ieee_single_big;
+  else
+    return builtin_type_ieee_single_little;
+}
+
+static struct type *
+mips_double_register_type (void)
+{
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+    return builtin_type_ieee_double_big;
+  else
+    return builtin_type_ieee_double_little;
+}
+
+/* Copy a 32-bit single-precision value from the current frame
+   into rare_buffer.  */
+
+static void
+mips_read_fp_register_single (int regno, char *rare_buffer)
+{
+  int raw_size = REGISTER_RAW_SIZE (regno);
+  char *raw_buffer = alloca (raw_size);
+
+  if (!frame_register_read (selected_frame, regno, raw_buffer))
+    error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
+  if (raw_size == 8)
+    {
+      /* We have a 64-bit value for this register.  Find the low-order
+        32 bits.  */
+      int offset;
+
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       offset = 4;
+      else
+       offset = 0;
+
+      memcpy (rare_buffer, raw_buffer + offset, 4);
+    }
+  else
+    {
+      memcpy (rare_buffer, raw_buffer, 4);
+    }
+}
+
+/* Copy a 64-bit double-precision value from the current frame into
+   rare_buffer.  This may include getting half of it from the next
+   register.  */
+
+static void
+mips_read_fp_register_double (int regno, char *rare_buffer)
+{
+  int raw_size = REGISTER_RAW_SIZE (regno);
+
+  if (raw_size == 8 && !mips2_fp_compat ())
+    {
+      /* We have a 64-bit value for this register, and we should use
+        all 64 bits.  */
+      if (!frame_register_read (selected_frame, regno, rare_buffer))
+       error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
+    }
+  else
+    {
+      if ((regno - FP0_REGNUM) & 1)
+       internal_error (__FILE__, __LINE__,
+                       "mips_read_fp_register_double: bad access to "
+                       "odd-numbered FP register");
+
+      /* mips_read_fp_register_single will find the correct 32 bits from
+        each register.  */
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+       {
+         mips_read_fp_register_single (regno, rare_buffer + 4);
+         mips_read_fp_register_single (regno + 1, rare_buffer);
+       }
+      else
+       {
+         mips_read_fp_register_single (regno, rare_buffer);
+         mips_read_fp_register_single (regno + 1, rare_buffer + 4);
+       }
+    }
+}
+
 static void
 mips_print_register (int regnum, int all)
 {
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
 
   /* Get the data in raw format.  */
 static void
 mips_print_register (int regnum, int all)
 {
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
 
   /* Get the data in raw format.  */
-  if (read_relative_register_raw_bytes (regnum, raw_buffer))
+  if (!frame_register_read (selected_frame, regnum, raw_buffer))
     {
       printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
       return;
     }
 
     {
       printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
       return;
     }
 
-  /* If an even floating point register, also print as double. */
+  /* If we have a actual 32-bit floating point register (or we are in
+     32-bit compatibility mode), and the register is even-numbered,
+     also print it as a double (spanning two registers).  */
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
+      && (REGISTER_RAW_SIZE (regnum) == 4
+         || mips2_fp_compat ())
       && !((regnum - FP0_REGNUM) & 1))
       && !((regnum - FP0_REGNUM) & 1))
-    if (REGISTER_RAW_SIZE (regnum) == 4)       /* this would be silly on MIPS64 or N32 (Irix 6) */
-      {
-       char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
+    {
+      char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
 
 
-       read_relative_register_raw_bytes (regnum, dbuffer);
-       read_relative_register_raw_bytes (regnum + 1, dbuffer + MIPS_REGSIZE);
-       REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
+      mips_read_fp_register_double (regnum, dbuffer);
 
 
-       printf_filtered ("(d%d: ", regnum - FP0_REGNUM);
-       val_print (builtin_type_double, dbuffer, 0, 0,
-                  gdb_stdout, 0, 1, 0, Val_pretty_default);
-       printf_filtered ("); ");
-      }
+      printf_filtered ("(d%d: ", regnum - FP0_REGNUM);
+      val_print (mips_double_register_type (), dbuffer, 0, 0,
+                gdb_stdout, 0, 1, 0, Val_pretty_default);
+      printf_filtered ("); ");
+    }
   fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
 
   /* The problem with printing numeric register names (r26, etc.) is that
   fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
 
   /* The problem with printing numeric register names (r26, etc.) is that
@@ -2607,15 +2990,17 @@ mips_print_register (int regnum, int all)
 
   /* If virtual format is floating, print it that way.  */
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
 
   /* If virtual format is floating, print it that way.  */
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
-    if (FP_REGISTER_DOUBLE)
-      {                                /* show 8-byte floats as float AND double: */
-       int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
+    if (REGISTER_RAW_SIZE (regnum) == 8 && !mips2_fp_compat ())
+      {
+       /* We have a meaningful 64-bit value in this register.  Show
+          it as a 32-bit float and a 64-bit double.  */
+       int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
 
        printf_filtered (" (float) ");
 
        printf_filtered (" (float) ");
-       val_print (builtin_type_float, raw_buffer + offset, 0, 0,
+       val_print (mips_float_register_type (), raw_buffer + offset, 0, 0,
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
        printf_filtered (", (double) ");
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
        printf_filtered (", (double) ");
-       val_print (builtin_type_double, raw_buffer, 0, 0,
+       val_print (mips_double_register_type (), raw_buffer, 0, 0,
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
       }
     else
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
       }
     else
@@ -2626,74 +3011,86 @@ mips_print_register (int regnum, int all)
     {
       int offset;
 
     {
       int offset;
 
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
         offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
       else
        offset = 0;
         offset = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
       else
        offset = 0;
-       
+
       print_scalar_formatted (raw_buffer + offset,
                              REGISTER_VIRTUAL_TYPE (regnum),
                              'x', 0, gdb_stdout);
     }
 }
 
       print_scalar_formatted (raw_buffer + offset,
                              REGISTER_VIRTUAL_TYPE (regnum),
                              'x', 0, gdb_stdout);
     }
 }
 
-/* Replacement for generic do_registers_info.  
+/* Replacement for generic do_registers_info.
    Print regs in pretty columns.  */
 
 static int
 do_fp_register_row (int regnum)
 {                              /* do values for FP (float) regs */
    Print regs in pretty columns.  */
 
 static int
 do_fp_register_row (int regnum)
 {                              /* do values for FP (float) regs */
-  char *raw_buffer[2];
-  char *dbl_buffer;
-  /* use HI and LO to control the order of combining two flt regs */
-  int HI = (TARGET_BYTE_ORDER == BIG_ENDIAN);
-  int LO = (TARGET_BYTE_ORDER != BIG_ENDIAN);
+  char *raw_buffer;
   double doub, flt1, flt2;     /* doubles extracted from raw hex data */
   int inv1, inv2, inv3;
 
   double doub, flt1, flt2;     /* doubles extracted from raw hex data */
   int inv1, inv2, inv3;
 
-  raw_buffer[0] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
-  raw_buffer[1] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
-  dbl_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
+  raw_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
 
 
-  /* Get the data in raw format.  */
-  if (read_relative_register_raw_bytes (regnum, raw_buffer[HI]))
-    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
-  if (REGISTER_RAW_SIZE (regnum) == 4)
+  if (REGISTER_RAW_SIZE (regnum) == 4 || mips2_fp_compat ())
     {
     {
-      /* 4-byte registers: we can fit two registers per row. */
-      /* Also print every pair of 4-byte regs as an 8-byte double. */
-      if (read_relative_register_raw_bytes (regnum + 1, raw_buffer[LO]))
-       error ("can't read register %d (%s)",
-              regnum + 1, REGISTER_NAME (regnum + 1));
-
-      /* copy the two floats into one double, and unpack both */
-      memcpy (dbl_buffer, raw_buffer, 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
-      flt1 = unpack_double (builtin_type_float, raw_buffer[HI], &inv1);
-      flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2);
-      doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
-
-      printf_filtered (inv1 ? " %-5s: <invalid float>" :
-                      " %-5s%-17.9g", REGISTER_NAME (regnum), flt1);
-      printf_filtered (inv2 ? " %-5s: <invalid float>" :
-                      " %-5s%-17.9g", REGISTER_NAME (regnum + 1), flt2);
-      printf_filtered (inv3 ? " dbl: <invalid double>\n" :
-                      " dbl: %-24.17g\n", doub);
+      /* 4-byte registers: we can fit two registers per row.  */
+      /* Also print every pair of 4-byte regs as an 8-byte double.  */
+      mips_read_fp_register_single (regnum, raw_buffer);
+      flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
+
+      mips_read_fp_register_single (regnum + 1, raw_buffer);
+      flt2 = unpack_double (mips_float_register_type (), raw_buffer, &inv2);
+
+      mips_read_fp_register_double (regnum, raw_buffer);
+      doub = unpack_double (mips_double_register_type (), raw_buffer, &inv3);
+
+      printf_filtered (" %-5s", REGISTER_NAME (regnum));
+      if (inv1)
+       printf_filtered (": <invalid float>");
+      else
+       printf_filtered ("%-17.9g", flt1);
+
+      printf_filtered (" %-5s", REGISTER_NAME (regnum + 1));
+      if (inv2)
+       printf_filtered (": <invalid float>");
+      else
+       printf_filtered ("%-17.9g", flt2);
+
+      printf_filtered (" dbl: ");
+      if (inv3)
+       printf_filtered ("<invalid double>");
+      else
+       printf_filtered ("%-24.17g", doub);
+      printf_filtered ("\n");
+
       /* may want to do hex display here (future enhancement) */
       regnum += 2;
     }
   else
       /* may want to do hex display here (future enhancement) */
       regnum += 2;
     }
   else
-    {                          /* eight byte registers: print each one as float AND as double. */
-      int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
-
-      memcpy (dbl_buffer, raw_buffer[HI], 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
-      flt1 = unpack_double (builtin_type_float,
-                           &raw_buffer[HI][offset], &inv1);
-      doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
-
-      printf_filtered (inv1 ? " %-5s: <invalid float>" :
-                      " %-5s flt: %-17.9g", REGISTER_NAME (regnum), flt1);
-      printf_filtered (inv3 ? " dbl: <invalid double>\n" :
-                      " dbl: %-24.17g\n", doub);
+    {
+      /* Eight byte registers: print each one as float AND as double.  */
+      mips_read_fp_register_single (regnum, raw_buffer);
+      flt1 = unpack_double (mips_double_register_type (), raw_buffer, &inv1);
+
+      mips_read_fp_register_double (regnum, raw_buffer);
+      doub = unpack_double (mips_double_register_type (), raw_buffer, &inv3);
+
+      printf_filtered (" %-5s: ", REGISTER_NAME (regnum));
+      if (inv1)
+       printf_filtered ("<invalid float>");
+      else
+       printf_filtered ("flt: %-17.9g", flt1);
+
+      printf_filtered (" dbl: ");
+      if (inv3)
+       printf_filtered ("<invalid double>");
+      else
+       printf_filtered ("%-24.17g", doub);
+
+      printf_filtered ("\n");
       /* may want to do hex display here (future enhancement) */
       regnum++;
     }
       /* may want to do hex display here (future enhancement) */
       regnum++;
     }
@@ -2737,13 +3134,13 @@ do_gp_register_row (int regnum)
       if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
        break;                  /* end row: reached FP register */
       /* OK: get the data in raw format.  */
       if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
        break;                  /* end row: reached FP register */
       /* OK: get the data in raw format.  */
-      if (read_relative_register_raw_bytes (regnum, raw_buffer))
+      if (!frame_register_read (selected_frame, regnum, raw_buffer))
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
       /* pad small registers */
       for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
        printf_filtered ("  ");
       /* Now print the register value in hex, endian order. */
        error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
       /* pad small registers */
       for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_VIRTUAL_SIZE (regnum)); byte++)
        printf_filtered ("  ");
       /* Now print the register value in hex, endian order. */
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte++)
        for (byte = REGISTER_RAW_SIZE (regnum) - REGISTER_VIRTUAL_SIZE (regnum);
             byte < REGISTER_RAW_SIZE (regnum);
             byte++)
@@ -3086,9 +3483,9 @@ return_value_location (struct type *valtype,
        {
          /* We need to break a 64bit float in two 32 bit halves and
             spread them across a floating-point register pair. */
        {
          /* We need to break a 64bit float in two 32 bit halves and
             spread them across a floating-point register pair. */
-         lo->buf_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
-         hi->buf_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 0 : 4;
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BIG_ENDIAN
+         lo->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 4 : 0;
+         hi->buf_offset = TARGET_BYTE_ORDER == BFD_ENDIAN_BIG ? 0 : 4;
+         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8)
                            ? 4 : 0);
          hi->reg_offset = lo->reg_offset;
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8)
                            ? 4 : 0);
          hi->reg_offset = lo->reg_offset;
@@ -3101,7 +3498,7 @@ return_value_location (struct type *valtype,
        {
          /* The floating point value fits in a single floating-point
             register. */
        {
          /* The floating point value fits in a single floating-point
             register. */
-         lo->reg_offset = ((TARGET_BYTE_ORDER == BIG_ENDIAN
+         lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8
                             && len == 4)
                            ? 4 : 0);
                             && REGISTER_RAW_SIZE (FP0_REGNUM) == 8
                             && len == 4)
                            ? 4 : 0);
@@ -3120,7 +3517,7 @@ return_value_location (struct type *valtype,
       int regnum = 2;
       lo->reg = regnum + 0;
       hi->reg = regnum + 1;
       int regnum = 2;
       lo->reg = regnum + 0;
       hi->reg = regnum + 1;
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && len < MIPS_SAVED_REGSIZE)
        {
          /* "un-left-justify" the value in the low register */
          && len < MIPS_SAVED_REGSIZE)
        {
          /* "un-left-justify" the value in the low register */
@@ -3129,7 +3526,7 @@ return_value_location (struct type *valtype,
          hi->reg_offset = 0;
          hi->len = 0;
        }
          hi->reg_offset = 0;
          hi->len = 0;
        }
-      else if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      else if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
               && len > MIPS_SAVED_REGSIZE      /* odd-size structs */
               && len < MIPS_SAVED_REGSIZE * 2
               && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
               && len > MIPS_SAVED_REGSIZE      /* odd-size structs */
               && len < MIPS_SAVED_REGSIZE * 2
               && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT ||
@@ -3157,7 +3554,7 @@ return_value_location (struct type *valtype,
              hi->len = 0;
            }
        }
              hi->len = 0;
            }
        }
-      if (TARGET_BYTE_ORDER == BIG_ENDIAN
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
          && REGISTER_RAW_SIZE (regnum) == 8
          && MIPS_SAVED_REGSIZE == 4)
        {
          && REGISTER_RAW_SIZE (regnum) == 8
          && MIPS_SAVED_REGSIZE == 4)
        {
@@ -3181,7 +3578,7 @@ mips_extract_return_value (struct type *valtype,
 {
   struct return_value_word lo;
   struct return_value_word hi;
 {
   struct return_value_word lo;
   struct return_value_word hi;
-  return_value_location (valtype, &lo, &hi);
+  return_value_location (valtype, &hi, &lo);
 
   memcpy (valbuf + lo.buf_offset,
          regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset,
 
   memcpy (valbuf + lo.buf_offset,
          regbuf + REGISTER_BYTE (lo.reg) + lo.reg_offset,
@@ -3202,7 +3599,7 @@ mips_store_return_value (struct type *valtype, char *valbuf)
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
   struct return_value_word lo;
   struct return_value_word hi;
   char raw_buffer[MAX_REGISTER_RAW_SIZE];
   struct return_value_word lo;
   struct return_value_word hi;
-  return_value_location (valtype, &lo, &hi);
+  return_value_location (valtype, &hi, &lo);
 
   memset (raw_buffer, 0, sizeof (raw_buffer));
   memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
 
   memset (raw_buffer, 0, sizeof (raw_buffer));
   memcpy (raw_buffer + lo.reg_offset, valbuf + lo.buf_offset, lo.len);
@@ -3251,7 +3648,6 @@ set_mips_command (char *args, int from_tty)
 static void
 show_mipsfpu_command (char *args, int from_tty)
 {
 static void
 show_mipsfpu_command (char *args, int from_tty)
 {
-  char *msg;
   char *fpu;
   switch (MIPS_FPU_TYPE)
     {
   char *fpu;
   switch (MIPS_FPU_TYPE)
     {
@@ -3264,6 +3660,8 @@ show_mipsfpu_command (char *args, int from_tty)
     case MIPS_FPU_NONE:
       fpu = "absent (none)";
       break;
     case MIPS_FPU_NONE:
       fpu = "absent (none)";
       break;
+    default:
+      internal_error (__FILE__, __LINE__, "bad switch");
     }
   if (mips_fpu_type_auto)
     printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
     }
   if (mips_fpu_type_auto)
     printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
@@ -3286,10 +3684,7 @@ set_mipsfpu_single_command (char *args, int from_tty)
 {
   mips_fpu_type = MIPS_FPU_SINGLE;
   mips_fpu_type_auto = 0;
 {
   mips_fpu_type = MIPS_FPU_SINGLE;
   mips_fpu_type_auto = 0;
-  if (GDB_MULTI_ARCH)
-    {
-      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE;
-    }
+  gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE;
 }
 
 static void
 }
 
 static void
@@ -3297,10 +3692,7 @@ set_mipsfpu_double_command (char *args, int from_tty)
 {
   mips_fpu_type = MIPS_FPU_DOUBLE;
   mips_fpu_type_auto = 0;
 {
   mips_fpu_type = MIPS_FPU_DOUBLE;
   mips_fpu_type_auto = 0;
-  if (GDB_MULTI_ARCH)
-    {
-      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE;
-    }
+  gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE;
 }
 
 static void
 }
 
 static void
@@ -3308,10 +3700,7 @@ set_mipsfpu_none_command (char *args, int from_tty)
 {
   mips_fpu_type = MIPS_FPU_NONE;
   mips_fpu_type_auto = 0;
 {
   mips_fpu_type = MIPS_FPU_NONE;
   mips_fpu_type_auto = 0;
-  if (GDB_MULTI_ARCH)
-    {
-      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE;
-    }
+  gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE;
 }
 
 static void
 }
 
 static void
@@ -3357,7 +3746,7 @@ mips_show_processor_type_command (char *args, int from_tty)
 int
 mips_set_processor_type (char *str)
 {
 int
 mips_set_processor_type (char *str)
 {
-  int i, j;
+  int i;
 
   if (str == NULL)
     return 0;
 
   if (str == NULL)
     return 0;
@@ -3420,17 +3809,17 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
      it's definitely a 16-bit function.  Otherwise, we have to just
      guess that if the address passed in is odd, it's 16-bits.  */
   if (proc_desc)
      it's definitely a 16-bit function.  Otherwise, we have to just
      guess that if the address passed in is odd, it's 16-bits.  */
   if (proc_desc)
-    info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ? 
+    info->mach = pc_is_mips16 (PROC_LOW_ADDR (proc_desc)) ?
       bfd_mach_mips16 : TM_PRINT_INSN_MACH;
   else
       bfd_mach_mips16 : TM_PRINT_INSN_MACH;
   else
-    info->mach = pc_is_mips16 (memaddr) ? 
+    info->mach = pc_is_mips16 (memaddr) ?
       bfd_mach_mips16 : TM_PRINT_INSN_MACH;
 
   /* Round down the instruction address to the appropriate boundary.  */
   memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
       bfd_mach_mips16 : TM_PRINT_INSN_MACH;
 
   /* Round down the instruction address to the appropriate boundary.  */
   memaddr &= (info->mach == bfd_mach_mips16 ? ~1 : ~3);
 
   /* Call the appropriate disassembler based on the target endian-ness.  */
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     return print_insn_big_mips (memaddr, info);
   else
     return print_insn_little_mips (memaddr, info);
     return print_insn_big_mips (memaddr, info);
   else
     return print_insn_little_mips (memaddr, info);
@@ -3456,23 +3845,24 @@ gdb_print_insn_mips (bfd_vma memaddr, disassemble_info *info)
    (if necessary) to point to the actual memory location where the
    breakpoint should be inserted.  */
 
    (if necessary) to point to the actual memory location where the
    breakpoint should be inserted.  */
 
-unsigned char *
+const unsigned char *
 mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
 {
 mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
 {
-  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
     {
       if (pc_is_mips16 (*pcptr))
        {
     {
       if (pc_is_mips16 (*pcptr))
        {
-         static char mips16_big_breakpoint[] = MIPS16_BIG_BREAKPOINT;
+         static unsigned char mips16_big_breakpoint[] =
+           MIPS16_BIG_BREAKPOINT;
          *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
          *lenptr = sizeof (mips16_big_breakpoint);
          return mips16_big_breakpoint;
        }
       else
        {
          *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
          *lenptr = sizeof (mips16_big_breakpoint);
          return mips16_big_breakpoint;
        }
       else
        {
-         static char big_breakpoint[] = BIG_BREAKPOINT;
-         static char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
-         static char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
+         static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+         static unsigned char pmon_big_breakpoint[] = PMON_BIG_BREAKPOINT;
+         static unsigned char idt_big_breakpoint[] = IDT_BIG_BREAKPOINT;
 
          *lenptr = sizeof (big_breakpoint);
 
 
          *lenptr = sizeof (big_breakpoint);
 
@@ -3490,16 +3880,19 @@ mips_breakpoint_from_pc (CORE_ADDR * pcptr, int *lenptr)
     {
       if (pc_is_mips16 (*pcptr))
        {
     {
       if (pc_is_mips16 (*pcptr))
        {
-         static char mips16_little_breakpoint[] = MIPS16_LITTLE_BREAKPOINT;
+         static unsigned char mips16_little_breakpoint[] =
+           MIPS16_LITTLE_BREAKPOINT;
          *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
          *lenptr = sizeof (mips16_little_breakpoint);
          return mips16_little_breakpoint;
        }
       else
        {
          *pcptr = UNMAKE_MIPS16_ADDR (*pcptr);
          *lenptr = sizeof (mips16_little_breakpoint);
          return mips16_little_breakpoint;
        }
       else
        {
-         static char little_breakpoint[] = LITTLE_BREAKPOINT;
-         static char pmon_little_breakpoint[] = PMON_LITTLE_BREAKPOINT;
-         static char idt_little_breakpoint[] = IDT_LITTLE_BREAKPOINT;
+         static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+         static unsigned char pmon_little_breakpoint[] =
+           PMON_LITTLE_BREAKPOINT;
+         static unsigned char idt_little_breakpoint[] =
+           IDT_LITTLE_BREAKPOINT;
 
          *lenptr = sizeof (little_breakpoint);
 
 
          *lenptr = sizeof (little_breakpoint);
 
@@ -3812,7 +4205,7 @@ mips_stab_reg_to_regnum (int num)
 {
   if (num < 32)
     return num;
 {
   if (num < 32)
     return num;
-  else 
+  else
     return num + FP0_REGNUM - 38;
 }
 
     return num + FP0_REGNUM - 38;
 }
 
@@ -3827,6 +4220,59 @@ mips_ecoff_reg_to_regnum (int num)
     return num + FP0_REGNUM - 32;
 }
 
     return num + FP0_REGNUM - 32;
 }
 
+/* Convert an integer into an address.  By first converting the value
+   into a pointer and then extracting it signed, the address is
+   guarenteed to be correctly sign extended.  */
+
+static CORE_ADDR
+mips_integer_to_address (struct type *type, void *buf)
+{
+  char *tmp = alloca (TYPE_LENGTH (builtin_type_void_data_ptr));
+  LONGEST val = unpack_long (type, buf);
+  store_signed_integer (tmp, TYPE_LENGTH (builtin_type_void_data_ptr), val);
+  return extract_signed_integer (tmp,
+                                TYPE_LENGTH (builtin_type_void_data_ptr));
+}
+
+static void
+mips_find_abi_section (bfd *abfd, asection *sect, void *obj)
+{
+  enum mips_abi *abip = (enum mips_abi *) obj;
+  const char *name = bfd_get_section_name (abfd, sect);
+
+  if (*abip != MIPS_ABI_UNKNOWN)
+    return;
+
+  if (strncmp (name, ".mdebug.", 8) != 0)
+    return;
+
+  if (strcmp (name, ".mdebug.abi32") == 0)
+    *abip = MIPS_ABI_O32;
+  else if (strcmp (name, ".mdebug.abiN32") == 0)
+    *abip = MIPS_ABI_N32;
+  else if (strcmp (name, ".mdebug.abiO64") == 0)
+    *abip = MIPS_ABI_O64;
+  else if (strcmp (name, ".mdebug.eabi32") == 0)
+    *abip = MIPS_ABI_EABI32;
+  else if (strcmp (name, ".mdebug.eabi64") == 0)
+    *abip = MIPS_ABI_EABI64;
+  else
+    warning ("unsupported ABI %s.", name + 8);
+}
+
+static enum mips_abi
+global_mips_abi (void)
+{
+  int i;
+
+  for (i = 0; mips_abi_strings[i] != NULL; i++)
+    if (mips_abi_strings[i] == mips_abi_string)
+      return (enum mips_abi) i;
+
+  internal_error (__FILE__, __LINE__,
+                 "unknown ABI string");
+}
+
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info,
                   struct gdbarch_list *arches)
 static struct gdbarch *
 mips_gdbarch_init (struct gdbarch_info info,
                   struct gdbarch_list *arches)
@@ -3836,14 +4282,27 @@ mips_gdbarch_init (struct gdbarch_info info,
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
   int elf_flags;
   struct gdbarch *gdbarch;
   struct gdbarch_tdep *tdep;
   int elf_flags;
-  enum mips_abi mips_abi;
+  enum mips_abi mips_abi, found_abi, wanted_abi;
+  enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
 
 
-  /* Extract the elf_flags if available */
-  if (info.abfd != NULL
-      && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
-    elf_flags = elf_elfheader (info.abfd)->e_flags;
-  else
-    elf_flags = 0;
+  /* Reset the disassembly info, in case it was set to something
+     non-default.  */
+  tm_print_insn_info.flavour = bfd_target_unknown_flavour;
+  tm_print_insn_info.arch = bfd_arch_unknown;
+  tm_print_insn_info.mach = 0;
+
+  elf_flags = 0;
+
+  if (info.abfd)
+    {
+      /* First of all, extract the elf_flags, if available.  */
+      if (bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
+       elf_flags = elf_elfheader (info.abfd)->e_flags;
+
+      /* Try to determine the OS ABI of the object we are loading.  If
+        we end up with `unknown', just leave it that way.  */
+      osabi = gdbarch_lookup_osabi (info.abfd);
+    }
 
   /* Check ELF_FLAGS to see if it specifies the ABI being used. */
   switch ((elf_flags & EF_MIPS_ABI))
 
   /* Check ELF_FLAGS to see if it specifies the ABI being used. */
   switch ((elf_flags & EF_MIPS_ABI))
@@ -3868,6 +4327,15 @@ mips_gdbarch_init (struct gdbarch_info info,
       break;
     }
 
       break;
     }
 
+  /* GCC creates a pseudo-section whose name describes the ABI.  */
+  if (mips_abi == MIPS_ABI_UNKNOWN && info.abfd != NULL)
+    bfd_map_over_sections (info.abfd, mips_find_abi_section, &mips_abi);
+
+  /* If we have no bfd, then mips_abi will still be MIPS_ABI_UNKNOWN.
+     Use the ABI from the last architecture if there is one.  */
+  if (info.abfd == NULL && arches != NULL)
+    mips_abi = gdbarch_tdep (arches->gdbarch)->found_abi;
+
   /* Try the architecture for any hint of the corect ABI */
   if (mips_abi == MIPS_ABI_UNKNOWN
       && info.bfd_arch_info != NULL
   /* Try the architecture for any hint of the corect ABI */
   if (mips_abi == MIPS_ABI_UNKNOWN
       && info.bfd_arch_info != NULL
@@ -3882,13 +4350,28 @@ mips_gdbarch_init (struct gdbarch_info info,
        case bfd_mach_mips5000:
          mips_abi = MIPS_ABI_EABI64;
          break;
        case bfd_mach_mips5000:
          mips_abi = MIPS_ABI_EABI64;
          break;
+       case bfd_mach_mips8000:
+       case bfd_mach_mips10000:
+         mips_abi = MIPS_ABI_N32;
+         break;
        }
     }
        }
     }
+
 #ifdef MIPS_DEFAULT_ABI
   if (mips_abi == MIPS_ABI_UNKNOWN)
     mips_abi = MIPS_DEFAULT_ABI;
 #endif
 
 #ifdef MIPS_DEFAULT_ABI
   if (mips_abi == MIPS_ABI_UNKNOWN)
     mips_abi = MIPS_DEFAULT_ABI;
 #endif
 
+  if (mips_abi == MIPS_ABI_UNKNOWN)
+    mips_abi = MIPS_ABI_O32;
+
+  /* Now that we have found what the ABI for this binary would be,
+     check whether the user is overriding it.  */
+  found_abi = mips_abi;
+  wanted_abi = global_mips_abi ();
+  if (wanted_abi != MIPS_ABI_UNKNOWN)
+    mips_abi = wanted_abi;
+
   if (gdbarch_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
   if (gdbarch_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
@@ -3897,6 +4380,9 @@ mips_gdbarch_init (struct gdbarch_info info,
       fprintf_unfiltered (gdb_stdlog,
                          "mips_gdbarch_init: mips_abi = %d\n",
                          mips_abi);
       fprintf_unfiltered (gdb_stdlog,
                          "mips_gdbarch_init: mips_abi = %d\n",
                          mips_abi);
+      fprintf_unfiltered (gdb_stdlog,
+                         "mips_gdbarch_init: found_mips_abi = %d\n",
+                         found_abi);
     }
 
   /* try to find a pre-existing architecture */
     }
 
   /* try to find a pre-existing architecture */
@@ -3910,25 +4396,29 @@ mips_gdbarch_init (struct gdbarch_info info,
        continue;
       if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
        continue;
        continue;
       if (gdbarch_tdep (arches->gdbarch)->mips_abi != mips_abi)
        continue;
-      return arches->gdbarch;
+      if (gdbarch_tdep (arches->gdbarch)->osabi == osabi)
+        return arches->gdbarch;
     }
 
   /* Need a new architecture. Fill in a target specific vector. */
   tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
   tdep->elf_flags = elf_flags;
     }
 
   /* Need a new architecture. Fill in a target specific vector. */
   tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
   gdbarch = gdbarch_alloc (&info, tdep);
   tdep->elf_flags = elf_flags;
+  tdep->osabi = osabi;
 
 
-  /* Initially set everything according to the ABI. */
+  /* Initially set everything according to the default ABI/ISA. */
   set_gdbarch_short_bit (gdbarch, 16);
   set_gdbarch_int_bit (gdbarch, 32);
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_double_bit (gdbarch, 64);
   set_gdbarch_long_double_bit (gdbarch, 64);
   set_gdbarch_short_bit (gdbarch, 16);
   set_gdbarch_int_bit (gdbarch, 32);
   set_gdbarch_float_bit (gdbarch, 32);
   set_gdbarch_double_bit (gdbarch, 64);
   set_gdbarch_long_double_bit (gdbarch, 64);
+  set_gdbarch_register_raw_size (gdbarch, mips_register_raw_size);
+  tdep->found_abi = found_abi;
   tdep->mips_abi = mips_abi;
   tdep->mips_abi = mips_abi;
+
   switch (mips_abi)
     {
     case MIPS_ABI_O32:
   switch (mips_abi)
     {
     case MIPS_ABI_O32:
-      tdep->mips_abi_string = "o32";
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
@@ -3942,7 +4432,6 @@ mips_gdbarch_init (struct gdbarch_info info,
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_O64:
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_O64:
-      tdep->mips_abi_string = "o64";
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
@@ -3950,13 +4439,12 @@ mips_gdbarch_init (struct gdbarch_info info,
       tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
       tdep->mips_regs_have_home_p = 1;
       tdep->gdb_target_is_mips64 = 1;
       tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
       tdep->mips_regs_have_home_p = 1;
       tdep->gdb_target_is_mips64 = 1;
-      tdep->default_mask_address_p = 0; 
+      tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_EABI32:
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_EABI32:
-      tdep->mips_abi_string = "eabi32";
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
@@ -3970,7 +4458,6 @@ mips_gdbarch_init (struct gdbarch_info info,
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_EABI64:
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_EABI64:
-       tdep->mips_abi_string = "eabi64";
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
@@ -3984,7 +4471,6 @@ mips_gdbarch_init (struct gdbarch_info info,
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_N32:
       set_gdbarch_long_long_bit (gdbarch, 64);
       break;
     case MIPS_ABI_N32:
-      tdep->mips_abi_string = "n32";
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
@@ -3996,21 +4482,21 @@ mips_gdbarch_init (struct gdbarch_info info,
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
       set_gdbarch_long_bit (gdbarch, 32);
       set_gdbarch_ptr_bit (gdbarch, 32);
       set_gdbarch_long_long_bit (gdbarch, 64);
+
+      /* Set up the disassembler info, so that we get the right
+        register names from libopcodes.  */
+      tm_print_insn_info.flavour = bfd_target_elf_flavour;
+      tm_print_insn_info.arch = bfd_arch_mips;
+      if (info.bfd_arch_info != NULL
+         && info.bfd_arch_info->arch == bfd_arch_mips
+         && info.bfd_arch_info->mach)
+       tm_print_insn_info.mach = info.bfd_arch_info->mach;
+      else
+       tm_print_insn_info.mach = bfd_mach_mips8000;
       break;
     default:
       break;
     default:
-      tdep->mips_abi_string = "default";
-      tdep->mips_default_saved_regsize = MIPS_REGSIZE;
-      tdep->mips_default_stack_argsize = MIPS_REGSIZE;
-      tdep->mips_fp_register_double = (REGISTER_VIRTUAL_SIZE (FP0_REGNUM) == 8);
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
-      tdep->mips_regs_have_home_p = 1;
-      tdep->gdb_target_is_mips64 = 0;
-      tdep->default_mask_address_p = 0;
-      set_gdbarch_long_bit (gdbarch, 32);
-      set_gdbarch_ptr_bit (gdbarch, 32);
-      set_gdbarch_long_long_bit (gdbarch, 64);
-      break;
+      internal_error (__FILE__, __LINE__,
+                     "unknown ABI in switch");
     }
 
   /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE
     }
 
   /* FIXME: jlarmour/2000-04-07: There *is* a flag EF_MIPS_32BIT_MODE
@@ -4021,7 +4507,7 @@ mips_gdbarch_init (struct gdbarch_info info,
      flag in object files because to do so would make it impossible to
      link with libraries compiled without "-gp32". This is
      unnecessarily restrictive.
      flag in object files because to do so would make it impossible to
      link with libraries compiled without "-gp32". This is
      unnecessarily restrictive.
+
      We could solve this problem by adding "-gp32" multilibs to gcc,
      but to set this flag before gcc is built with such multilibs will
      break too many systems.''
      We could solve this problem by adding "-gp32" multilibs to gcc,
      but to set this flag before gcc is built with such multilibs will
      break too many systems.''
@@ -4064,10 +4550,18 @@ mips_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_read_pc (gdbarch, mips_read_pc);
   set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
   set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
   set_gdbarch_read_pc (gdbarch, mips_read_pc);
   set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
   set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
-  set_gdbarch_write_fp (gdbarch, generic_target_write_fp);
   set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
   set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
 
   set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
   set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
 
+  /* Add/remove bits from an address. The MIPS needs be careful to
+     ensure that all 32 bit addresses are sign extended to 64 bits. */
+  set_gdbarch_addr_bits_remove (gdbarch, mips_addr_bits_remove);
+
+  /* There's a mess in stack frame creation.  See comments in
+     blockframe.c near reference to INIT_FRAME_PC_FIRST.  */
+  set_gdbarch_init_frame_pc_first (gdbarch, mips_init_frame_pc_first);
+  set_gdbarch_init_frame_pc (gdbarch, init_frame_pc_noop);
+
   /* Map debug register numbers onto internal register numbers. */
   set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
   set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum);
   /* Map debug register numbers onto internal register numbers. */
   set_gdbarch_stab_reg_to_regnum (gdbarch, mips_stab_reg_to_regnum);
   set_gdbarch_ecoff_reg_to_regnum (gdbarch, mips_ecoff_reg_to_regnum);
@@ -4100,14 +4594,32 @@ mips_gdbarch_init (struct gdbarch_info info,
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 0);
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, mips_breakpoint_from_pc);
   set_gdbarch_decr_pc_after_break (gdbarch, 0);
-  set_gdbarch_ieee_float (gdbarch, 1);
 
   set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
   set_gdbarch_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
 
 
   set_gdbarch_skip_prologue (gdbarch, mips_skip_prologue);
   set_gdbarch_saved_pc_after_call (gdbarch, mips_saved_pc_after_call);
 
+  set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address);
+  set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer);
+  set_gdbarch_integer_to_address (gdbarch, mips_integer_to_address);
+
+  /* Hook in OS ABI-specific overrides, if they have been registered.  */
+  gdbarch_init_osabi (info, gdbarch, osabi);
+
   return gdbarch;
 }
 
   return gdbarch;
 }
 
+static void
+mips_abi_update (char *ignore_args, int from_tty, 
+                struct cmd_list_element *c)
+{
+  struct gdbarch_info info;
+
+  /* Force the architecture to update, and (if it's a MIPS architecture)
+     mips_gdbarch_init will take care of the rest.  */
+  gdbarch_info_init (&info);
+  gdbarch_update_p (info);
+}
+
 static void
 mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
 {
 static void
 mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
 {
@@ -4129,9 +4641,10 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
          ef_mips_arch = 3;
          break;
        case E_MIPS_ARCH_4:
          ef_mips_arch = 3;
          break;
        case E_MIPS_ARCH_4:
-         ef_mips_arch = 0;
+         ef_mips_arch = 4;
          break;
        default:
          break;
        default:
+         ef_mips_arch = 0;
          break;
        }
       /* determine the size of a pointer */
          break;
        }
       /* determine the size of a pointer */
@@ -4148,7 +4661,7 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
       fprintf_unfiltered (file,
                          "mips_dump_tdep: tdep->mips_abi = %d (%s)\n",
                          tdep->mips_abi,
       fprintf_unfiltered (file,
                          "mips_dump_tdep: tdep->mips_abi = %d (%s)\n",
                          tdep->mips_abi,
-                         tdep->mips_abi_string);
+                         mips_abi_strings[tdep->mips_abi]);
       fprintf_unfiltered (file,
                          "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
                          mips_mask_address_p (),
       fprintf_unfiltered (file,
                          "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
                          mips_mask_address_p (),
@@ -4268,15 +4781,6 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                      "mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
                      XSTRING (IGNORE_HELPER_CALL (PC)));
   fprintf_unfiltered (file,
                      "mips_dump_tdep: IGNORE_HELPER_CALL # %s\n",
                      XSTRING (IGNORE_HELPER_CALL (PC)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: INIT_FRAME_PC # %s\n",
-                     XSTRING (INIT_FRAME_PC (FROMLEAF, PREV)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: INIT_FRAME_PC_FIRST # %s\n",
-                     XSTRING (INIT_FRAME_PC_FIRST (FROMLEAF, PREV)));
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: IN_SIGTRAMP # %s\n",
-                     XSTRING (IN_SIGTRAMP (PC, NAME)));
   fprintf_unfiltered (file,
                      "mips_dump_tdep: IN_SOLIB_CALL_TRAMPOLINE # %s\n",
                      XSTRING (IN_SOLIB_CALL_TRAMPOLINE (PC, NAME)));
   fprintf_unfiltered (file,
                      "mips_dump_tdep: IN_SOLIB_CALL_TRAMPOLINE # %s\n",
                      XSTRING (IN_SOLIB_CALL_TRAMPOLINE (PC, NAME)));
@@ -4442,11 +4946,8 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
                      "mips_dump_tdep: SOFTWARE_SINGLE_STEP # %s\n",
                      XSTRING (SOFTWARE_SINGLE_STEP (SIG, BP_P)));
   fprintf_unfiltered (file,
                      "mips_dump_tdep: SOFTWARE_SINGLE_STEP # %s\n",
                      XSTRING (SOFTWARE_SINGLE_STEP (SIG, BP_P)));
   fprintf_unfiltered (file,
-                     "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P = %d\n",
-                     SOFTWARE_SINGLE_STEP_P);
-  fprintf_unfiltered (file,
-                     "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P = %d\n",
-                     SOFTWARE_SINGLE_STEP_P);
+                     "mips_dump_tdep: SOFTWARE_SINGLE_STEP_P () = %d\n",
+                     SOFTWARE_SINGLE_STEP_P ());
   fprintf_unfiltered (file,
                      "mips_dump_tdep: STAB_REG_TO_REGNUM # %s\n",
                      XSTRING (STAB_REG_TO_REGNUM (REGNUM)));
   fprintf_unfiltered (file,
                      "mips_dump_tdep: STAB_REG_TO_REGNUM # %s\n",
                      XSTRING (STAB_REG_TO_REGNUM (REGNUM)));
@@ -4524,6 +5025,10 @@ mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
   fprintf_unfiltered (file,
                      "mips_dump_tdep: _PROC_MAGIC_ = %d\n",
                      _PROC_MAGIC_);
   fprintf_unfiltered (file,
                      "mips_dump_tdep: _PROC_MAGIC_ = %d\n",
                      _PROC_MAGIC_);
+
+  fprintf_unfiltered (file,
+                     "mips_dump_tdep: OS ABI = %s\n",
+                     gdbarch_osabi_name (tdep->osabi));
 }
 
 void
 }
 
 void
@@ -4532,6 +5037,11 @@ _initialize_mips_tdep (void)
   static struct cmd_list_element *mipsfpulist = NULL;
   struct cmd_list_element *c;
 
   static struct cmd_list_element *mipsfpulist = NULL;
   struct cmd_list_element *c;
 
+  mips_abi_string = mips_abi_strings [MIPS_ABI_UNKNOWN];
+  if (MIPS_ABI_LAST + 1
+      != sizeof (mips_abi_strings) / sizeof (mips_abi_strings[0]))
+    internal_error (__FILE__, __LINE__, "mips_abi_strings out of sync");
+
   gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
   if (!tm_print_insn)          /* Someone may have already set it */
     tm_print_insn = gdb_print_insn_mips;
   gdbarch_register (bfd_arch_mips, mips_gdbarch_init, mips_dump_tdep);
   if (!tm_print_insn)          /* Someone may have already set it */
     tm_print_insn = gdb_print_insn_mips;
@@ -4574,6 +5084,21 @@ This option can be set to one of:\n\
                                       &setmipscmdlist),
                     &showmipscmdlist);
 
                                       &setmipscmdlist),
                     &showmipscmdlist);
 
+  /* Allow the user to override the ABI. */
+  c = add_set_enum_cmd
+    ("abi", class_obscure, mips_abi_strings, &mips_abi_string,
+     "Set the ABI used by this program.\n"
+     "This option can be set to one of:\n"
+     "  auto  - the default ABI associated with the current binary\n"
+     "  o32\n"
+     "  o64\n"
+     "  n32\n"
+     "  eabi32\n"
+     "  eabi64",
+     &setmipscmdlist);
+  add_show_from_set (c, &showmipscmdlist);
+  set_cmd_sfunc (c, mips_abi_update);
+
   /* Let the user turn off floating point and set the fence post for
      heuristic_proc_start.  */
 
   /* Let the user turn off floating point and set the fence post for
      heuristic_proc_start.  */
 
@@ -4602,21 +5127,6 @@ This option can be set to one of:\n\
           "Show current use of MIPS floating-point coprocessor target.",
           &showlist);
 
           "Show current use of MIPS floating-point coprocessor target.",
           &showlist);
 
-#if !GDB_MULTI_ARCH
-  c = add_set_cmd ("processor", class_support, var_string_noescape,
-                  (char *) &tmp_mips_processor_type,
-                  "Set the type of MIPS processor in use.\n\
-Set this to be able to access processor-type-specific registers.\n\
-",
-                  &setlist);
-  c->function.cfunc = mips_set_processor_type_command;
-  c = add_show_from_set (c, &showlist);
-  c->function.cfunc = mips_show_processor_type_command;
-
-  tmp_mips_processor_type = xstrdup (DEFAULT_MIPS_TYPE);
-  mips_set_processor_type_command (xstrdup (DEFAULT_MIPS_TYPE), 0);
-#endif
-
   /* We really would like to have both "0" and "unlimited" work, but
      command.c doesn't deal with that.  So make it a var_zinteger
      because the user can always use "999999" or some such for unlimited.  */
   /* We really would like to have both "0" and "unlimited" work, but
      command.c doesn't deal with that.  So make it a var_zinteger
      because the user can always use "999999" or some such for unlimited.  */
@@ -4630,18 +5140,18 @@ search.  The only need to set it is when debugging a stripped executable.",
                   &setlist);
   /* We need to throw away the frame cache when we set this, since it
      might change our ability to get backtraces.  */
                   &setlist);
   /* We need to throw away the frame cache when we set this, since it
      might change our ability to get backtraces.  */
-  c->function.sfunc = reinit_frame_cache_sfunc;
+  set_cmd_sfunc (c, reinit_frame_cache_sfunc);
   add_show_from_set (c, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
      addresses should be zeroed.  */
   add_show_from_set (c, &showlist);
 
   /* Allow the user to control whether the upper bits of 64-bit
      addresses should be zeroed.  */
-  c = add_set_auto_boolean_cmd ("mask-address", no_class, &mask_address_var,
-                               "Set zeroing of upper 32 bits of 64-bit addresses.\n\
-Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to allow GDB to determine\n\
-the correct value.\n",
-                               &setmipscmdlist);
-  add_cmd ("mask-address", no_class, show_mask_address,
-              "Show current mask-address value", &showmipscmdlist);
+  add_setshow_auto_boolean_cmd ("mask-address", no_class, &mask_address_var, "\
+Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Use \"on\" to enable the masking, \"off\" to disable it and \"auto\" to \n\
+allow GDB to determine the correct value.\n", "\
+Show zeroing of upper 32 bits of 64-bit addresses.",
+                               NULL, show_mask_address,
+                               &setmipscmdlist, &showmipscmdlist);
 
   /* Allow the user to control the size of 32 bit registers within the
      raw remote packet.  */
 
   /* Allow the user to control the size of 32 bit registers within the
      raw remote packet.  */
@@ -4662,4 +5172,3 @@ that would transfer 32 bits for some registers (e.g. SR, FSR) and\n\
 When non-zero, mips specific debugging is enabled.", &setdebuglist),
                     &showdebuglist);
 }
 When non-zero, mips specific debugging is enabled.", &setdebuglist),
                     &showdebuglist);
 }
-
This page took 0.049848 seconds and 4 git commands to generate.