1999-01-19 Fernando Nasser <fnasser@totem.to.cygnus.com>
[deliverable/binutils-gdb.git] / gdb / mips-tdep.c
index 41dc0cad017d4cc4e3ee852e9764505f9c048cdd..0cd00636028db4a4f578ecd242280b9feff4fc44 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-dependent code for the MIPS architecture, for GDB, the GNU Debugger.
-   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+   Copyright 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
    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.
@@ -35,11 +35,68 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "target.h"
 
 #include "opcode/mips.h"
+/* start-sanitize-carp start-sanitize-vr4xxx */
+#include "elf/mips.h"
+#include "elf-bfd.h"
+
+/* end-sanitize-carp end-sanitize-vr4xxx */
+
+/* Some MIPS boards don't support floating point, so we permit the
+   user to turn it off.  */
+
+enum mips_fpu_type
+{
+  MIPS_FPU_DOUBLE,     /* Full double precision floating point.  */
+  MIPS_FPU_SINGLE,     /* Single precision floating point (R4650).  */
+  MIPS_FPU_NONE                /* No floating point.  */
+};
+
+#ifndef MIPS_DEFAULT_FPU_TYPE
+#define MIPS_DEFAULT_FPU_TYPE MIPS_FPU_DOUBLE
+#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
+
+/* start-sanitize-carp start-sanitize-vr4xxx */
+
+/* MIPS specific per-architecture information */
+struct gdbarch_tdep
+{
+  int elf_abi;
+  /* mips options */
+  int mips_eabi;
+  enum mips_fpu_type mips_fpu_type;
+  int mips_last_arg_regnum;
+  int mips_last_fp_arg_regnum;
+};
+
+#if GDB_MULTI_ARCH
+#undef MIPS_EABI
+#define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_eabi)
+#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)
+#endif
+
+#if GDB_MULTI_ARCH
+#undef 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)
+#endif
+
+/* end-sanitize-carp end-sanitize-vr4xxx */
 
 #define VM_MIN_ADDRESS (CORE_ADDR)0x400000
 
-/* FIXME: Put this declaration in frame.h.  */
-extern struct obstack frame_cache_obstack;
+/* Do not use "TARGET_IS_MIPS64" to test the size of floating point registers */
+#define FP_REGISTER_DOUBLE (REGISTER_VIRTUAL_SIZE(FP0_REGNUM) == 8)
 
 #if 0
 static int mips_in_lenient_prologue PARAMS ((CORE_ADDR, CORE_ADDR));
@@ -56,12 +113,6 @@ static CORE_ADDR heuristic_proc_start PARAMS ((CORE_ADDR));
 
 static CORE_ADDR read_next_frame_reg PARAMS ((struct frame_info *, int));
 
-static void mips_set_fpu_command PARAMS ((char *, int,
-                                         struct cmd_list_element *));
-
-static void mips_show_fpu_command PARAMS ((char *, int,
-                                          struct cmd_list_element *));
-
 void mips_set_processor_type_command PARAMS ((char *, int));
 
 int mips_set_processor_type PARAMS ((char *));
@@ -84,13 +135,6 @@ char *mips_processor_type;
 
 char *tmp_mips_processor_type;
 
-/* Some MIPS boards don't support floating point, so we permit the
-   user to turn it off.  */
-
-enum mips_fpu_type mips_fpu;
-
-static char *mips_fpu_string;
-
 /* A set of original names, to be used when restoring back to generic
    registers from a specific set.  */
 
@@ -208,6 +252,21 @@ struct linked_proc_info
 } *linked_proc_desc_table = NULL;
 
 
+/* Should the upper word of 64-bit addresses be zeroed? */
+static int mask_address_p = 1;
+
+/* Should call_function allocate stack space for a struct return?  */
+int
+mips_use_struct_convention (gcc_p, type)
+     int gcc_p;
+     struct type *type;
+{
+  if (MIPS_EABI)
+    return (TYPE_LENGTH (type) > 2 * MIPS_REGSIZE);
+  else
+    return 1; /* Structures are returned by ref in extra arg0 */
+}
+
 /* Tell if the program counter value in MEMADDR is in a MIPS16 function.  */
 
 static int
@@ -282,6 +341,9 @@ mips32_decode_reg_save (inst, gen_mask, float_mask)
 
   if ((inst & 0xffe00000) == 0xafa00000                /* sw reg,n($sp) */
       || (inst & 0xffe00000) == 0xafc00000     /* sw reg,n($r30) */
+      /* start-sanitize-r5900 */
+      || (inst & 0xffe00000) == 0x7fa00000     /* sq reg,n($sp) */
+      /* end-sanitize-r5900 */
       || (inst & 0xffe00000) == 0xffa00000)    /* sd reg,n($sp) */
     {
       /* It might be possible to use the instruction to
@@ -808,9 +870,7 @@ mips_find_saved_regs (fci)
   mips_extra_func_info_t proc_desc;
   t_inst inst;
 
-  fci->saved_regs = (struct frame_saved_regs *)
-    obstack_alloc (&frame_cache_obstack, sizeof(struct frame_saved_regs));
-  memset (fci->saved_regs, 0, sizeof (struct frame_saved_regs));
+  frame_saved_regs_zalloc (fci);
 
   /* If it is the frame for sigtramp, the saved registers are located
      in a sigcontext structure somewhere on the stack.
@@ -836,15 +896,15 @@ mips_find_saved_regs (fci)
        {
          reg_position = fci->frame + SIGFRAME_REGSAVE_OFF
                         + ireg * SIGFRAME_REG_SIZE;
-         fci->saved_regs->regs[ireg] = reg_position;
+         fci->saved_regs[ireg] = reg_position;
        }
       for (ireg = 0; ireg < MIPS_NUMREGS; ireg++)
        {
          reg_position = fci->frame + SIGFRAME_FPREGSAVE_OFF
                         + ireg * SIGFRAME_REG_SIZE;
-         fci->saved_regs->regs[FP0_REGNUM + ireg] = reg_position;
+         fci->saved_regs[FP0_REGNUM + ireg] = reg_position;
        }
-      fci->saved_regs->regs[PC_REGNUM] = fci->frame + SIGFRAME_PC_OFF;
+      fci->saved_regs[PC_REGNUM] = fci->frame + SIGFRAME_PC_OFF;
       return;
     }
 
@@ -914,8 +974,17 @@ mips_find_saved_regs (fci)
   for (ireg= MIPS_NUMREGS-1; gen_mask; --ireg, gen_mask <<= 1)
     if (gen_mask & 0x80000000)
       {
-       fci->saved_regs->regs[ireg] = reg_position;
+       fci->saved_regs[ireg] = reg_position;
        reg_position -= MIPS_REGSIZE;
+       /* start-sanitize-r5900 */
+#ifdef R5900_128BIT_GPR_HACK
+       /* Gross.  The r5900 has 128bit wide registers, but MIPS_REGSIZE is
+          still 64bits.  See the comments in tm.h for a discussion of the
+          various problems this causes.  */
+       if (ireg <= RA_REGNUM)
+         reg_position -= MIPS_REGSIZE;
+#endif
+       /* end-sanitize-r5900 */
       }
 
   /* The MIPS16 entry instruction saves $s0 and $s1 in the reverse order
@@ -938,7 +1007,7 @@ mips_find_saved_regs (fci)
          /* Check if the s0 and s1 registers were pushed on the stack.  */
          for (reg = 16; reg < sreg_count+16; reg++)
            {
-             fci->saved_regs->regs[reg] = reg_position;
+             fci->saved_regs[reg] = reg_position;
              reg_position -= MIPS_REGSIZE;
            }
        }
@@ -958,11 +1027,11 @@ mips_find_saved_regs (fci)
   for (ireg = MIPS_NUMREGS-1; float_mask; --ireg, float_mask <<= 1)
     if (float_mask & 0x80000000)
       {
-       fci->saved_regs->regs[FP0_REGNUM+ireg] = reg_position;
+       fci->saved_regs[FP0_REGNUM+ireg] = reg_position;
        reg_position -= MIPS_REGSIZE;
       }
 
-  fci->saved_regs->regs[PC_REGNUM] = fci->saved_regs->regs[RA_REGNUM];
+  fci->saved_regs[PC_REGNUM] = fci->saved_regs[RA_REGNUM];
 }
 
 static CORE_ADDR
@@ -980,8 +1049,8 @@ read_next_frame_reg(fi, regno)
        {
          if (fi->saved_regs == NULL)
            mips_find_saved_regs (fi);
-         if (fi->saved_regs->regs[regno])
-           return read_memory_integer(fi->saved_regs->regs[regno], MIPS_REGSIZE);
+         if (fi->saved_regs[regno])
+           return read_memory_integer(fi->saved_regs[regno], MIPS_REGSIZE);
        }
     }
   return read_register (regno);
@@ -994,10 +1063,7 @@ mips_addr_bits_remove (addr)
     CORE_ADDR addr;
 {
 #if GDB_TARGET_IS_MIPS64
-  if ((addr >> 32 == (CORE_ADDR)0xffffffff)
-      && (strcmp (target_shortname,"pmon")==0
-        || strcmp (target_shortname,"ddb")==0
-        || strcmp (target_shortname,"sim")==0))
+  if (mask_address_p && (addr >> 32 == (CORE_ADDR)0xffffffff))
     {
       /* This hack is a work-around for existing boards using PMON,
         the simulator, and any other 64-bit targets that doesn't have
@@ -1075,12 +1141,32 @@ set_reg_offset (regno, offset)
 }
 
 
+/* Test whether the PC points to the return instruction at the
+   end of a function. */
+
+static int 
+mips_about_to_return (pc)
+     CORE_ADDR pc;
+{
+  if (pc_is_mips16 (pc))
+    /* This mips16 case isn't necessarily reliable.  Sometimes the compiler
+       generates a "jr $ra"; other times it generates code to load
+       the return address from the stack to an accessible register (such
+       as $a3), then a "jr" using that register.  This second case
+       is almost impossible to distinguish from an indirect jump
+       used for switch statements, so we don't even try.  */
+    return mips_fetch_instruction (pc) == 0xe820;      /* jr $ra */
+  else
+    return mips_fetch_instruction (pc) == 0x3e00008;   /* jr $ra */
+}
+
+
 /* This fencepost looks highly suspicious to me.  Removing it also
    seems suspicious as it could affect remote debugging across serial
    lines.  */
 
 static CORE_ADDR
-heuristic_proc_start(pc)
+heuristic_proc_start (pc)
     CORE_ADDR pc;
 {
     CORE_ADDR start_pc;
@@ -1154,7 +1240,7 @@ Otherwise, you told GDB there was a function where there isn't one, or\n\
            else
              seen_adjsp = 0;
          }
-       else if (ABOUT_TO_RETURN(start_pc))
+       else if (mips_about_to_return (start_pc))
          {
            start_pc += 2 * MIPS_INSTLEN; /* skip return, and its delay slot */
            break;
@@ -1355,6 +1441,7 @@ mips32_heuristic_proc_desc(start_pc, limit_pc, next_frame, sp)
   CORE_ADDR cur_pc;
   CORE_ADDR frame_addr = 0; /* Value of $r30. Used by gcc for frame-pointer */
 restart:
+  memset (&temp_saved_regs, '\0', sizeof(struct frame_saved_regs));
   PROC_FRAME_OFFSET(&temp_proc_desc) = 0;
   PROC_FRAME_ADJUST (&temp_proc_desc) = 0;     /* offset of FP from SP */
   for (cur_pc = start_pc; cur_pc < limit_pc; cur_pc += MIPS_INSTLEN)
@@ -1395,6 +1482,15 @@ restart:
          PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
          set_reg_offset (reg, sp + low_word + 8 - MIPS_REGSIZE);
        }
+      /* start-sanitize-r5900 */
+      else if ((high_word & 0xFFE0) == 0x7fa0) /* sq reg,offset($sp) */
+       {
+         /* I don't think we have to worry about the Irix 6.2 N32 ABI
+            issue noted int he sd reg, offset($sp) case above.  */
+         PROC_REG_MASK(&temp_proc_desc) |= 1 << reg;
+         set_reg_offset (reg, sp + low_word);
+       }
+      /* end-sanitize-r5900 */
       else if (high_word == 0x27be)                    /* addiu $30,$sp,size */
        {
          /* Old gcc frame, r30 is virtual frame pointer.  */
@@ -1660,12 +1756,11 @@ init_extra_frame_info(fci)
                                    (CORE_ADDR *)NULL,(CORE_ADDR *)NULL);
          if (!IN_SIGTRAMP (fci->pc, name))
            {
-             fci->saved_regs = (struct frame_saved_regs*)
-               obstack_alloc (&frame_cache_obstack,
-                              sizeof (struct frame_saved_regs));
-             *fci->saved_regs = temp_saved_regs;
-             fci->saved_regs->regs[PC_REGNUM]
-               = fci->saved_regs->regs[RA_REGNUM];
+             fci->saved_regs = (CORE_ADDR*)
+               frame_obstack_alloc (SIZEOF_FRAME_SAVED_REGS);
+             memcpy (fci->saved_regs, temp_saved_regs.regs, SIZEOF_FRAME_SAVED_REGS);
+             fci->saved_regs[PC_REGNUM]
+               = fci->saved_regs[RA_REGNUM];
            }
        }
 
@@ -1708,6 +1803,20 @@ setup_arbitrary_frame (argc, argv)
   return create_new_frame (argv[0], argv[1]);
 }
 
+/*
+ * STACK_ARGSIZE -- how many bytes does a pushed function arg take up on the stack?
+ *
+ * For n32 ABI, eight.
+ * For all others, he same as the size of a general register.
+ */
+#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
+#define MIPS_NABI32   1
+#define STACK_ARGSIZE 8
+#else
+#define MIPS_NABI32   0
+#define STACK_ARGSIZE MIPS_REGSIZE
+#endif
+
 CORE_ADDR
 mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
      int nargs;
@@ -1728,9 +1837,11 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
 #define ROUND_UP(n,a) (((n)+(a)-1) & ~((a)-1))
   
   /* First ensure that the stack and structure return address (if any)
-     are properly aligned. The stack has to be 64-bit aligned even
-     on 32-bit machines, because doubles must be 64-bit aligned. */
-  sp = ROUND_DOWN (sp, 8);
+     are properly aligned. The stack has to be at least 64-bit aligned
+     even on 32-bit machines, because doubles must be 64-bit aligned.
+     On at least one MIPS variant, stack frames need to be 128-bit
+     aligned, so we round to this widest known alignment. */
+  sp = ROUND_DOWN (sp, 16);
   struct_addr = ROUND_DOWN (struct_addr, MIPS_REGSIZE);
       
   /* Now make space on the stack for the args. We allocate more
@@ -1738,7 +1849,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
      passed in registers, but that's OK. */
   for (argnum = 0; argnum < nargs; argnum++)
     len += ROUND_UP (TYPE_LENGTH(VALUE_TYPE(args[argnum])), MIPS_REGSIZE);
-  sp -= ROUND_UP (len, 8);
+  sp -= ROUND_UP (len, 16);
 
   /* Initialize the integer and float register pointers.  */
   argreg = A0_REGNUM;
@@ -1775,7 +1886,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
 
       /* 32-bit ABIs always start floating point arguments in an
          even-numbered floating point register.   */
-      if (!GDB_TARGET_IS_MIPS64 && typecode == TYPE_CODE_FLT
+      if (!FP_REGISTER_DOUBLE && typecode == TYPE_CODE_FLT
           && (float_argreg & 1))
        float_argreg++;
 
@@ -1790,9 +1901,9 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
         because those registers are normally skipped.  */
       if (typecode == TYPE_CODE_FLT
          && float_argreg <= MIPS_LAST_FP_ARG_REGNUM
-         && mips_fpu != MIPS_FPU_NONE)
+         && MIPS_FPU_TYPE != MIPS_FPU_NONE)
        {
-         if (!GDB_TARGET_IS_MIPS64 && len == 8)
+         if (!FP_REGISTER_DOUBLE && len == 8)
            {
              int low_offset = TARGET_BYTE_ORDER == BIG_ENDIAN ? 4 : 0;
              unsigned long regval;
@@ -1822,7 +1933,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
              if (!MIPS_EABI)
                {
                  write_register (argreg, regval);
-                 argreg += GDB_TARGET_IS_MIPS64 ? 1 : 2;
+                 argreg += FP_REGISTER_DOUBLE ? 1 : 2;
                }
            }
        }
@@ -1850,15 +1961,15 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
 
                  int longword_offset = 0;
                  if (TARGET_BYTE_ORDER == BIG_ENDIAN)
-                   if (MIPS_REGSIZE == 8 &&
+                   if (STACK_ARGSIZE == 8 &&
                        (typecode == TYPE_CODE_INT ||
                         typecode == TYPE_CODE_PTR ||
                         typecode == TYPE_CODE_FLT) && len <= 4)
-                     longword_offset = MIPS_REGSIZE - len;
+                     longword_offset = STACK_ARGSIZE - len;
                    else if ((typecode == TYPE_CODE_STRUCT ||
                              typecode == TYPE_CODE_UNION) &&
-                            TYPE_LENGTH (arg_type) < MIPS_REGSIZE)
-                     longword_offset = MIPS_REGSIZE - len;
+                            TYPE_LENGTH (arg_type) < STACK_ARGSIZE)
+                     longword_offset = STACK_ARGSIZE - len;
 
                  write_memory (sp + stack_offset + longword_offset, 
                                val, partial_len);
@@ -1879,13 +1990,15 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
                     It does not seem to be necessary to do the
                     same for integral types.
 
-                    Also don't do this adjustment on EABI targets.  */
+                    Also don't do this adjustment on EABI and O64
+                    binaries. */
 
-                 if (!MIPS_EABI &&
-                     TARGET_BYTE_ORDER == BIG_ENDIAN &&
-                     partial_len < MIPS_REGSIZE &&
-                     (typecode == TYPE_CODE_STRUCT ||
-                      typecode == TYPE_CODE_UNION))
+                 if (!MIPS_EABI
+                     && (MIPS_REGSIZE < 8)
+                     && TARGET_BYTE_ORDER == BIG_ENDIAN
+                     && (partial_len < MIPS_REGSIZE)
+                     && (typecode == TYPE_CODE_STRUCT ||
+                         typecode == TYPE_CODE_UNION))
                    regval <<= ((MIPS_REGSIZE - partial_len) * 
                                TARGET_CHAR_BIT);
 
@@ -1907,12 +2020,14 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
                 begins at (4 * MIPS_REGSIZE) in the old ABI.  This 
                 leaves room for the "home" area for register parameters.
 
-                In the new EABI, the 8 register parameters do not 
-                have "home" stack space reserved for them, so the
+                In the new EABI (and the NABI32), the 8 register parameters 
+                do not have "home" stack space reserved for them, so the
                 stack offset does not get incremented until after
                 we have used up the 8 parameter registers.  */
-             if (!(MIPS_EABI && argnum < 8))
-               stack_offset += ROUND_UP (partial_len, MIPS_REGSIZE);
+
+             if (!(MIPS_EABI || MIPS_NABI32) ||
+                 argnum >= 8)
+               stack_offset += ROUND_UP (partial_len, STACK_ARGSIZE);
            }
        }
     }
@@ -1986,20 +2101,23 @@ mips_push_dummy_frame()
   mips_push_register (&sp, PC_REGNUM);
   mips_push_register (&sp, HI_REGNUM);
   mips_push_register (&sp, LO_REGNUM);
-  mips_push_register (&sp, mips_fpu == MIPS_FPU_NONE ? 0 : FCRCS_REGNUM);
+  mips_push_register (&sp, MIPS_FPU_TYPE == MIPS_FPU_NONE ? 0 : FCRCS_REGNUM);
 
   /* Save general CPU registers */
   PROC_REG_MASK(proc_desc) = GEN_REG_SAVE_MASK;
-  PROC_REG_OFFSET(proc_desc) = sp - old_sp; /* offset of (Saved R31) from FP */
+  /* PROC_REG_OFFSET is the offset of the first saved register from FP.  */
+  PROC_REG_OFFSET(proc_desc) = sp - old_sp - MIPS_REGSIZE;
   for (ireg = 32; --ireg >= 0; )
     if (PROC_REG_MASK(proc_desc) & (1 << ireg))
       mips_push_register (&sp, ireg);
 
   /* Save floating point registers starting with high order word */
   PROC_FREG_MASK(proc_desc) = 
-    mips_fpu == MIPS_FPU_DOUBLE ? FLOAT_REG_SAVE_MASK
-    : mips_fpu == MIPS_FPU_SINGLE ? FLOAT_SINGLE_REG_SAVE_MASK : 0;
-  PROC_FREG_OFFSET(proc_desc) = sp - old_sp; /* offset of (Saved D18) from FP */
+    MIPS_FPU_TYPE == MIPS_FPU_DOUBLE ? FLOAT_REG_SAVE_MASK
+    : MIPS_FPU_TYPE == MIPS_FPU_SINGLE ? FLOAT_SINGLE_REG_SAVE_MASK : 0;
+  /* PROC_FREG_OFFSET is the offset of the first saved *double* register
+     from FP.  */
+  PROC_FREG_OFFSET(proc_desc) = sp - old_sp - 8;
   for (ireg = 32; --ireg >= 0; )
     if (PROC_FREG_MASK(proc_desc) & (1 << ireg))
       mips_push_register (&sp, ireg + FP0_REGNUM);
@@ -2030,9 +2148,9 @@ mips_pop_frame()
   for (regnum = 0; regnum < NUM_REGS; regnum++)
     {
       if (regnum != SP_REGNUM && regnum != PC_REGNUM
-         && frame->saved_regs->regs[regnum])
+         && frame->saved_regs[regnum])
        write_register (regnum,
-                       read_memory_integer (frame->saved_regs->regs[regnum],
+                       read_memory_integer (frame->saved_regs[regnum],
                                             MIPS_REGSIZE)); 
     }
   write_register (SP_REGNUM, new_sp);
@@ -2064,7 +2182,7 @@ mips_pop_frame()
                read_memory_integer (new_sp - 2*MIPS_REGSIZE, MIPS_REGSIZE));
       write_register (LO_REGNUM,
                read_memory_integer (new_sp - 3*MIPS_REGSIZE, MIPS_REGSIZE));
-      if (mips_fpu != MIPS_FPU_NONE)
+      if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
        write_register (FCRCS_REGNUM,
                read_memory_integer (new_sp - 4*MIPS_REGSIZE, MIPS_REGSIZE));
     }
@@ -2079,14 +2197,14 @@ mips_print_register (regnum, all)
   /* Get the data in raw format.  */
   if (read_relative_register_raw_bytes (regnum, raw_buffer))
     {
-      printf_filtered ("%s: [Invalid]", reg_names[regnum]);
+      printf_filtered ("%s: [Invalid]", REGISTER_NAME (regnum));
       return;
     }
 
   /* If an even floating point register, also print as double. */
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
       && !((regnum-FP0_REGNUM) & 1))
-    if (REGISTER_RAW_SIZE(regnum) == 4)        /* this would be silly on MIPS64 */
+    if (REGISTER_RAW_SIZE(regnum) == 4)        /* this would be silly on MIPS64 or N32 (Irix 6) */
       {
        char dbuffer[2 * MAX_REGISTER_RAW_SIZE]; 
 
@@ -2095,11 +2213,11 @@ mips_print_register (regnum, all)
        REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
 
        printf_filtered ("(d%d: ", regnum-FP0_REGNUM);
-       val_print (builtin_type_double, dbuffer, 0,
+       val_print (builtin_type_double, dbuffer, 0, 0,
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
        printf_filtered ("); ");
       }
-  fputs_filtered (reg_names[regnum], gdb_stdout);
+  fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
 
   /* The problem with printing numeric register names (r26, etc.) is that
      the user can't use them on input.  Probably the best solution is to
@@ -2112,19 +2230,19 @@ mips_print_register (regnum, all)
 
   /* If virtual format is floating, print it that way.  */
   if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
-    if (REGISTER_RAW_SIZE(regnum) == 8)
+    if (FP_REGISTER_DOUBLE)
       { /* show 8-byte floats as float AND double: */
        int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
 
        printf_filtered (" (float) ");
-       val_print (builtin_type_float, raw_buffer + offset, 0,
+       val_print (builtin_type_float, raw_buffer + offset, 0, 0,
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
        printf_filtered (", (double) ");
-       val_print (builtin_type_double, raw_buffer, 0,
+       val_print (builtin_type_double, raw_buffer, 0, 0,
                   gdb_stdout, 0, 1, 0, Val_pretty_default);
       }
     else
-      val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0,
+      val_print (REGISTER_VIRTUAL_TYPE (regnum), raw_buffer, 0, 0,
                 gdb_stdout, 0, 1, 0, Val_pretty_default);
   /* Else print as integer in hex.  */
   else
@@ -2153,14 +2271,14 @@ do_fp_register_row (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, reg_names[regnum]);
+    error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
   if (REGISTER_RAW_SIZE(regnum) == 4)
     {
       /* 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, reg_names[regnum + 1]);
+              regnum + 1, REGISTER_NAME (regnum + 1));
 
       /* copy the two floats into one double, and unpack both */
       memcpy (dbl_buffer, raw_buffer, sizeof(dbl_buffer));
@@ -2169,9 +2287,9 @@ do_fp_register_row (regnum)
       doub = unpack_double (builtin_type_double, dbl_buffer,     &inv3);
 
       printf_filtered (inv1 ? " %-5s: <invalid float>" : 
-                      " %-5s%-17.9g", reg_names[regnum],     flt1);
+                      " %-5s%-17.9g", REGISTER_NAME (regnum),     flt1);
       printf_filtered (inv2 ? " %-5s: <invalid float>" : 
-                      " %-5s%-17.9g", reg_names[regnum + 1], flt2);
+                      " %-5s%-17.9g", REGISTER_NAME (regnum + 1), flt2);
       printf_filtered (inv3 ? " dbl: <invalid double>\n" : 
                       " dbl: %-24.17g\n", doub);
       /* may want to do hex display here (future enhancement) */
@@ -2187,7 +2305,7 @@ do_fp_register_row (regnum)
       doub = unpack_double (builtin_type_double, dbl_buffer,    &inv3);
 
       printf_filtered (inv1 ? " %-5s: <invalid float>" : 
-                      " %-5s flt: %-17.9g", reg_names[regnum], flt1);
+                      " %-5s flt: %-17.9g", REGISTER_NAME (regnum), flt1);
       printf_filtered (inv3 ? " dbl: <invalid double>\n" : 
                       " dbl: %-24.17g\n", doub);
       /* may want to do hex display here (future enhancement) */
@@ -2210,8 +2328,8 @@ do_gp_register_row (regnum)
   int numregs = NUM_REGS;
 
 /* start-sanitize-sky */
-#ifdef NUM_R5900_REGS
-  numregs = NUM_R5900_REGS;
+#ifdef NUM_CORE_REGS
+  numregs = NUM_CORE_REGS;
 #endif
 /* end-sanitize-sky */
 
@@ -2219,12 +2337,12 @@ do_gp_register_row (regnum)
   printf_filtered ("     ");
   for (col = 0; col < ncols && regnum < numregs; regnum++)
     {
-      if (*reg_names[regnum] == '\0')
+      if (*REGISTER_NAME (regnum) == '\0')
        continue;       /* unused register */
       if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
        break;  /* end the row: reached FP register */
       printf_filtered (MIPS_REGSIZE == 8 ? "%17s" : "%9s", 
-                      reg_names[regnum]);
+                      REGISTER_NAME (regnum));
       col++;
     }
   printf_filtered (start_regnum < MIPS_NUMREGS ? "\n R%-4d" : "\n      ", 
@@ -2234,13 +2352,13 @@ do_gp_register_row (regnum)
   /* now print the values in hex, 4 or 8 to the row */
   for (col = 0; col < ncols && regnum < numregs; regnum++)
     {
-      if (*reg_names[regnum] == '\0')
+      if (*REGISTER_NAME (regnum) == '\0')
        continue;       /* unused register */
       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))
-       error ("can't read register %d (%s)", regnum, reg_names[regnum]);
+       error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
       /* pad small registers */
       for (byte = 0; byte < (MIPS_REGSIZE - REGISTER_RAW_SIZE (regnum)); byte++)
        printf_filtered ("  ");
@@ -2269,7 +2387,7 @@ mips_do_registers_info (regnum, fpregs)
 {
   if (regnum != -1)    /* do one specified register */
     {
-      if (*(reg_names[regnum]) == '\0')
+      if (*(REGISTER_NAME (regnum)) == '\0')
        error ("Not a valid register for the current processor type");
 
       mips_print_register (regnum, 0);
@@ -2288,10 +2406,10 @@ mips_do_registers_info (regnum, fpregs)
          else
            regnum = do_gp_register_row (regnum);       /* GP (int) regs */
 /* start-sanitize-sky */
-#ifdef NUM_R5900_REGS
+#ifdef NUM_CORE_REGS
          /* For the sky project, NUM_REGS includes the vector slaves,
             which are handled elsewhere */
-         if (regnum >= NUM_R5900_REGS)
+         if (regnum >= NUM_CORE_REGS)
            break;
 #endif
 /* end-sanitize-sky */
@@ -2387,6 +2505,9 @@ mips32_skip_prologue (pc, lenient)
                 inst == 0x03a8e823)            /* subu $sp,$sp,$t0 */
            seen_sp_adjust = 1;
        else if (((inst & 0xFFE00000) == 0xAFA00000 /* sw reg,n($sp) */
+                 /* start-sanitize-r5900 */
+                 || (inst & 0xFFE00000) == 0x7FA00000 /* sq reg,n($sp) */
+                 /* end-sanitize-r5900 */
                  || (inst & 0xFFE00000) == 0xFFA00000) /* sd reg,n($sp) */
                 && (inst & 0x001F0000))        /* reg != $zero */
            continue;
@@ -2583,8 +2704,9 @@ mips_extract_return_value (valtype, regbuf, valbuf)
   
   regnum = 2;
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT
-      && (mips_fpu == MIPS_FPU_DOUBLE
-         || (mips_fpu == MIPS_FPU_SINGLE && len <= MIPS_FPU_SINGLE_REGSIZE)))
+      && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
+         || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
+             && len <= MIPS_FPU_SINGLE_REGSIZE)))
     regnum = FP0_REGNUM;
 
   if (TARGET_BYTE_ORDER == BIG_ENDIAN)
@@ -2615,8 +2737,9 @@ mips_store_return_value (valtype, valbuf)
   
   regnum = 2;
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT
-      && (mips_fpu == MIPS_FPU_DOUBLE
-         || (mips_fpu == MIPS_FPU_SINGLE && len <= MIPS_REGSIZE)))
+      && (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE
+         || (MIPS_FPU_TYPE == MIPS_FPU_SINGLE
+             && len <= MIPS_REGSIZE)))
     regnum = FP0_REGNUM;
 
   if (TARGET_BYTE_ORDER == BIG_ENDIAN)
@@ -2648,67 +2771,102 @@ in_sigtramp (pc, ignore)
   return (pc >= sigtramp_address && pc < sigtramp_end);
 }
 
-/* Command to set FPU type.  mips_fpu_string will have been set to the
-   user's argument.  Set mips_fpu based on mips_fpu_string, and then
-   canonicalize mips_fpu_string.  */
+/* Commands to show/set the MIPS FPU type.  */
 
-/*ARGSUSED*/
+static void show_mipsfpu_command PARAMS ((char *, int));
 static void
-mips_set_fpu_command (args, from_tty, c)
+show_mipsfpu_command (args, from_tty)
      char *args;
      int from_tty;
-     struct cmd_list_element *c;
 {
-  char *err = NULL;
-
-  if (mips_fpu_string == NULL || *mips_fpu_string == '\0')
-    mips_fpu = MIPS_FPU_DOUBLE;
-  else if (strcasecmp (mips_fpu_string, "double") == 0
-          || strcasecmp (mips_fpu_string, "on") == 0
-          || strcasecmp (mips_fpu_string, "1") == 0
-          || strcasecmp (mips_fpu_string, "yes") == 0)
-    mips_fpu = MIPS_FPU_DOUBLE;
-  else if (strcasecmp (mips_fpu_string, "none") == 0
-          || strcasecmp (mips_fpu_string, "off") == 0
-          || strcasecmp (mips_fpu_string, "0") == 0
-          || strcasecmp (mips_fpu_string, "no") == 0)
-    mips_fpu = MIPS_FPU_NONE;
-  else if (strcasecmp (mips_fpu_string, "single") == 0)
-    mips_fpu = MIPS_FPU_SINGLE;
-  else
-    err = strsave (mips_fpu_string);
-
-  if (mips_fpu_string != NULL)
-    free (mips_fpu_string);
-
-  switch (mips_fpu)
+  char *msg;
+  char *fpu;
+  switch (MIPS_FPU_TYPE)
     {
-    case MIPS_FPU_DOUBLE:
-      mips_fpu_string = strsave ("double");
-      break;
     case MIPS_FPU_SINGLE:
-      mips_fpu_string = strsave ("single");
+      fpu = "single-precision";
+      break;
+    case MIPS_FPU_DOUBLE:
+      fpu = "double-precision";
       break;
     case MIPS_FPU_NONE:
-      mips_fpu_string = strsave ("none");
+      fpu = "absent (none)";
       break;
     }
+  if (mips_fpu_type_auto)
+    printf_unfiltered ("The MIPS floating-point coprocessor is set automatically (currently %s)\n",
+                      fpu);
+  else
+    printf_unfiltered ("The MIPS floating-point coprocessor is assumed to be %s\n",
+                      fpu);
+}
 
-  if (err != NULL)
+
+static void set_mipsfpu_command PARAMS ((char *, int));
+static void
+set_mipsfpu_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  printf_unfiltered ("\"set mipsfpu\" must be followed by \"double\", \"single\",\"none\" or \"auto\".\n");
+  show_mipsfpu_command (args, from_tty);
+}
+
+static void set_mipsfpu_single_command PARAMS ((char *, int));
+static void
+set_mipsfpu_single_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  mips_fpu_type = MIPS_FPU_SINGLE;
+  mips_fpu_type_auto = 0;
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+  if (GDB_MULTI_ARCH)
     {
-      struct cleanup *cleanups = make_cleanup (free, err);
-      error ("Unknown FPU type `%s'.  Use `double', `none', or `single'.",
-            err);
-      do_cleanups (cleanups);
+      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_SINGLE;
     }
+  /* end-sanitize-carp end-sanitize-vr4xxx */
 }
 
+static void set_mipsfpu_double_command PARAMS ((char *, int));
 static void
-mips_show_fpu_command (args, from_tty, c)
+set_mipsfpu_double_command (args, from_tty)
      char *args;
      int from_tty;
-     struct cmd_list_element *c;
 {
+  mips_fpu_type = MIPS_FPU_DOUBLE;
+  mips_fpu_type_auto = 0;
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+  if (GDB_MULTI_ARCH)
+    {
+      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_DOUBLE;
+    }
+  /* end-sanitize-carp end-sanitize-vr4xxx */
+}
+
+static void set_mipsfpu_none_command PARAMS ((char *, int));
+static void
+set_mipsfpu_none_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  mips_fpu_type = MIPS_FPU_NONE;
+  mips_fpu_type_auto = 0;
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+  if (GDB_MULTI_ARCH)
+    {
+      gdbarch_tdep (current_gdbarch)->mips_fpu_type = MIPS_FPU_NONE;
+    }
+  /* end-sanitize-carp end-sanitize-vr4xxx */
+}
+
+static void set_mipsfpu_auto_command PARAMS ((char *, int));
+static void
+set_mipsfpu_auto_command (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  mips_fpu_type_auto = 1;
 }
 
 /* Command to set the processor type.  */
@@ -2765,7 +2923,8 @@ mips_set_processor_type (str)
          mips_processor_type = str;
 
          for (j = 0; j < NUM_REGS; ++j)
-           reg_names[j] = mips_processor_type_table[i].regnames[j];
+           /* FIXME - MIPS should be defining REGISTER_NAME() instead */
+           gdb_register_names[j] = mips_processor_type_table[i].regnames[j];
 
          return 1;
 
@@ -2838,6 +2997,19 @@ gdb_print_insn_mips (memaddr, info)
     return print_insn_little_mips (memaddr, info);
 }
 
+/* Old-style breakpoint macros.
+   The IDT board uses an unusual breakpoint value, and sometimes gets
+   confused when it sees the usual MIPS breakpoint instruction.  */
+
+#define BIG_BREAKPOINT {0, 0x5, 0, 0xd}
+#define LITTLE_BREAKPOINT {0xd, 0, 0x5, 0}
+#define PMON_BIG_BREAKPOINT {0, 0, 0, 0xd}
+#define PMON_LITTLE_BREAKPOINT {0xd, 0, 0, 0}
+#define IDT_BIG_BREAKPOINT {0, 0, 0x0a, 0xd}
+#define IDT_LITTLE_BREAKPOINT {0xd, 0x0a, 0, 0}
+#define MIPS16_BIG_BREAKPOINT {0xe8, 0xa5}
+#define MIPS16_LITTLE_BREAKPOINT {0xa5, 0xe8}
+
 /* This function implements the BREAKPOINT_FROM_PC macro.  It uses the program
    counter value to determine whether a 16- or 32-bit breakpoint should be
    used.  It returns a pointer to a string of bytes that encode a breakpoint
@@ -2905,26 +3077,6 @@ unsigned char *mips_breakpoint_from_pc (pcptr, lenptr)
     }
 }
 
-/* Test whether the PC points to the return instruction at the
-   end of a function.  This implements the ABOUT_TO_RETURN macro.  */
-
-int 
-mips_about_to_return (pc)
-     CORE_ADDR pc;
-{
-  if (pc_is_mips16 (pc))
-    /* This mips16 case isn't necessarily reliable.  Sometimes the compiler
-       generates a "jr $ra"; other times it generates code to load
-       the return address from the stack to an accessible register (such
-       as $a3), then a "jr" using that register.  This second case
-       is almost impossible to distinguish from an indirect jump
-       used for switch statements, so we don't even try.  */
-    return mips_fetch_instruction (pc) == 0xe820;      /* jr $ra */
-  else
-    return mips_fetch_instruction (pc) == 0x3e00008;   /* jr $ra */
-}
-
-
 /* If PC is in a mips16 call or return stub, return the address of the target
    PC, which is either the callee or the caller.  There are several
    cases which must be handled:
@@ -3105,42 +3257,202 @@ mips_ignore_helper (pc)
 }
 
 
+/* Return a location where we can set a breakpoint that will be hit
+   when an inferior function call returns.  This is normally the
+   program's entry point.  Executables that don't have an entry
+   point (e.g. programs in ROM) should define a symbol __CALL_DUMMY_ADDRESS
+   whose address is the location where the breakpoint should be placed.  */
+
+CORE_ADDR
+mips_call_dummy_address ()
+{
+  struct minimal_symbol *sym;
+
+  sym = lookup_minimal_symbol ("__CALL_DUMMY_ADDRESS", NULL, NULL);
+  if (sym)
+    return SYMBOL_VALUE_ADDRESS (sym);
+  else
+    return entry_point_address ();
+}
+
+/* start-sanitize-carp start-sanitize-vr4xxx */
+
+static gdbarch_init_ftype mips_gdbarch_init;
+static struct gdbarch *
+mips_gdbarch_init (info, arches)
+     struct gdbarch_info info;
+     struct gdbarch_list *arches;
+{
+  struct gdbarch *gdbarch;
+  struct gdbarch_tdep *tdep;
+  int elf_abi;
+  char *abi_name;
+
+  /* find a default for ELF_ABI */
+  if (info.abfd != NULL)
+    elf_abi = elf_elfheader (info.abfd)->e_flags & EF_MIPS_ABI;
+  else if (gdbarch_bfd_arch_info (current_gdbarch)->arch == bfd_arch_mips)
+    elf_abi = gdbarch_tdep (current_gdbarch)->elf_abi;
+  else
+    elf_abi = 0;
+
+  /* try to find a pre-existing architecture */
+  for (arches = gdbarch_list_lookup_by_info (arches, &info);
+       arches != NULL;
+       arches = gdbarch_list_lookup_by_info (arches->next, &info))
+    {
+      /* MIPS needs to be pedantic about which ABI the object is
+         using. */
+      if (gdbarch_tdep (current_gdbarch)->elf_abi != elf_abi)
+       continue;
+      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_abi = elf_abi;
+  switch (elf_abi)
+    {
+    case E_MIPS_ABI_O32:
+      abi_name = "o32";
+      tdep->mips_eabi = 0;
+      set_gdbarch_long_bit (gdbarch, 32);
+      set_gdbarch_ptr_bit (gdbarch, 32);
+      break;
+    case E_MIPS_ABI_O64:
+      abi_name = "o64";
+      tdep->mips_eabi = 0;
+      set_gdbarch_long_bit (gdbarch, 32);
+      set_gdbarch_ptr_bit (gdbarch, 32);
+      break;
+    case E_MIPS_ABI_EABI32:
+      abi_name = "eabi32";
+      tdep->mips_eabi = 1;
+      set_gdbarch_long_bit (gdbarch, 32);
+      set_gdbarch_ptr_bit (gdbarch, 32);
+      break;
+    case E_MIPS_ABI_EABI64:
+      abi_name = "eabi64";
+      tdep->mips_eabi = 1;
+      set_gdbarch_long_bit (gdbarch, 64);
+      set_gdbarch_ptr_bit (gdbarch, 64);
+      break;
+    default:
+      abi_name = "default";
+      tdep->mips_eabi = 0;
+      set_gdbarch_long_bit (gdbarch, 32);
+      set_gdbarch_ptr_bit (gdbarch, 32);
+      break;
+    }
+  if (tdep->mips_eabi)
+    {
+      /* EABI uses R4 through R11 for args */
+      tdep->mips_last_arg_regnum = 11;
+      /* EABI uses F12 through F19 for args */
+      tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 19;
+    }
+  else
+    {
+      /* old ABI uses R4 through R7 for args */
+      tdep->mips_last_arg_regnum = 7;
+      /* old ABI uses F12 through F15 for args */
+      tdep->mips_last_fp_arg_regnum = FP0_REGNUM + 15;
+    }
+  set_gdbarch_long_long_bit (gdbarch, 64);
+
+  /* enable/disable the MIPS FPU */
+  if (!mips_fpu_type_auto)
+    tdep->mips_fpu_type = mips_fpu_type;
+  else if (info.bfd_arch_info != NULL
+          && info.bfd_arch_info->arch == bfd_arch_mips)
+    switch (info.bfd_arch_info->mach)
+      {
+      case bfd_mach_mips4100:
+      case bfd_mach_mips4111:
+      case bfd_mach_mips4121:
+       tdep->mips_fpu_type = MIPS_FPU_NONE;
+       break;
+      default:
+       tdep->mips_fpu_type = MIPS_FPU_DOUBLE;
+       break;
+      }
+  else
+    tdep->mips_fpu_type = MIPS_FPU_DOUBLE;
+
+  if (gdbarch_debug)
+    {
+      fprintf_unfiltered (stderr,
+                         "mips_gdbarch_init: (info)elf_abi 0x%x (%s)\n",
+                         elf_abi, abi_name);
+      fprintf_unfiltered (stderr,
+                         "mips_gdbarch_init: MIPS_EABI = %d\n",
+                         tdep->mips_eabi);
+      fprintf_unfiltered (stderr,
+                         "mips_gdbarch_init: MIPS_LAST_ARG_REGNUM = %d\n",
+                         tdep->mips_last_arg_regnum);
+      fprintf_unfiltered (stderr,
+                         "mips_gdbarch_init: MIPS_LAST_FP_ARG_REGNUM = %d (%d)\n",
+                         tdep->mips_last_fp_arg_regnum,
+                         tdep->mips_last_fp_arg_regnum - FP0_REGNUM);
+      fprintf_unfiltered (stderr,
+                         "mips_gdbarch_init: tdep->mips_fpu_type = %d (%s)\n",
+                         tdep->mips_fpu_type,
+                         (tdep->mips_fpu_type == MIPS_FPU_NONE ? "none"
+                          : tdep->mips_fpu_type == MIPS_FPU_SINGLE ? "single"
+                          : tdep->mips_fpu_type == MIPS_FPU_DOUBLE ? "double"
+                          : "???"));
+    }
+
+  return gdbarch;
+}
+
+/* end-sanitize-carp end-sanitize-vr4xxx */
+
 void
 _initialize_mips_tdep ()
 {
+  static struct cmd_list_element *mipsfpulist = NULL;
   struct cmd_list_element *c;
 
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+  if (GDB_MULTI_ARCH)
+    register_gdbarch_init (bfd_arch_mips, mips_gdbarch_init);
+  /* end-sanitize-carp end-sanitize-vr4xxx */
   if (!tm_print_insn) /* Someone may have already set it */
     tm_print_insn = gdb_print_insn_mips;
 
   /* Let the user turn off floating point and set the fence post for
      heuristic_proc_start.  */
 
-  c = add_set_cmd ("mipsfpu", class_support, var_string_noescape,
-                  (char *) &mips_fpu_string,
-                  "Set use of floating point coprocessor.\n\
-Set to `none' to avoid using floating point instructions when calling\n\
-functions or dealing with return values.  Set to `single' to use only\n\
-single precision floating point as on the R4650.  Set to `double' for\n\
-normal floating point support.",
-                  &setlist);
-  c->function.sfunc = mips_set_fpu_command;
-  c = add_show_from_set (c, &showlist);
-  c->function.sfunc = mips_show_fpu_command;
-
-#ifndef MIPS_DEFAULT_FPU_TYPE
-  mips_fpu = MIPS_FPU_DOUBLE;
-  mips_fpu_string = strsave ("double");
-#else
-  mips_fpu = MIPS_DEFAULT_FPU_TYPE;
-  switch (mips_fpu) 
-  {
-    case MIPS_FPU_DOUBLE:  mips_fpu_string = strsave ("double");  break;
-    case MIPS_FPU_SINGLE:  mips_fpu_string = strsave ("single");  break;
-    case MIPS_FPU_NONE:    mips_fpu_string = strsave ("none");    break;
-  }    
-#endif
-
+  add_prefix_cmd ("mipsfpu", class_support, set_mipsfpu_command,
+                 "Set use of MIPS floating-point coprocessor.",
+                 &mipsfpulist, "set mipsfpu ", 0, &setlist);
+  add_cmd ("single", class_support, set_mipsfpu_single_command,
+          "Select single-precision MIPS floating-point coprocessor.",
+          &mipsfpulist);
+  add_cmd ("double", class_support, set_mipsfpu_double_command,
+          "Select double-precision MIPS floating-point coprocessor .",
+          &mipsfpulist);
+  add_alias_cmd ("on", "double", class_support, 1, &mipsfpulist);
+  add_alias_cmd ("yes", "double", class_support, 1, &mipsfpulist);
+  add_alias_cmd ("1", "double", class_support, 1, &mipsfpulist);
+  add_cmd ("none", class_support, set_mipsfpu_none_command,
+          "Select no MIPS floating-point coprocessor.",
+          &mipsfpulist);
+  add_alias_cmd ("off", "none", class_support, 1, &mipsfpulist);
+  add_alias_cmd ("no", "none", class_support, 1, &mipsfpulist);
+  add_alias_cmd ("0", "none", class_support, 1, &mipsfpulist);
+  add_cmd ("auto", class_support, set_mipsfpu_auto_command,
+          "Select MIPS floating-point coprocessor automatically.",
+          &mipsfpulist);
+  add_cmd ("mipsfpu", class_support, show_mipsfpu_command,
+          "Show current use of MIPS floating-point coprocessor target.",
+          &showlist);
+
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+#if !GDB_MULTI_ARCH
+  /* end-sanitize-carp end-sanitize-vr4xxx */
   c = add_set_cmd ("processor", class_support, var_string_noescape,
                   (char *) &tmp_mips_processor_type,
                   "Set the type of MIPS processor in use.\n\
@@ -3153,6 +3465,9 @@ Set this to be able to access processor-type-specific registers.\n\
 
   tmp_mips_processor_type = strsave (DEFAULT_MIPS_TYPE);
   mips_set_processor_type_command (strsave (DEFAULT_MIPS_TYPE), 0);
+  /* start-sanitize-carp start-sanitize-vr4xxx */
+#endif
+  /* end-sanitize-carp end-sanitize-vr4xxx */
 
   /* 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
@@ -3169,4 +3484,13 @@ search.  The only need to set it is when debugging a stripped executable.",
      might change our ability to get backtraces.  */
   c->function.sfunc = 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
+    (add_set_cmd ("mask-address", no_class, var_boolean, (char *)&mask_address_p,
+          "Set zeroing of upper 32 bits of 64-bit addresses.\n\
+Use \"on\" to enable the masking, and \"off\" to disable it.\n\
+Without an argument, zeroing of upper address bits is enabled.", &setlist),
+     &showlist);
 }
This page took 0.037465 seconds and 4 git commands to generate.