This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[WIP/RFC] MIPS registers overhaul


The patch below represents the results of trying to fix two problems
related to floating point registers, stumbling at various points along
the way, and realizing that I needed to fix even more...

The two problems related to floating point registers that I started out
trying to fix are the following:

 1) On mips64, it's not possible to set a floating point register to
    a single precision value.
 2) Again, on mips64, when running a program using the o32 ABI, floating
    point doubles were not being fetched from GDB's regcache correctly.
    For o32, floating point doubles are represented using register pairs,
    but, for mips64, each register is stored in a 64-bit container.  When
    attempting to retrieve the value of a 64-bit double that should
    be retrieved by taking 32-bits from a pair, the single 64-bit container
    was being considered to be the value of the double.

Problem 1 was solved by introducing a union type for floating point
registers.  When attempting to display a value using ``print'', you'll
see (with my patch) something like this:

    (gdb) p $f20
    $1 = {i = 4621199872640208077, f = -107374184, d = 8.9000000000000004}

(If someone can think of more meaningful, but still terse field names for
the above, please let me know.)

If you want to set the register, you can do it as follows:

    (gdb) set $f20.d=2.3
    (gdb) p $f20
    $2 = {i = 4612361558371493478, f = 2.72008302e+23, d = 2.2999999999999998}
    (gdb) set $f20.f=2.2
    (gdb) p $f20
    $3 = {i = 4612361557728087245, f = 2.20000005, d = 2.2999997142702342}
    (gdb) set $f20.i=42
    (gdb) p $f20
    $4 = {i = 42, f = 5.88545355e-44, d = 2.0750757125332355e-322}

Also, you can still do:

    (gdb) set $f20=3.3
    (gdb) p $f20
    $5 = {i = 4614613358185178726, f = 2.72008302e+23, d = 3.2999999999999998}

Problem 2 was solved by introducing pseudo-registers for the floating point
registers.  Along the way (last Friday, I think), I ran into an assertion
failure which caused me to make even more extensive changes to the MIPS code.

BTW, the raw floating point registers are still accessible.  Doing
"info registers raw" will display all of the raw registers.  Or, if
you know the names of the registers you want to display, you can do,
e.g, "info registers raw_f20".

Which reminds me...  I've introduced two sets of register numbers.  I
called these the "cooked" and "raw" regnums.  In many cases, the
cooked and raw numbers are the same.  (They'll usually be the same
when the raw and cooked types are the same.) In the cases where the
numbers are different, the cooked number is a pseudo register number
and the corresponding raw register is (usually) used to determine the
value of cooked value.  Raw registers numbers should be used by the
lower layers of GDB which communicate with the target and need to
populate GDB's regcache.  The cooked registers *should* be used almost
everywhere else.  Except they aren't at the moment.  In particular,
most of mips-tdep.c wants to still operate on "raw" register data. 
(Anywhere you see a byte order check, that's a clue that raw register
numbers should still be used.) So, in order to prevent this patch from
becoming even larger than it already is, much of mips-tdep.c still
uses raw register numbers.  These should (probably) be cleaned up some
day to use cooked numbers instead.  (I need to check to make sure I
have this as a comment in the code somewhere...)

For the o32 case that I was originally trying to fix, we end up
creating 16 64-bit cooked floating point registers of the union type
mentioned above.  The raw floating point registers (in pairs) are used
to construct the cooked value.  It's also possible to end up with no
cooked floating point registers or 32-floating floating point
registers, either 32- or 64-bit.  (The values of FP_REGISTER_DOUBLE
and MIPS_FPU_TYPE influence what exactly gets done.)

Anyway, here it is.  Any suggestions on how to break this patch up so
that it can be sensibly reviewed will be very much appreciated.  (It
seems that much of what I've done is interdependent...)

	* mdebugread.c, mips-linux-nat.c, mips-linux-tdep.c, mips-nat.c,
	mips-tdep.c, mipsnbsd-nat.c, remote-mips.c, config/mips/nm-riscos.h
	(ZERO_REGNUM, V0_REGNUM, A0_REGNUM, T9_REGNUM, SP_REGNUM, RA_REGNUM)
	(PS_REGNUM, HI_REGNUM, LO_REGNUM, BADVADDR_REGNUM, CAUSE_REGNUM)
	(PC_REGNUM, FP0_REGNUM, FPA0_REGNUM, FCRCS_REGNUM, FIRST_EMBED_REGNUM)
	(PRID_REGNUM, LAST_EMBED_REGNUM, MIPS_LAST_ARG_REGNUM)
	(MIPS_LAST_FP_ARG_REGNUM: Replace references to these macros
	with references to members in the mips_regnums struct.
	* Makefile.in (mdebugread.o, mips-linux-nat.o, mips-nat.o): Add
	dependency on $(mips_tdep_h).
	(mips-tdep.o): Add dependency on $(reggroups_h).
	* mdebugread.c (mips-tdep.h): Include.
	(RA_REGNUM): Revise definition.
	* mips-linux-nat.c (mips-tdep.h): Include.
	* mips-nat.c (mips-tdep.h): Include.
	(REGISTER_PTRACE_ADDR): Rewrite macro into function.
	* mips-tdep.c (reggroups.h): Include.
	(struct gdbarch_tdep): Move ``mips_last_arg_regnum'' and
	``mips_last_fp_arg_regnum'' members (renamed slightly) to
	the mips_regnums struct.  Add new members ``raw_regnums''
	and ``cooked_regnums''.
	(MIPS_LAST_FP_ARG_REGNUM, MIPS_LAST_ARG_REGNUM): Delete
	macros.
	(FP_REGISTER_DOUBLE): Move location of macro definition earlier
	in the file.
	(mips_raw_regnums, mips_cooked_regnums): New accessor functions.
	(mips2_fp_compat): Use FP_REGISTER_DOUBLE to help determine
	return value.
	(mips_type_float_double_register_big)
	(mips_type_float_double_register_little)
	(mips_type_float_single_register_big)
	(mips_type_float_single_register_little): New static variables
	representing types for MIPS (cooked) floating point registers.
	(mips_generic_embed_reg_names): New static variable.
	(mips_processor_reg_names): Rename to mips_embed_reg_names.
	(reg_name): New function.
	(mips_register_name): Rewritten to use reg_name().
	(mips_tx39_embed_reg_names): New static array listing names
	of tx39 embedded registers.
	(mips_r3041_reg_names): Rename to mips_r3041_embed_reg_names.
	Prune names to just those of the embedded registers.
	(mips_r3051_reg_names): Rename to mips_r3051_embed_reg_names.
	Prune names to just those of the embedded registers.
	(mips_r3081_reg_names): Rename to mips_r3081_embed_reg_names.
	Prune names to just those of the embedded registers.
	(mips_lsi33k_reg_names): Disable this broken code.
	(mips_processor_type_table): Change all ``regnames'' references
	to those listed above.  Add entry for "tx39".
	(mips_register_raw_size, mips_register_convertible)
	(mips_register_convert_to_virtual, mips_register_convert_to_raw)
	(mips_register_convert_to_type, mips_register_convert_from_type):
	Delete.
	(mips_register_virtual_type): Rewrite so that registers in
	range [0, NUM_REGS) have a type whose size is the same as
	that expected by the remote protocol.  Pseudo-registers
	above this range are give more user-friendly types.
	(mips_find_saved_regs): For the floating point registers, put
	references to both the cooked and raw regnums in the ``saved_regs''
	array.
	(mips_raw_reggroup): New static global.
	(mips_init_reggroups, mips_add_reggroups, mips_register_reggroup_p)
	(mips_is_floating_point_register, mips_is_raw_register)
	(mips_is_general_purpose_register)
	(build_mips_type_float_double_register_big)
	(build_mips_type_float_double_register_little)
	(build_mips_type_float_single_register_big)
	(build_mips_type_float_single_register_little)
	(cooked_regnum_to_raw_regnum, mips_pseudo_register_read)
	(mips_psuedo_register_write): New functions.
	(mips_read_fp_register_double): Simplify.
	(mips_print_fp_register): Revise, taking into account the
	fact that floating point registers are now pseudo registers.
	(mips_print_register): Eliminate references to
	REGISTER_VIRTUAL_TYPE().
	(do_fp_register_row): Return early for no-name registers.
	(do_gp_register_row): Eliminate references to REGISTER_VIRTUAL_TYPE().
	Change logic to not break out of row printing loop when a non-general
	purpose register is seen.
	(mips_do_registers_info): Account for the fact that we now have
	pseudo registers.  Print the general purpose registers and the
	floating point registers in seperate passes.
	(mips_set_processor_type): Refer to ``mips_embed_reg_names''
	instead of ``mips_processor_reg_names''.
	(mips_stab_reg_to_regnum, mips_dwarf_dwarf2_ecoff_reg_to_regnum):
	Add case for dealing with 16 cooked floating point registers.
	(mips_gdbarch_init): Don't call set_gdbarch_register_raw_size(),
	set_gdbarch_register_convertible(),
	set_gdbarch_register_convert_to_virtual(), or
	set_gdbarch_register_convert_to_raw() any longer.  Initialize
	tdep->raw_regnums and tdep->cooked_regnums.  Initialize register
	groups.  Invoke set_gdbarch_sp_regnum() and set_gdbarch_pc_regnum().
	(mips_dump_regnums): New function.
	(mips_dump_tdep): Call mips_dump_regnums() to dump new members
	of struct gdbarch_tdep.  Don't dump things which've been deleted.
	(_initialize_mips_tdep): Invoke mips_init_reggroups ().
	Initialize mips_type_float_double_register_big,
	mips_type_float_double_register_little,
	mips_type_float_single_register_big, and
	mips_type_float_single_register_little.
	* mips-tdep.h (mips_regnums): New struct.
	(mips_raw_regnums, mips_cooked_regnums): New functions.
	* mipsnbsd-nat.c (mips-tdep.h): Include.
	* remote-mips.c (mips-tdep.h): Include.
	* config/mips/tm-irix3.h (MIPS_REGISTER_NAMES, FP0_REGNUM)
	(PC_REGNUM, CAUSE_REGNUM, BADVADDR_REGNUM, HI_REGNUM, LO_REGNUM)
	(FCRCS_REGNUM, FCRIR_REGNUM): Delete.
	* config/mips/tm-irix5.h (REGISTER_BYTES, REGISTER_BYTE)
	(REGISTER_VIRTUAL_TYPE): Delete.
	* config/mips/tm-irix6.h (MIPS_REGISTER_NAMES, FP0_REGNUM)
	(PC_REGNUM, CAUSE_REGNUM, BADVADDR_REGNUM, HI_REGNUM, LO_REGNUM)
	(FCRCS_REGNUM, FCRIR_REGNUM, REGISTER_BYTE): Delete.
	(REGISTER_VIRTUAL_TYPE): Delete #undef.
	* config/mips/tmp-mips.h (MIPS_REGISTER_NAMES, ZERO_REGNUM)
	(V0_REGNUM, A0_REGNUM, T9_REGNUM, SP_REGNUM, RA_REGNUM, PS_REGNUM)
	(HI_REGNUM, LO_REGNUM, BADVADDR_REGNUM, CAUSE_REGNUM, PC_REGNUM)
	(FP0_REGNUM, FPA0_REGNUM, FCRCS_REGNUM, FCRIR_REGNUM)
	(UNUSED_REGNUM, FIRST_EMBED_REGNUM, PRID_REGNUM, LAST_EMBED_REGNUM)
	(REGISTER_BYTE, REGISTER_VIRTUAL_TYPE)
	(mips_register_convert_to_type, mips_register_convert_from_type)
	(MIPS_REGISTER_CONVERT_TO_TYPE, MIPS_REGISTER_CONVERT_FROM_TYPE):
	Delete.
	* config/mips/tm-mips64.h (REGISTER_VIRTUAL_TYPE): Delete.
	* config/mips/tm-tx39.h, config/mips/tm-tx39l.h
	(MIPS_REGISTER_NAMES): Delete.

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.374
diff -u -p -r1.374 Makefile.in
--- Makefile.in	5 May 2003 18:33:10 -0000	1.374
+++ Makefile.in	9 May 2003 23:36:30 -0000
@@ -1953,7 +1953,7 @@ mdebugread.o: mdebugread.c $(defs_h) $(s
 	$(block_h) \
 	$(coff_sym_h) $(coff_symconst_h) $(gdb_stat_h) $(gdb_string_h) \
 	$(bfd_h) $(coff_ecoff_h) $(libaout_h) $(aout_aout64_h) \
-	$(aout_stab_gnu_h) $(expression_h) $(language_h)
+	$(aout_stab_gnu_h) $(expression_h) $(language_h) $(mips_tdep_h)
 mem-break.o: mem-break.c $(defs_h) $(symtab_h) $(breakpoint_h) $(inferior_h) \
 	$(target_h)
 memattr.o: memattr.c $(defs_h) $(command_h) $(gdbcmd_h) $(memattr_h) \
@@ -1961,17 +1961,18 @@ memattr.o: memattr.c $(defs_h) $(command
 minsyms.o: minsyms.c $(defs_h) $(gdb_string_h) $(symtab_h) $(bfd_h) \
 	$(symfile_h) $(objfiles_h) $(demangle_h) $(value_h) $(cp_abi_h)
 mips-irix-tdep.o: mips-irix-tdep.c $(defs_h) $(osabi_h) $(elf_bfd_h)
-mips-linux-nat.o: mips-linux-nat.c $(defs_h)
+mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
 	$(solib_svr4_h) $(osabi_h) $(gdb_string_h) $(mips_tdep_h) \
 	$(gdb_assert_h)
-mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h)
+mips-nat.o: mips-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) $(regcache_h) \
+	$(mips_tdep_h)
 mips-tdep.o: mips-tdep.c $(defs_h) $(gdb_string_h) $(gdb_assert_h) \
 	$(frame_h) $(inferior_h) $(symtab_h) $(value_h) $(gdbcmd_h) \
 	$(language_h) $(gdbcore_h) $(symfile_h) $(objfiles_h) \
 	$(gdbtypes_h) $(target_h) $(arch_utils_h) $(regcache_h) \
 	$(osabi_h) $(mips_tdep_h) $(block_h) $(opcode_mips_h) \
-	$(elf_mips_h) $(elf_bfd_h) $(symcat_h)
+	$(elf_mips_h) $(elf_bfd_h) $(symcat_h) $(reggroups_h)
 mipsm3-nat.o: mipsm3-nat.c $(defs_h) $(inferior_h) $(regcache_h)
 mipsnbsd-nat.o: mipsnbsd-nat.c $(defs_h) $(inferior_h) $(regcache_h) \
 	$(mipsnbsd_tdep_h)
Index: mdebugread.c
===================================================================
RCS file: /cvs/src/src/gdb/mdebugread.c,v
retrieving revision 1.44
diff -u -p -r1.44 mdebugread.c
--- mdebugread.c	19 Mar 2003 19:45:49 -0000	1.44
+++ mdebugread.c	9 May 2003 23:36:32 -0000
@@ -55,6 +55,9 @@
 #include "gdb_assert.h"
 #include "block.h"
 
+#include "mips-tdep.h"
+#define RA_REGNUM (mips_cooked_regnums (current_gdbarch)->ra_regnum)
+
 /* These are needed if the tm.h file does not contain the necessary
    mips specific definitions.  */
 
@@ -69,9 +72,6 @@ typedef struct mips_extra_func_info
     PDR pdr;
   }
  *mips_extra_func_info_t;
-#ifndef RA_REGNUM
-#define RA_REGNUM 0
-#endif
 #endif
 
 #ifdef USG
Index: mips-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-nat.c,v
retrieving revision 1.4
diff -u -p -r1.4 mips-linux-nat.c
--- mips-linux-nat.c	30 Oct 2002 04:10:06 -0000	1.4
+++ mips-linux-nat.c	9 May 2003 23:36:32 -0000
@@ -20,6 +20,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
+#include "mips-tdep.h"
 
 /* Pseudo registers can not be read.  ptrace does not provide a way to
    read (or set) PS_REGNUM, and there's no point in reading or setting
@@ -29,11 +30,13 @@
 int
 mips_linux_cannot_fetch_register (int regno)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (REGISTER_NAME (regno)[0] == 0)
     return 1;
-  if (regno == PS_REGNUM)
+  if (regno == regnums->ps_regnum)
     return 1;
-  else if (regno == ZERO_REGNUM)
+  else if (regno == regnums->zero_regnum)
     return 1;
   else
     return 0;
@@ -42,17 +45,19 @@ mips_linux_cannot_fetch_register (int re
 int
 mips_linux_cannot_store_register (int regno)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (REGISTER_NAME (regno)[0] == 0)
     return 1;
-  if (regno == PS_REGNUM)
+  if (regno == regnums->ps_regnum)
     return 1;
-  else if (regno == ZERO_REGNUM)
+  else if (regno == regnums->zero_regnum)
     return 1;
-  else if (regno == BADVADDR_REGNUM)
+  else if (regno == regnums->badvaddr_regnum)
     return 1;
-  else if (regno == CAUSE_REGNUM)
+  else if (regno == regnums->cause_regnum)
     return 1;
-  else if (regno == FCRIR_REGNUM)
+  else if (regno == regnums->fcrir_regnum)
     return 1;
   else
     return 0;
Index: mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.9
diff -u -p -r1.9 mips-linux-tdep.c
--- mips-linux-tdep.c	24 Dec 2002 19:21:10 -0000	1.9
+++ mips-linux-tdep.c	9 May 2003 23:36:32 -0000
@@ -72,8 +72,9 @@ mips_linux_get_longjmp_target (CORE_ADDR
 {
   CORE_ADDR jb_addr;
   char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
 
-  jb_addr = read_register (A0_REGNUM);
+  jb_addr = read_register (regnums->a0_regnum);
 
   if (target_read_memory (jb_addr
 			  + MIPS_LINUX_JB_PC * MIPS_LINUX_JB_ELEMENT_SIZE,
@@ -105,23 +106,25 @@ supply_gregset (elf_gregset_t *gregsetp)
   int regi;
   elf_greg_t *regp = *gregsetp;
   char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
 
   for (regi = EF_REG0; regi <= EF_REG31; regi++)
     supply_32bit_reg ((regi - EF_REG0), (char *)(regp + regi));
 
-  supply_32bit_reg (LO_REGNUM, (char *)(regp + EF_LO));
-  supply_32bit_reg (HI_REGNUM, (char *)(regp + EF_HI));
+  supply_32bit_reg (regnums->lo_regnum, (char *)(regp + EF_LO));
+  supply_32bit_reg (regnums->hi_regnum, (char *)(regp + EF_HI));
 
-  supply_32bit_reg (PC_REGNUM, (char *)(regp + EF_CP0_EPC));
-  supply_32bit_reg (BADVADDR_REGNUM, (char *)(regp + EF_CP0_BADVADDR));
-  supply_32bit_reg (PS_REGNUM, (char *)(regp + EF_CP0_STATUS));
-  supply_32bit_reg (CAUSE_REGNUM, (char *)(regp + EF_CP0_CAUSE));
+  supply_32bit_reg (regnums->pc_regnum, (char *)(regp + EF_CP0_EPC));
+  supply_32bit_reg (regnums->badvaddr_regnum, (char *)(regp + EF_CP0_BADVADDR));
+  supply_32bit_reg (regnums->ps_regnum, (char *)(regp + EF_CP0_STATUS));
+  supply_32bit_reg (regnums->cause_regnum, (char *)(regp + EF_CP0_CAUSE));
 
   /* Fill inaccessible registers with zero.  */
-  supply_register (UNUSED_REGNUM, zerobuf);
-  for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
+  for (regi = regnums->first_embed_regnum;
+       regi < regnums->last_embed_regnum;
+       regi++)
     supply_register (regi, zerobuf);
 }
 
@@ -133,18 +136,19 @@ fill_gregset (elf_gregset_t *gregsetp, i
   int regaddr, regi;
   elf_greg_t *regp = *gregsetp;
   void *dst;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno == -1)
     {
       memset (regp, 0, sizeof (elf_gregset_t));
       for (regi = 0; regi < 32; regi++)
         fill_gregset (gregsetp, regi);
-      fill_gregset (gregsetp, LO_REGNUM);
-      fill_gregset (gregsetp, HI_REGNUM);
-      fill_gregset (gregsetp, PC_REGNUM);
-      fill_gregset (gregsetp, BADVADDR_REGNUM);
-      fill_gregset (gregsetp, PS_REGNUM);
-      fill_gregset (gregsetp, CAUSE_REGNUM);
+      fill_gregset (gregsetp, regnums->lo_regnum);
+      fill_gregset (gregsetp, regnums->hi_regnum);
+      fill_gregset (gregsetp, regnums->pc_regnum);
+      fill_gregset (gregsetp, regnums->badvaddr_regnum);
+      fill_gregset (gregsetp, regnums->ps_regnum);
+      fill_gregset (gregsetp, regnums->cause_regnum);
 
       return;
    }
@@ -157,27 +161,18 @@ fill_gregset (elf_gregset_t *gregsetp, i
     }
 
   regaddr = -1;
-  switch (regno)
-    {
-      case LO_REGNUM:
-	regaddr = EF_LO;
-	break;
-      case HI_REGNUM:
-	regaddr = EF_HI;
-	break;
-      case PC_REGNUM:
-	regaddr = EF_CP0_EPC;
-	break;
-      case BADVADDR_REGNUM:
-	regaddr = EF_CP0_BADVADDR;
-	break;
-      case PS_REGNUM:
-	regaddr = EF_CP0_STATUS;
-	break;
-      case CAUSE_REGNUM:
-	regaddr = EF_CP0_CAUSE;
-	break;
-    }
+  if (regno == regnums->lo_regnum)
+    regaddr = EF_LO;
+  else if (regno == regnums->hi_regnum)
+    regaddr = EF_HI;
+  else if (regno == regnums->pc_regnum)
+    regaddr = EF_CP0_EPC;
+  else if (regno == regnums->badvaddr_regnum)
+    regaddr = EF_CP0_BADVADDR;
+  else if (regno == regnums->ps_regnum)
+    regaddr = EF_CP0_STATUS;
+  else if (regno == regnums->cause_regnum)
+    regaddr = EF_CP0_CAUSE;
 
   if (regaddr != -1)
     {
@@ -193,17 +188,17 @@ supply_fpregset (elf_fpregset_t *fpregse
 {
   register int regi;
   char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
 
   for (regi = 0; regi < 32; regi++)
-    supply_register (FP0_REGNUM + regi,
-		     (char *)(*fpregsetp + regi));
+    supply_register (regnums->fp0_regnum + regi, (char *)(*fpregsetp + regi));
 
-  supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
+  supply_register (regnums->fcrcs_regnum, (char *)(*fpregsetp + 32));
 
-  /* FIXME: how can we supply FCRIR_REGNUM?  The ABI doesn't tell us. */
-  supply_register (FCRIR_REGNUM, zerobuf);
+  /* FIXME: how can we supply FCRIR?  The ABI doesn't tell us. */
+  supply_register (regnums->fcrir_regnum, zerobuf);
 }
 
 /* Likewise, pack one or all floating point registers into an
@@ -213,14 +208,15 @@ void
 fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
 {
   char *from, *to;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
-  if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
+  if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
     {
       from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
-      to = (char *) (*fpregsetp + regno - FP0_REGNUM);
-      memcpy (to, from, REGISTER_RAW_SIZE (regno - FP0_REGNUM));
+      to = (char *) (*fpregsetp + regno - regnums->fp0_regnum);
+      memcpy (to, from, REGISTER_RAW_SIZE (regno - regnums->fp0_regnum));
     }
-  else if (regno == FCRCS_REGNUM)
+  else if (regno == regnums->fcrcs_regnum)
     {
       from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
       to = (char *) (*fpregsetp + 32);
@@ -231,8 +227,8 @@ fill_fpregset (elf_fpregset_t *fpregsetp
       int regi;
 
       for (regi = 0; regi < 32; regi++)
-	fill_fpregset (fpregsetp, FP0_REGNUM + regi);
-      fill_fpregset(fpregsetp, FCRCS_REGNUM);
+	fill_fpregset (fpregsetp, regnums->fp0_regnum + regi);
+      fill_fpregset(fpregsetp, regnums->fcrcs_regnum);
     }
 }
 
@@ -243,27 +239,28 @@ static CORE_ADDR
 mips_linux_register_addr (int regno, CORE_ADDR blockend)
 {
   int regaddr;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno < 0 || regno >= NUM_REGS)
     error ("Bogon register number %d.", regno);
 
   if (regno < 32)
     regaddr = regno;
-  else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
-    regaddr = FPR_BASE + (regno - FP0_REGNUM);
-  else if (regno == PC_REGNUM)
+  else if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
+    regaddr = FPR_BASE + (regno - regnums->fp0_regnum);
+  else if (regno == regnums->pc_regnum)
     regaddr = PC;
-  else if (regno == CAUSE_REGNUM)
+  else if (regno == regnums->cause_regnum)
     regaddr = CAUSE;
-  else if (regno == BADVADDR_REGNUM)
+  else if (regno == regnums->badvaddr_regnum)
     regaddr = BADVADDR;
-  else if (regno == LO_REGNUM)
+  else if (regno == regnums->lo_regnum)
     regaddr = MMLO;
-  else if (regno == HI_REGNUM)
+  else if (regno == regnums->hi_regnum)
     regaddr = MMHI;
-  else if (regno == FCRCS_REGNUM)
+  else if (regno == regnums->fcrcs_regnum)
     regaddr = FPC_CSR;
-  else if (regno == FCRIR_REGNUM)
+  else if (regno == regnums->fcrir_regnum)
     regaddr = FPC_EIR;
   else
     error ("Unknowable register number %d.", regno);
@@ -360,8 +357,9 @@ mips64_linux_get_longjmp_target (CORE_AD
   CORE_ADDR jb_addr;
   void *buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
   int element_size = TARGET_PTR_BIT == 32 ? 4 : 8;
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
 
-  jb_addr = read_register (A0_REGNUM);
+  jb_addr = read_register (regnums->a0_regnum);
 
   if (target_read_memory (jb_addr + MIPS64_LINUX_JB_PC * element_size,
 			  buf, TARGET_PTR_BIT / TARGET_CHAR_BIT))
@@ -380,23 +378,25 @@ mips64_supply_gregset (mips64_elf_gregse
   int regi;
   mips64_elf_greg_t *regp = *gregsetp;
   char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
 
   for (regi = MIPS64_EF_REG0; regi <= MIPS64_EF_REG31; regi++)
     supply_register ((regi - MIPS64_EF_REG0), (char *)(regp + regi));
 
-  supply_register (LO_REGNUM, (char *)(regp + MIPS64_EF_LO));
-  supply_register (HI_REGNUM, (char *)(regp + MIPS64_EF_HI));
+  supply_register (regnums->lo_regnum, (char *)(regp + MIPS64_EF_LO));
+  supply_register (regnums->hi_regnum, (char *)(regp + MIPS64_EF_HI));
 
-  supply_register (PC_REGNUM, (char *)(regp + MIPS64_EF_CP0_EPC));
-  supply_register (BADVADDR_REGNUM, (char *)(regp + MIPS64_EF_CP0_BADVADDR));
-  supply_register (PS_REGNUM, (char *)(regp + MIPS64_EF_CP0_STATUS));
-  supply_register (CAUSE_REGNUM, (char *)(regp + MIPS64_EF_CP0_CAUSE));
+  supply_register (regnums->pc_regnum, (char *)(regp + MIPS64_EF_CP0_EPC));
+  supply_register (regnums->badvaddr_regnum, (char *)(regp + MIPS64_EF_CP0_BADVADDR));
+  supply_register (regnums->ps_regnum, (char *)(regp + MIPS64_EF_CP0_STATUS));
+  supply_register (regnums->cause_regnum, (char *)(regp + MIPS64_EF_CP0_CAUSE));
 
   /* Fill inaccessible registers with zero.  */
-  supply_register (UNUSED_REGNUM, zerobuf);
-  for (regi = FIRST_EMBED_REGNUM; regi < LAST_EMBED_REGNUM; regi++)
+  for (regi = regnums->first_embed_regnum;
+       regi < regnums->last_embed_regnum;
+       regi++)
     supply_register (regi, zerobuf);
 }
 
@@ -408,18 +408,19 @@ mips64_fill_gregset (mips64_elf_gregset_
   int regaddr, regi;
   mips64_elf_greg_t *regp = *gregsetp;
   void *src, *dst;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno == -1)
     {
       memset (regp, 0, sizeof (mips64_elf_gregset_t));
       for (regi = 0; regi < 32; regi++)
         mips64_fill_gregset (gregsetp, regi);
-      mips64_fill_gregset (gregsetp, LO_REGNUM);
-      mips64_fill_gregset (gregsetp, HI_REGNUM);
-      mips64_fill_gregset (gregsetp, PC_REGNUM);
-      mips64_fill_gregset (gregsetp, BADVADDR_REGNUM);
-      mips64_fill_gregset (gregsetp, PS_REGNUM);
-      mips64_fill_gregset (gregsetp, CAUSE_REGNUM);
+      mips64_fill_gregset (gregsetp, regnums->lo_regnum);
+      mips64_fill_gregset (gregsetp, regnums->hi_regnum);
+      mips64_fill_gregset (gregsetp, regnums->pc_regnum);
+      mips64_fill_gregset (gregsetp, regnums->badvaddr_regnum);
+      mips64_fill_gregset (gregsetp, regnums->ps_regnum);
+      mips64_fill_gregset (gregsetp, regnums->cause_regnum);
 
       return;
    }
@@ -432,27 +433,18 @@ mips64_fill_gregset (mips64_elf_gregset_
     }
 
   regaddr = -1;
-  switch (regno)
-    {
-      case LO_REGNUM:
+      if (regno ==  regnums->lo_regnum)
 	regaddr = MIPS64_EF_LO;
-	break;
-      case HI_REGNUM:
+      else if (regno ==  regnums->hi_regnum)
 	regaddr = MIPS64_EF_HI;
-	break;
-      case PC_REGNUM:
+      else if (regno ==  regnums->pc_regnum)
 	regaddr = MIPS64_EF_CP0_EPC;
-	break;
-      case BADVADDR_REGNUM:
+      else if (regno ==  regnums->badvaddr_regnum)
 	regaddr = MIPS64_EF_CP0_BADVADDR;
-	break;
-      case PS_REGNUM:
+      else if (regno ==  regnums->ps_regnum)
 	regaddr = MIPS64_EF_CP0_STATUS;
-	break;
-      case CAUSE_REGNUM:
+      else if (regno ==  regnums->cause_regnum)
 	regaddr = MIPS64_EF_CP0_CAUSE;
-	break;
-    }
 
   if (regaddr != -1)
     {
@@ -468,17 +460,17 @@ mips64_supply_fpregset (mips64_elf_fpreg
 {
   register int regi;
   char *zerobuf = alloca (MAX_REGISTER_RAW_SIZE);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   memset (zerobuf, 0, MAX_REGISTER_RAW_SIZE);
 
   for (regi = 0; regi < 32; regi++)
-    supply_register (FP0_REGNUM + regi,
-		     (char *)(*fpregsetp + regi));
+    supply_register (regnums->fp0_regnum + regi, (char *)(*fpregsetp + regi));
 
-  supply_register (FCRCS_REGNUM, (char *)(*fpregsetp + 32));
+  supply_register (regnums->fcrcs_regnum, (char *)(*fpregsetp + 32));
 
-  /* FIXME: how can we supply FCRIR_REGNUM?  The ABI doesn't tell us. */
-  supply_register (FCRIR_REGNUM, zerobuf);
+  /* FIXME: how can we supply FCRIR?  The ABI doesn't tell us. */
+  supply_register (regnums->fcrir_regnum, zerobuf);
 }
 
 /* Likewise, pack one or all floating point registers into an
@@ -488,14 +480,15 @@ static void
 mips64_fill_fpregset (mips64_elf_fpregset_t *fpregsetp, int regno)
 {
   char *from, *to;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
-  if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
+  if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
     {
       from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
-      to = (char *) (*fpregsetp + regno - FP0_REGNUM);
-      memcpy (to, from, REGISTER_RAW_SIZE (regno - FP0_REGNUM));
+      to = (char *) (*fpregsetp + regno - regnums->fp0_regnum);
+      memcpy (to, from, REGISTER_RAW_SIZE (regno - regnums->fp0_regnum));
     }
-  else if (regno == FCRCS_REGNUM)
+  else if (regno == regnums->fcrcs_regnum)
     {
       from = (char *) &deprecated_registers[REGISTER_BYTE (regno)];
       to = (char *) (*fpregsetp + 32);
@@ -506,8 +499,8 @@ mips64_fill_fpregset (mips64_elf_fpregse
       int regi;
 
       for (regi = 0; regi < 32; regi++)
-	mips64_fill_fpregset (fpregsetp, FP0_REGNUM + regi);
-      mips64_fill_fpregset(fpregsetp, FCRCS_REGNUM);
+	mips64_fill_fpregset (fpregsetp, regnums->fp0_regnum + regi);
+      mips64_fill_fpregset(fpregsetp, regnums->fcrcs_regnum);
     }
 }
 
@@ -519,27 +512,28 @@ static CORE_ADDR
 mips64_linux_register_addr (int regno, CORE_ADDR blockend)
 {
   int regaddr;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno < 0 || regno >= NUM_REGS)
     error ("Bogon register number %d.", regno);
 
   if (regno < 32)
     regaddr = regno;
-  else if ((regno >= FP0_REGNUM) && (regno < FP0_REGNUM + 32))
-    regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
-  else if (regno == PC_REGNUM)
+  else if ((regno >= regnums->fp0_regnum) && (regno < regnums->fp0_regnum + 32))
+    regaddr = MIPS64_FPR_BASE + (regno - regnums->fp0_regnum);
+  else if (regno == regnums->pc_regnum)
     regaddr = MIPS64_PC;
-  else if (regno == CAUSE_REGNUM)
+  else if (regno == regnums->cause_regnum)
     regaddr = MIPS64_CAUSE;
-  else if (regno == BADVADDR_REGNUM)
+  else if (regno == regnums->badvaddr_regnum)
     regaddr = MIPS64_BADVADDR;
-  else if (regno == LO_REGNUM)
+  else if (regno == regnums->lo_regnum)
     regaddr = MIPS64_MMLO;
-  else if (regno == HI_REGNUM)
+  else if (regno == regnums->hi_regnum)
     regaddr = MIPS64_MMHI;
-  else if (regno == FCRCS_REGNUM)
+  else if (regno == regnums->fcrcs_regnum)
     regaddr = MIPS64_FPC_CSR;
-  else if (regno == FCRIR_REGNUM)
+  else if (regno == regnums->fcrir_regnum)
     regaddr = MIPS64_FPC_EIR;
   else
     error ("Unknowable register number %d.", regno);
Index: mips-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-nat.c,v
retrieving revision 1.10
diff -u -p -r1.10 mips-nat.c
--- mips-nat.c	29 Apr 2003 01:49:47 -0000	1.10
+++ mips-nat.c	9 May 2003 23:36:32 -0000
@@ -1,5 +1,5 @@
 /* Low level DECstation interface to ptrace, for GDB when running native.
-   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000, 2001
+   Copyright 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1999, 2000, 2001, 2003
    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.
@@ -43,6 +43,7 @@
 #undef JB_SR
 #undef NJBREGS
 #include <setjmp.h>		/* For JB_XXX.  */
+#include <mips-tdep.h>
 
 /* Size of elements in jmpbuf */
 
@@ -51,16 +52,22 @@
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are defined in DECstation <sys/ptrace.h> */
 
-#define REGISTER_PTRACE_ADDR(regno) \
-   (regno < 32 ? 		GPR_BASE + regno \
-  : regno == PC_REGNUM ?	PC	\
-  : regno == CAUSE_REGNUM ?	CAUSE	\
-  : regno == HI_REGNUM ?	MMHI	\
-  : regno == LO_REGNUM ?	MMLO	\
-  : regno == FCRCS_REGNUM ?	FPC_CSR	\
-  : regno == FCRIR_REGNUM ?	FPC_EIR	\
-  : regno >= FP0_REGNUM ?	FPR_BASE + (regno - FP0_REGNUM) \
+static int
+register_ptrace_addr (int regno)
+{
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
+  return
+   (regno < 32 ? 			GPR_BASE + regno
+  : regno == regnums->pc_regnum ?	PC
+  : regno == regnums->cause_regnum ?	CAUSE
+  : regno == regnums->hi_regnum ?	MMHI
+  : regno == regnums->lo_regnum ?	MMLO
+  : regno == regnums->fcrcs_regnum ?	FPC_CSR
+  : regno == regnums->fcrir_regnum ?	FPC_EIR
+  : regno >= regnums->fp0_regnum ?	FPR_BASE + (regno - regnums->fp0_regnum)
   : 0)
+}
 
 static void fetch_core_registers (char *, unsigned, int, CORE_ADDR);
 
@@ -73,13 +80,15 @@ fetch_inferior_registers (int regno)
   char *buf = alloca (max_register_size (current_gdbarch));
   register int i;
   char *zerobuf = alloca (max_register_size (current_gdbarch));
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   memset (zerobuf, 0, max_register_size (current_gdbarch));
 
   deprecated_registers_fetched ();
 
   for (regno = 1; regno < NUM_REGS; regno++)
     {
-      regaddr = REGISTER_PTRACE_ADDR (regno);
+      regaddr = register_ptrace_addr (regno);
       for (i = 0; i < REGISTER_RAW_SIZE (regno); i += sizeof (int))
 	{
 	  *(int *) &buf[i] = ptrace (PT_READ_U, PIDGET (inferior_ptid),
@@ -89,7 +98,7 @@ fetch_inferior_registers (int regno)
       supply_register (regno, buf);
     }
 
-  supply_register (ZERO_REGNUM, zerobuf);
+  supply_register (regnums->zero_regnum, zerobuf);
   /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
   supply_register (DEPRECATED_FP_REGNUM, zerobuf);
 }
@@ -103,15 +112,20 @@ store_inferior_registers (int regno)
 {
   register unsigned int regaddr;
   char buf[80];
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno > 0)
     {
-      if (regno == ZERO_REGNUM || regno == PS_REGNUM
-	  || regno == BADVADDR_REGNUM || regno == CAUSE_REGNUM
-	  || regno == FCRIR_REGNUM || regno == DEPRECATED_FP_REGNUM
-	  || (regno >= FIRST_EMBED_REGNUM && regno <= LAST_EMBED_REGNUM))
+      if (regno == regnums->zero_regnum
+          || regno == regnums->ps_regnum
+	  || regno == regnums->badvaddr_regnum
+	  || regnums->regno == regnums->cause_regnum
+	  || regno == regnums->fcrir_regnum
+	  || regno == DEPRECATED_FP_REGNUM
+	  || (regno >= regnums->first_embed_regnum
+	      && regno <= regnums->last_embed_regnum))
 	return;
-      regaddr = REGISTER_PTRACE_ADDR (regno);
+      regaddr = register_ptrace_addr (regno);
       errno = 0;
       ptrace (PT_WRITE_U, PIDGET (inferior_ptid), (PTRACE_ARG3_TYPE) regaddr,
 	      read_register (regno));
@@ -139,9 +153,10 @@ get_longjmp_target (CORE_ADDR *pc)
 {
   CORE_ADDR jb_addr;
   char *buf;
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
 
   buf = alloca (TARGET_PTR_BIT / TARGET_CHAR_BIT);
-  jb_addr = read_register (A0_REGNUM);
+  jb_addr = read_register (regnums->a0_regnum);
 
   if (target_read_memory (jb_addr + JB_PC * JB_ELEMENT_SIZE, buf,
 			  TARGET_PTR_BIT / TARGET_CHAR_BIT))
@@ -173,6 +188,7 @@ fetch_core_registers (char *core_reg_sec
   register unsigned int addr;
   int bad_reg = -1;
   register reg_ptr = -reg_addr;	/* Original u.u_ar0 is -reg_addr. */
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   char *zerobuf = alloca (max_register_size (current_gdbarch));
   memset (zerobuf, 0, max_register_size (current_gdbarch));
@@ -208,7 +224,7 @@ fetch_core_registers (char *core_reg_sec
     {
       error ("Register %s not found in core file.", REGISTER_NAME (bad_reg));
     }
-  supply_register (ZERO_REGNUM, zerobuf);
+  supply_register (regnums->zero_regnum, zerobuf);
   /* Frame ptr reg must appear to be 0; it is faked by stack handling code. */
   supply_register (DEPRECATED_FP_REGNUM, zerobuf);
 }
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.195
diff -u -p -r1.195 mips-tdep.c
--- mips-tdep.c	5 May 2003 17:56:55 -0000	1.195
+++ mips-tdep.c	9 May 2003 23:36:34 -0000
@@ -42,6 +42,7 @@
 #include "osabi.h"
 #include "mips-tdep.h"
 #include "block.h"
+#include "reggroups.h"
 
 #include "opcode/mips.h"
 #include "elf/mips.h"
@@ -124,24 +125,30 @@ struct gdbarch_tdep
     enum mips_abi mips_abi;
     enum mips_abi found_abi;
     enum mips_fpu_type mips_fpu_type;
-    int mips_last_arg_regnum;
-    int mips_last_fp_arg_regnum;
     int mips_default_saved_regsize;
     int mips_fp_register_double;
     int mips_default_stack_argsize;
     int gdb_target_is_mips64;
     int default_mask_address_p;
+
+    struct mips_regnums raw_regnums;
+    struct mips_regnums cooked_regnums;
+
+    char **regnames;
   };
 
 #define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
 		   || gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
 
-#define MIPS_LAST_FP_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_fp_arg_regnum)
-
-#define MIPS_LAST_ARG_REGNUM (gdbarch_tdep (current_gdbarch)->mips_last_arg_regnum)
-
 #define MIPS_FPU_TYPE (gdbarch_tdep (current_gdbarch)->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. */
+#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
+
 /* Return the currently configured (or set) saved register size. */
 
 #define MIPS_DEFAULT_SAVED_REGSIZE (gdbarch_tdep (current_gdbarch)->mips_default_saved_regsize)
@@ -157,6 +164,18 @@ mips_abi (struct gdbarch *gdbarch)
   return gdbarch_tdep (gdbarch)->mips_abi;
 }
 
+const struct mips_regnums *
+mips_raw_regnums (struct gdbarch *gdbarch)
+{
+  return &(gdbarch_tdep (gdbarch)->raw_regnums);
+}
+
+const struct mips_regnums *
+mips_cooked_regnums (struct gdbarch *gdbarch)
+{
+  return &(gdbarch_tdep (gdbarch)->cooked_regnums);
+}
+
 static unsigned int
 mips_saved_regsize (void)
 {
@@ -266,9 +285,11 @@ mips_xfer_register (struct regcache *reg
 static int
 mips2_fp_compat (void)
 {
+  const struct mips_regnums *cooked_regnums
+    = mips_cooked_regnums (current_gdbarch);
   /* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
      meaningful.  */
-  if (REGISTER_RAW_SIZE (FP0_REGNUM) == 4)
+  if (REGISTER_RAW_SIZE (cooked_regnums->fp0_regnum) == 4)
     return 0;
 
 #if 0
@@ -277,20 +298,13 @@ mips2_fp_compat (void)
   /* 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)
+  if ((read_register (cooked_regnums->ps_regnum) & ST0_FR) == 0)
     return 1;
 #endif
 
-  return 0;
+  return !FP_REGISTER_DOUBLE;
 }
 
-/* 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. */
-#define FP_REGISTER_DOUBLE (gdbarch_tdep (current_gdbarch)->mips_fp_register_double)
-
 /* The amount of space reserved on the stack for registers. This is
    different to MIPS_SAVED_REGSIZE as it determines the alignment of
    data allocated after the registers have run out. */
@@ -348,6 +362,14 @@ static void mips_read_fp_register_double
 static struct type *mips_float_register_type (void);
 static struct type *mips_double_register_type (void);
 
+/* Types used for cooked floating point registers.  These are union
+   types which allow the user to view (or set) the floating point
+   register in a variety of ways.  */
+static struct type *mips_type_float_double_register_big;
+static struct type *mips_type_float_double_register_little;
+static struct type *mips_type_float_single_register_big;
+static struct type *mips_type_float_single_register_little;
+
 /* This value is the model of MIPS in use.  It is derived from the value
    of the PrID register.  */
 
@@ -360,19 +382,20 @@ char *tmp_mips_processor_type;
 static struct cmd_list_element *setmipscmdlist = NULL;
 static struct cmd_list_element *showmipscmdlist = NULL;
 
-/* A set of original names, to be used when restoring back to generic
-   registers from a specific set.  */
-static char *mips_generic_reg_names[] = MIPS_REGISTER_NAMES;
-
-/* Integer registers 0 thru 31 are handled explicitly by
-   mips_register_name().  Processor specific registers 32 and above
-   are listed in the sets of register names assigned to
-   mips_processor_reg_names.  */
-static char **mips_processor_reg_names = mips_generic_reg_names;
+/* Names of generic embedded registers.  */
+char *mips_generic_embed_reg_names[] = {
+  "", "", "", "", "", "", "", "",
+  "", "", "", "", "", "", "", "",
+};
 
-/* Return the name of the register corresponding to REGNO.  */
+/* Names of special purpose (embedded) registers.  */
+static char **mips_embed_reg_names = mips_generic_embed_reg_names;
+
+/* Given a register number REGNO and set of register numbers assignments
+   REGNUMS, return the name for REGNO.  If no name can be determined,
+   return NULL.  */
 static const char *
-mips_register_name (int regno)
+reg_name (int regno, const struct mips_regnums *regnums)
 {
   /* GPR names for all ABIs other than n32/n64.  */
   static char *mips_gpr_names[] = {
@@ -390,67 +413,135 @@ mips_register_name (int regno)
     "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
   };
 
+  /* FPR names */
+  static char *mips_fpr_names[] = {
+    "f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
+    "f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
+    "f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
+    "f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
+  };
+
   enum mips_abi abi = mips_abi (current_gdbarch);
 
-  /* The MIPS integer registers are always mapped from 0 to 31.  The
-     names of the registers (which reflects the conventions regarding
-     register use) vary depending on the ABI.  */
-  if (0 <= regno && regno < 32)
+  /* ``zero_regnum'' is the first GPR.  ``ra_regnum'' is the last GPR.
+     The names of the general purpose registers (which reflects the
+     conventions regarding register use) vary depending on the ABI.  */
+  if (regnums->zero_regnum <= regno && regno <= regnums->ra_regnum)
     {
       if (abi == MIPS_ABI_N32 || abi == MIPS_ABI_N64)
-	return mips_n32_n64_gpr_names[regno];
+	return mips_n32_n64_gpr_names[regno - regnums->zero_regnum];
       else
-	return mips_gpr_names[regno];
+	return mips_gpr_names[regno - regnums->zero_regnum];
     }
-  else if (32 <= regno && regno < NUM_REGS)
-    return mips_processor_reg_names[regno - 32];
+  else if (regnums->fp0_regnum <= regno && regno <= regnums->fplast_regnum)
+    {
+      if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+	return mips_fpr_names[2 * (regno - regnums->fp0_regnum)];
+      else
+	return mips_fpr_names[regno - regnums->fp0_regnum];
+    }
+  else if (regno == regnums->ps_regnum)
+    return "sr";
+  else if (regno == regnums->lo_regnum)
+    return "lo";
+  else if (regno == regnums->hi_regnum)
+    return "hi";
+  else if (regno == regnums->badvaddr_regnum)
+    return "bad";
+  else if (regno == regnums->cause_regnum)
+    return "cause";
+  else if (regno == regnums->pc_regnum)
+    return "pc";
+  else if (regno == regnums->fcrcs_regnum)
+    return "fsr";
+  else if (regno == regnums->fcrir_regnum)
+    return "fir";
+  else if (regnums->first_embed_regnum <= regno
+           && regno <= regnums->last_embed_regnum)
+    return mips_embed_reg_names[regno - regnums->first_embed_regnum];
   else
-    internal_error (__FILE__, __LINE__,
-		    "mips_register_name: bad register number %d", regno);
+    return NULL;
+}
+
+/* Return the name of the register corresponding to REGNO.  */
+static const char *
+mips_register_name (int regno)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const char *name;
+
+  if (tdep->regnames == NULL)
+    tdep->regnames = xcalloc (NUM_REGS + NUM_PSEUDO_REGS, sizeof (char *));
+
+  gdb_assert (0 <= regno && regno < NUM_REGS + NUM_PSEUDO_REGS);
+
+  if (tdep->regnames[regno])
+    return tdep->regnames[regno];
+
+  name = reg_name (regno, mips_cooked_regnums (current_gdbarch));
+
+  if (name != NULL)
+    {
+      tdep->regnames[regno] = xstrdup (name);
+      return name;
+    }
+
+  name = reg_name (regno, mips_raw_regnums (current_gdbarch));
+
+  if (name != NULL && *name != '\0')
+    {
+      char *raw_name = xmalloc (strlen (name) + 4 /* for "raw_" */ + 1);
+      strcpy (raw_name, "raw_");
+      strcat (raw_name, name);
+      tdep->regnames[regno] = raw_name;
+      return raw_name;
+    }
+
+  /* Couldn't find a name.  Use the empty string.  */
+  name = "";
+  tdep->regnames[regno] = xstrdup (name);
+  return name;
 }
 
 /* *INDENT-OFF* */
-/* Names of IDT R3041 registers.  */
 
-char *mips_r3041_reg_names[] = {
-	"sr",	"lo",	"hi",	"bad",	"cause","pc",
-	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-	"fsr",  "fir",  "",/*"fp"*/	"",
+
+/* Names of tx39 embedded registers.  */
+
+char *mips_tx39_embed_reg_names[] = {
+	"",	"",	"",	"",	"",	"",	"",	"",
+	"",	"", "config", "cache", "debug", "depc", "epc",	"" 
+};
+
+/* Names of IDT R3041 embedded registers.  */
+
+char *mips_r3041_embed_reg_names[] = {
 	"",	"",	"bus",	"ccfg",	"",	"",	"",	"",
 	"",	"",	"port",	"cmp",	"",	"",	"epc",	"prid",
 };
 
-/* Names of IDT R3051 registers.  */
+/* Names of IDT R3051 embedded registers.  */
 
-char *mips_r3051_reg_names[] = {
-	"sr",	"lo",	"hi",	"bad",	"cause","pc",
-	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-	"fsr",  "fir",  ""/*"fp"*/,	"",
+char *mips_r3051_embed_reg_names[] = {
 	"inx",	"rand",	"elo",	"",	"ctxt",	"",	"",	"",
 	"",	"",	"ehi",	"",	"",	"",	"epc",	"prid",
 };
 
-/* Names of IDT R3081 registers.  */
+/* Names of IDT R3081 embedded registers.  */
 
-char *mips_r3081_reg_names[] = {
-	"sr",	"lo",	"hi",	"bad",	"cause","pc",
-	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7",
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15",
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",
-	"fsr",  "fir",  ""/*"fp"*/,	"",
+char *mips_r3081_embed_reg_names[] = {
 	"inx",	"rand",	"elo",	"cfg",	"ctxt",	"",	"",	"",
 	"",	"",	"ehi",	"",	"",	"",	"epc",	"prid",
 };
 
+#if 0
 /* Names of LSI 33k registers.  */
 
+/* Note: kevinb/2003-05-06: These are all of the names following the GPRs.
+   "baddvaddr" is in the position where "pc" would normally appear, so
+   I don't see how this ever could have worked.  I've disabled this code
+   until someone who understands it better than I do can take a look...  */
+
 char *mips_lsi33k_reg_names[] = {
 	"epc",	"hi",	"lo",	"sr",	"cause","badvaddr",
 	"dcic", "bpc",  "bda",  "",     "",     "",     "",      "",
@@ -461,17 +552,21 @@ char *mips_lsi33k_reg_names[] = {
 	"",	"",	"",	"",	"",	"",	"",	 "",
 	"",	"",	"",	"",	"",	"",	"",	 "",
 };
+#endif
 
 struct {
   char *name;
   char **regnames;
 } mips_processor_type_table[] = {
-  { "generic", mips_generic_reg_names },
-  { "r3041", mips_r3041_reg_names },
-  { "r3051", mips_r3051_reg_names },
-  { "r3071", mips_r3081_reg_names },
-  { "r3081", mips_r3081_reg_names },
-  { "lsi33k", mips_lsi33k_reg_names },
+  { "generic", mips_generic_embed_reg_names },
+  { "r3041", mips_r3041_embed_reg_names },
+  { "r3051", mips_r3051_embed_reg_names },
+  { "r3071", mips_r3081_embed_reg_names },
+  { "r3081", mips_r3081_embed_reg_names },
+#if 0
+  { "lsi33k", mips_lsi33k_embed_reg_names },
+#endif
+  { "tx39", mips_tx39_embed_reg_names },
   { NULL, NULL }
 };
 /* *INDENT-ON* */
@@ -531,126 +626,119 @@ mips_print_extra_frame_info (struct fram
 
 static int mips64_transfers_32bit_regs_p = 0;
 
-static int
-mips_register_raw_size (int 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;
-}
-
-/* Convert between RAW and VIRTUAL registers.  The RAW register size
-   defines the remote-gdb packet. */
-
-static int
-mips_register_convertible (int reg_nr)
-{
-  if (mips64_transfers_32bit_regs_p)
-    return 0;
-  else
-    return (REGISTER_RAW_SIZE (reg_nr) > REGISTER_VIRTUAL_SIZE (reg_nr));
-}
-
-static void
-mips_register_convert_to_virtual (int n, struct type *virtual_type,
-				  char *raw_buf, char *virt_buf)
-{
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-    memcpy (virt_buf,
-	    raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
-	    TYPE_LENGTH (virtual_type));
-  else
-    memcpy (virt_buf,
-	    raw_buf,
-	    TYPE_LENGTH (virtual_type));
-}
-
-static void
-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));
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-    memcpy (raw_buf + (REGISTER_RAW_SIZE (n) - TYPE_LENGTH (virtual_type)),
-	    virt_buf,
-	    TYPE_LENGTH (virtual_type));
-  else
-    memcpy (raw_buf,
-	    virt_buf,
-	    TYPE_LENGTH (virtual_type));
-}
-
-void
-mips_register_convert_to_type (int regnum, struct type *type, char *buffer)
-{
-  if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-      && REGISTER_RAW_SIZE (regnum) == 4
-      && (regnum) >= FP0_REGNUM && (regnum) < FP0_REGNUM + 32
-      && TYPE_CODE(type) == TYPE_CODE_FLT
-      && TYPE_LENGTH(type) == 8) 
-    {
-      char temp[4];
-      memcpy (temp, ((char *)(buffer))+4, 4);
-      memcpy (((char *)(buffer))+4, (buffer), 4);
-      memcpy (((char *)(buffer)), temp, 4); 
-    }
-}
-
-void
-mips_register_convert_from_type (int regnum, struct type *type, char *buffer)
-{
-if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-    && REGISTER_RAW_SIZE (regnum) == 4
-    && (regnum) >= FP0_REGNUM && (regnum) < FP0_REGNUM + 32
-    && TYPE_CODE(type) == TYPE_CODE_FLT
-    && TYPE_LENGTH(type) == 8) 
-  {
-    char temp[4];
-    memcpy (temp, ((char *)(buffer))+4, 4);
-    memcpy (((char *)(buffer))+4, (buffer), 4);
-    memcpy (((char *)(buffer)), temp, 4);
-  }
-}
-
 /* Return the GDB type object for the "standard" data type
    of data in register REG.  
    
-   Note: kevinb/2002-08-01: The definition below should faithfully
-   reproduce the behavior of each of the REGISTER_VIRTUAL_TYPE
-   definitions found in config/mips/tm-*.h.  I'm concerned about the
-   ``FCRCS_REGNUM <= reg && reg <= LAST_EMBED_REGNUM'' clause though.
-   In some cases DEPRECATED_FP_REGNUM is in this range, and I doubt
-   that this code is correct for the 64-bit case.  */
+   As noted below, the types returned in the [0, NUM_REGS) range are
+   constrained by the remote protocol.  */
 
 static struct type *
-mips_register_virtual_type (int reg)
+mips_register_type (struct gdbarch *gdbarch, int regno)
 {
-  if (FP0_REGNUM <= reg && reg < FP0_REGNUM + 32)
+  const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+
+  gdb_assert (0 <= regno && regno <= NUM_REGS + NUM_PSEUDO_REGS);
+
+  if (regno < NUM_REGS)
     {
-      /* Floating point registers...  */
-      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
-	return builtin_type_ieee_double_big;
+      /* We must be careful with the sizes of these types because
+         they influence the layout of the remote protocol.  */
+      if (MIPS_REGSIZE == 4)
+	{
+	  /* The type length of each of the types returned in this
+	     block is 4.  */
+	  if (raw_regnums->fp0_regnum <= regno
+	      && regno <= raw_regnums->fplast_regnum)
+	    {
+	      /* It's tempting to make these some kind of floating
+	         point type, but it's actually more useful to just
+		 print the raw fp registers as ints.  The cooked
+		 regnums provide access to multiple representations.  */
+	      return builtin_type_uint32;
+	    }
+	  else if (regno == raw_regnums->ps_regnum /* SR */
+	        || regno == raw_regnums->fcrcs_regnum
+	        || regno == raw_regnums->fcrir_regnum
+		|| (raw_regnums->first_embed_regnum <= regno
+		    && regno <= raw_regnums->last_embed_regnum))
+	    return builtin_type_uint32;
+	  else
+	    return builtin_type_int32;
+	}
+      else if (MIPS_REGSIZE == 8)
+	{
+	  /* The type lengths of each of the types returned in this
+	     block is 8 except when ``mips64_transfers_32_bit_regs_p''
+	     is true.  When ``mips64_transfers_32_bit_regs_p'' is true,
+	     certain registers are only 4 bytes wide.  */
+	  if (raw_regnums->fp0_regnum <= regno
+	      && regno <= raw_regnums->fplast_regnum)
+	    {
+	      return builtin_type_uint64;
+	    }
+	  else if (regno == raw_regnums->ps_regnum /* SR */
+	        || regno == raw_regnums->fcrcs_regnum
+	        || regno == raw_regnums->fcrir_regnum
+		|| (raw_regnums->first_embed_regnum <= regno
+		    && regno <= raw_regnums->last_embed_regnum))
+	    {
+	      if (mips64_transfers_32bit_regs_p)
+		return builtin_type_uint32;
+	      else
+		return builtin_type_uint64;
+	    }
+	  else
+	    return builtin_type_uint64;
+	}
       else
-	return builtin_type_ieee_double_little;
+	{
+	  internal_error (__FILE__, __LINE__,
+			  "mips_register_type: bad MIPS_REGSIZE value");
+	}
     }
-  else if (reg == PS_REGNUM /* CR */)
-    return builtin_type_uint32;
-  else if (FCRCS_REGNUM <= reg && reg <= LAST_EMBED_REGNUM)
-    return builtin_type_uint32;
   else
     {
-      /* Everything else...
-         Return type appropriate for width of register.  */
-      if (MIPS_REGSIZE == TYPE_LENGTH (builtin_type_uint64))
-	return builtin_type_uint64;
-      else
+      /* These registers are pseudo-registers.  We are (more or less)
+         free to define them to be whatever we want them to be.  */
+      if (cooked_regnums->fp0_regnum <= regno
+          && regno <= cooked_regnums->fplast_regnum)
+	{
+	  if (MIPS_FPU_TYPE == MIPS_FPU_SINGLE)
+	    {
+	      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+		return mips_type_float_single_register_big;
+	      else
+		return mips_type_float_single_register_little;
+	    }
+	  else if (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+	    {
+	      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+		return mips_type_float_double_register_big;
+	      else
+		return mips_type_float_double_register_little;
+	    }
+	  else
+	    {
+	      /* The other choice is that MIPS_FPU_TYPE is MIPS_FPU_NONE,
+	         but that shouldn't happen because fp0_regnum and
+		 fplast_regnum should've been set to -1.  */
+	      internal_error (__FILE__, __LINE__,
+			      "mips_register_type: bad MIPS_FPU_TYPE value");
+	    }
+	}
+      else if (regno == cooked_regnums->ps_regnum /* SR */
+	    || regno == cooked_regnums->fcrcs_regnum
+	    || regno == cooked_regnums->fcrir_regnum
+	    || (cooked_regnums->first_embed_regnum <= regno
+		&& cooked_regnums->last_embed_regnum))
 	return builtin_type_uint32;
+      else
+	{
+	  internal_error (__FILE__, __LINE__,
+			  "mips_register_type: unknown pseudo register %d [%s]\n",
+			  regno, REGISTER_NAME (regno));
+	}
     }
 }
 
@@ -659,7 +747,9 @@ mips_register_virtual_type (int reg)
 static CORE_ADDR
 mips_read_sp (void)
 {
-  return read_signed_register (SP_REGNUM);
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+  return read_signed_register (regnums->sp_regnum);
 }
 
 /* Should the upper word of 64-bit addresses be zeroed? */
@@ -781,7 +871,9 @@ pc_is_mips16 (bfd_vma memaddr)
 static CORE_ADDR
 mips_read_pc (ptid_t ptid)
 {
-  return read_signed_register_pid (PC_REGNUM, ptid);
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+  return read_signed_register_pid (regnums->pc_regnum, ptid);
 }
 
 /* This returns the PC of the first inst after the prologue.  If we can't
@@ -793,6 +885,7 @@ after_prologue (CORE_ADDR pc,
 {
   struct symtab_and_line sal;
   CORE_ADDR func_addr, func_end;
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
 
   /* Pass cur_frame == 0 to find_proc_desc.  We should not attempt
      to read the stack pointer from the current machine state, because
@@ -806,7 +899,7 @@ after_prologue (CORE_ADDR pc,
     {
       /* If function is frameless, then we need to do it the hard way.  I
          strongly suspect that frameless always means prologueless... */
-      if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+      if (PROC_FRAME_REG (proc_desc) == regnums->sp_regnum
 	  && PROC_FRAME_OFFSET (proc_desc) == 0)
 	return 0;
     }
@@ -866,6 +959,8 @@ mips32_decode_reg_save (t_inst inst, uns
 static void
 mips16_decode_reg_save (t_inst inst, unsigned long *gen_mask)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if ((inst & 0xf800) == 0xd000)	/* sw reg,n($sp) */
     {
       int reg = mips16_to_32_reg[(inst & 0x700) >> 8];
@@ -878,7 +973,7 @@ mips16_decode_reg_save (t_inst inst, uns
     }
   else if ((inst & 0xff00) == 0x6200	/* sw $ra,n($sp) */
 	   || (inst & 0xff00) == 0xfa00)	/* sd $ra,n($sp) */
-    *gen_mask |= (1 << RA_REGNUM);
+    *gen_mask |= (1 << (regnums->ra_regnum - regnums->zero_regnum));
 }
 
 
@@ -943,6 +1038,8 @@ mips32_next_pc (CORE_ADDR pc)
 {
   unsigned long inst;
   int op;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   inst = mips_fetch_instruction (pc);
   if ((inst & 0xe0000000) != 0)	/* Not a special, jump or branch instruction */
     {
@@ -969,7 +1066,7 @@ mips32_next_pc (CORE_ADDR pc)
 	{
 	  int tf = itype_rt (inst) & 0x01;
 	  int cnum = itype_rt (inst) >> 2;
-	  int fcrcs = read_signed_register (FCRCS_REGNUM);
+	  int fcrcs = read_signed_register (regnums->fcrcs_regnum);
 	  int cond = ((fcrcs >> 24) & 0x0e) | ((fcrcs >> 23) & 0x01);
 
 	  if (((cond >> cnum) & 0x01) == tf)
@@ -1420,6 +1517,8 @@ mips_find_saved_regs (struct frame_info 
   unsigned long gen_mask, float_mask;
   mips_extra_func_info_t proc_desc;
   t_inst inst;
+  const struct mips_regnums *raw_regnums = mips_raw_regnums (current_gdbarch);
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (current_gdbarch);
 
   frame_saved_regs_zalloc (fci);
 
@@ -1453,9 +1552,9 @@ mips_find_saved_regs (struct frame_info 
 	{
 	  reg_position = get_frame_base (fci) + SIGFRAME_FPREGSAVE_OFF
 	    + ireg * SIGFRAME_REG_SIZE;
-	  get_frame_saved_regs (fci)[FP0_REGNUM + ireg] = reg_position;
+	  get_frame_saved_regs (fci)[raw_regnums->fp0_regnum + ireg] = reg_position;
 	}
-      get_frame_saved_regs (fci)[PC_REGNUM] = get_frame_base (fci) + SIGFRAME_PC_OFF;
+      get_frame_saved_regs (fci)[raw_regnums->pc_regnum] = get_frame_base (fci) + SIGFRAME_PC_OFF;
       return;
     }
 
@@ -1581,11 +1680,25 @@ mips_find_saved_regs (struct frame_info 
   for (ireg = MIPS_NUMREGS - 1; float_mask; --ireg, float_mask <<= 1)
     if (float_mask & 0x80000000)
       {
-	get_frame_saved_regs (fci)[FP0_REGNUM + ireg] = reg_position;
+	get_frame_saved_regs (fci)[raw_regnums->fp0_regnum + ireg]
+	  = reg_position;
+
+	/* Now take care of the cooked register number.  */
+	if (!FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+	  {
+	    if ((ireg & 1) == 0)
+	      get_frame_saved_regs (fci)[cooked_regnums->fp0_regnum + ireg / 2]
+		= reg_position;
+	  }
+	else
+	  get_frame_saved_regs (fci)[cooked_regnums->fp0_regnum + ireg]
+	    = reg_position;
+
 	reg_position -= MIPS_SAVED_REGSIZE;
       }
 
-  get_frame_saved_regs (fci)[PC_REGNUM] = get_frame_saved_regs (fci)[RA_REGNUM];
+  get_frame_saved_regs (fci)[raw_regnums->pc_regnum]
+    = get_frame_saved_regs (fci)[raw_regnums->ra_regnum];
 }
 
 /* Set up the 'saved_regs' array.  This is a data structure containing
@@ -1598,11 +1711,13 @@ mips_find_saved_regs (struct frame_info 
 static void
 mips_frame_init_saved_regs (struct frame_info *frame)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (get_frame_saved_regs (frame) == NULL)
     {
       mips_find_saved_regs (frame);
     }
-  get_frame_saved_regs (frame)[SP_REGNUM] = get_frame_base (frame);
+  get_frame_saved_regs (frame)[regnums->sp_regnum] = get_frame_base (frame);
 }
 
 static CORE_ADDR
@@ -1697,10 +1812,11 @@ mips_software_single_step (enum target_s
   typedef char binsn_quantum[BREAKPOINT_MAX];
   static binsn_quantum break_mem;
   CORE_ADDR pc;
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
 
   if (insert_breakpoints_p)
     {
-      pc = read_register (PC_REGNUM);
+      pc = read_register (regnums->pc_regnum);
       next_pc = mips_next_pc (pc);
 
       target_insert_breakpoint (next_pc, break_mem);
@@ -1729,15 +1845,17 @@ mips_frame_saved_pc (struct frame_info *
 {
   CORE_ADDR saved_pc;
   mips_extra_func_info_t proc_desc = get_frame_extra_info (frame)->proc_desc;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   /* We have to get the saved pc from the sigcontext
      if it is a signal handler frame.  */
-  int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME) ? PC_REGNUM
-  : (proc_desc ? PROC_PC_REG (proc_desc) : RA_REGNUM);
+  int pcreg = (get_frame_type (frame) == SIGTRAMP_FRAME) ? regnums->pc_regnum
+  : (proc_desc ? PROC_PC_REG (proc_desc) : regnums->ra_regnum);
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
     {
       LONGEST tmp;
-      frame_unwind_signed_register (frame, PC_REGNUM, &tmp);
+      frame_unwind_signed_register (frame, regnums->pc_regnum, &tmp);
       saved_pc = tmp;
     }
   else if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
@@ -1933,6 +2051,7 @@ mips16_heuristic_proc_desc (CORE_ADDR st
   unsigned inst = 0;		/* current instruction */
   unsigned entry_inst = 0;	/* the entry instruction */
   int reg, offset;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   PROC_FRAME_OFFSET (&temp_proc_desc) = 0;	/* size of stack frame */
   PROC_FRAME_ADJUST (&temp_proc_desc) = 0;	/* offset of FP from SP */
@@ -1974,14 +2093,14 @@ mips16_heuristic_proc_desc (CORE_ADDR st
       else if ((inst & 0xff00) == 0x6200)	/* sw $ra,n($sp) */
 	{
 	  offset = mips16_get_imm (prev_inst, inst, 8, 4, 0);
-	  PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
-	  set_reg_offset (RA_REGNUM, sp + offset);
+	  PROC_REG_MASK (&temp_proc_desc) |= (1 << regnums->ra_regnum);
+	  set_reg_offset (regnums->ra_regnum, sp + offset);
 	}
       else if ((inst & 0xff00) == 0xfa00)	/* sd $ra,n($sp) */
 	{
 	  offset = mips16_get_imm (prev_inst, inst, 8, 8, 0);
-	  PROC_REG_MASK (&temp_proc_desc) |= (1 << RA_REGNUM);
-	  set_reg_offset (RA_REGNUM, sp + offset);
+	  PROC_REG_MASK (&temp_proc_desc) |= (1 << regnums->ra_regnum);
+	  set_reg_offset (regnums->ra_regnum, sp + offset);
 	}
       else if (inst == 0x673d)	/* move $s1, $sp */
 	{
@@ -2045,8 +2164,8 @@ mips16_heuristic_proc_desc (CORE_ADDR st
       offset = -4;
       if (entry_inst & 0x20)
 	{
-	  PROC_REG_MASK (&temp_proc_desc) |= 1 << RA_REGNUM;
-	  set_reg_offset (RA_REGNUM, sp + offset);
+	  PROC_REG_MASK (&temp_proc_desc) |= 1 << regnums->ra_regnum;
+	  set_reg_offset (regnums->ra_regnum, sp + offset);
 	  offset -= MIPS_SAVED_REGSIZE;
 	}
 
@@ -2066,6 +2185,8 @@ mips32_heuristic_proc_desc (CORE_ADDR st
 {
   CORE_ADDR cur_pc;
   CORE_ADDR frame_addr = 0;	/* Value of $r30. Used by gcc for frame-pointer */
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
 restart:
   temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
   memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
@@ -2114,7 +2235,7 @@ restart:
 	  /* Old gcc frame, r30 is virtual frame pointer.  */
 	  if ((long) low_word != PROC_FRAME_OFFSET (&temp_proc_desc))
 	    frame_addr = sp + low_word;
-	  else if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+	  else if (PROC_FRAME_REG (&temp_proc_desc) == regnums->sp_regnum)
 	    {
 	      unsigned alloca_adjust;
 	      PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2137,7 +2258,7 @@ restart:
       else if (inst == 0x03A0F021 || inst == 0x03a0f025 || inst == 0x03a0f02d)
 	{
 	  /* New gcc frame, virtual frame pointer is at r30 + frame_size.  */
-	  if (PROC_FRAME_REG (&temp_proc_desc) == SP_REGNUM)
+	  if (PROC_FRAME_REG (&temp_proc_desc) == regnums->sp_regnum)
 	    {
 	      unsigned alloca_adjust;
 	      PROC_FRAME_REG (&temp_proc_desc) = 30;
@@ -2167,9 +2288,10 @@ heuristic_proc_desc (CORE_ADDR start_pc,
 		     struct frame_info *next_frame, int cur_frame)
 {
   CORE_ADDR sp;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (cur_frame)
-    sp = read_next_frame_reg (next_frame, SP_REGNUM);
+    sp = read_next_frame_reg (next_frame, regnums->sp_regnum);
   else
     sp = 0;
 
@@ -2179,8 +2301,8 @@ heuristic_proc_desc (CORE_ADDR start_pc,
   temp_saved_regs = xrealloc (temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
   memset (temp_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS);
   PROC_LOW_ADDR (&temp_proc_desc) = start_pc;
-  PROC_FRAME_REG (&temp_proc_desc) = SP_REGNUM;
-  PROC_PC_REG (&temp_proc_desc) = RA_REGNUM;
+  PROC_FRAME_REG (&temp_proc_desc) = regnums->sp_regnum;
+  PROC_PC_REG (&temp_proc_desc) = regnums->ra_regnum;
 
   if (start_pc + 200 < limit_pc)
     limit_pc = start_pc + 200;
@@ -2455,6 +2577,7 @@ mips_frame_chain (struct frame_info *fra
   mips_extra_func_info_t proc_desc;
   CORE_ADDR tmp;
   CORE_ADDR saved_pc = DEPRECATED_FRAME_SAVED_PC (frame);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (saved_pc == 0 || inside_entry_file (saved_pc))
     return 0;
@@ -2482,7 +2605,7 @@ mips_frame_chain (struct frame_info *fra
   /* If no frame pointer and frame size is zero, we must be at end
      of stack (or otherwise hosed).  If we don't check frame size,
      we loop forever if we see a zero size frame.  */
-  if (PROC_FRAME_REG (proc_desc) == SP_REGNUM
+  if (PROC_FRAME_REG (proc_desc) == regnums->sp_regnum
       && PROC_FRAME_OFFSET (proc_desc) == 0
       /* The previous frame from a sigtramp frame might be frameless
 	 and have frame size zero.  */
@@ -2500,6 +2623,7 @@ mips_init_extra_frame_info (int fromleaf
 {
   int regnum;
   mips_extra_func_info_t proc_desc;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (get_frame_type (fci) == DUMMY_FRAME)
     return;
@@ -2528,7 +2652,8 @@ mips_init_extra_frame_info (int fromleaf
          interrupted by a signal at it's very start.  */
       if (get_frame_pc (fci) == PROC_LOW_ADDR (proc_desc)
 	  && !PROC_DESC_IS_DUMMY (proc_desc))
-	deprecated_update_frame_base_hack (fci, read_next_frame_reg (get_next_frame (fci), SP_REGNUM));
+	deprecated_update_frame_base_hack (fci,
+	  read_next_frame_reg (get_next_frame (fci), regnums->sp_regnum));
       else if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (fci), 0, 0))
 	/* Do not ``fix'' fci->frame.  It will have the value of the
            generic dummy frame's top-of-stack (since the draft
@@ -2557,25 +2682,28 @@ mips_init_extra_frame_info (int fromleaf
 	    {
 	      frame_saved_regs_zalloc (fci);
 	      memcpy (get_frame_saved_regs (fci), temp_saved_regs, SIZEOF_FRAME_SAVED_REGS);
-	      get_frame_saved_regs (fci)[PC_REGNUM]
-		= get_frame_saved_regs (fci)[RA_REGNUM];
+	      get_frame_saved_regs (fci)[regnums->pc_regnum]
+		= get_frame_saved_regs (fci)[regnums->ra_regnum];
 	      /* Set value of previous frame's stack pointer.  Remember that
 	         saved_regs[SP_REGNUM] is special in that it contains the
 		 value of the stack pointer register.  The other saved_regs
 		 values are addresses (in the inferior) at which a given
 		 register's value may be found.  */
-	      get_frame_saved_regs (fci)[SP_REGNUM] = get_frame_base (fci);
+	      get_frame_saved_regs (fci)[regnums->sp_regnum] = get_frame_base (fci);
 	    }
 	}
 
       /* hack: if argument regs are saved, guess these contain args */
       /* assume we can't tell how many args for now */
       get_frame_extra_info (fci)->num_args = -1;
-      for (regnum = MIPS_LAST_ARG_REGNUM; regnum >= A0_REGNUM; regnum--)
+      for (regnum = regnums->last_arg_regnum;
+           regnum >= regnums->a0_regnum;
+	   regnum--)
 	{
 	  if (PROC_REG_MASK (proc_desc) & (1 << regnum))
 	    {
-	      get_frame_extra_info (fci)->num_args = regnum - A0_REGNUM + 1;
+	      get_frame_extra_info (fci)->num_args
+	        = regnum - regnums->a0_regnum + 1;
 	      break;
 	    }
 	}
@@ -2678,6 +2806,7 @@ mips_eabi_push_arguments (int nargs,
   int argnum;
   int len = 0;
   int stack_offset = 0;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -2702,8 +2831,8 @@ mips_eabi_push_arguments (int nargs,
 			paddr_nz (sp), ROUND_UP (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
-  float_argreg = FPA0_REGNUM;
+  argreg = regnums->a0_regnum;
+  float_argreg = regnums->first_fp_arg_regnum;
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
   if (struct_return)
@@ -2772,7 +2901,7 @@ mips_eabi_push_arguments (int nargs,
          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)
+	  && float_argreg <= regnums->last_fp_arg_regnum)
 	{
 	  if (!FP_REGISTER_DOUBLE && len == 8)
 	    {
@@ -2832,7 +2961,7 @@ mips_eabi_push_arguments (int nargs,
 				    partial_len);
 
 	      /* Write this portion of the argument to the stack.  */
-	      if (argreg > MIPS_LAST_ARG_REGNUM
+	      if (argreg > regnums->last_arg_regnum
 		  || odd_sized_struct
 		  || fp_register_arg_p (typecode, arg_type))
 		{
@@ -2883,7 +3012,7 @@ mips_eabi_push_arguments (int nargs,
 	         arguments will not.  */
 	      /* Write this portion of the argument to a general
                  purpose register.  */
-	      if (argreg <= MIPS_LAST_ARG_REGNUM
+	      if (argreg <= regnums->last_arg_regnum
 		  && !fp_register_arg_p (typecode, arg_type))
 		{
 		  LONGEST regval = extract_unsigned_integer (val, partial_len);
@@ -2931,6 +3060,7 @@ mips_n32n64_push_arguments (int nargs,
   int argnum;
   int len = 0;
   int stack_offset = 0;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -2953,8 +3083,8 @@ mips_n32n64_push_arguments (int nargs,
 			paddr_nz (sp), ROUND_UP (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
-  float_argreg = FPA0_REGNUM;
+  argreg = regnums->a0_regnum;
+  float_argreg = regnums->first_fp_arg_regnum;
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
   if (struct_return)
@@ -2986,7 +3116,7 @@ mips_n32n64_push_arguments (int nargs,
       val = (char *) VALUE_CONTENTS (arg);
 
       if (fp_register_arg_p (typecode, arg_type)
-	  && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+	  && float_argreg <= regnums->last_fp_arg_regnum)
 	{
 	  /* This is a floating point value that fits entirely
 	     in a single register.  */
@@ -3029,7 +3159,7 @@ mips_n32n64_push_arguments (int nargs,
 				    partial_len);
 
 	      /* Write this portion of the argument to the stack.  */
-	      if (argreg > MIPS_LAST_ARG_REGNUM
+	      if (argreg > regnums->last_arg_regnum
 		  || odd_sized_struct
 		  || fp_register_arg_p (typecode, arg_type))
 		{
@@ -3076,7 +3206,7 @@ mips_n32n64_push_arguments (int nargs,
 	         arguments will not.  */
 	      /* Write this portion of the argument to a general
                  purpose register.  */
-	      if (argreg <= MIPS_LAST_ARG_REGNUM
+	      if (argreg <= regnums->last_arg_regnum
 		  && !fp_register_arg_p (typecode, arg_type))
 		{
 		  LONGEST regval = extract_unsigned_integer (val, partial_len);
@@ -3153,6 +3283,7 @@ mips_o32_push_arguments (int nargs,
   int argnum;
   int len = 0;
   int stack_offset = 0;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -3175,8 +3306,8 @@ mips_o32_push_arguments (int nargs,
 			paddr_nz (sp), ROUND_UP (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
-  float_argreg = FPA0_REGNUM;
+  argreg = regnums->a0_regnum;
+  float_argreg = regnums->first_fp_arg_regnum;
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
   if (struct_return)
@@ -3231,7 +3362,7 @@ mips_o32_push_arguments (int nargs,
          because those registers are normally skipped.  */
 
       if (fp_register_arg_p (typecode, arg_type)
-	  && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+	  && float_argreg <= regnums->last_fp_arg_regnum)
 	{
 	  if (!FP_REGISTER_DOUBLE && len == 8)
 	    {
@@ -3318,7 +3449,7 @@ mips_o32_push_arguments (int nargs,
 				    partial_len);
 
 	      /* Write this portion of the argument to the stack.  */
-	      if (argreg > MIPS_LAST_ARG_REGNUM
+	      if (argreg > regnums->last_arg_regnum
 		  || odd_sized_struct
 		  || fp_register_arg_p (typecode, arg_type))
 		{
@@ -3365,7 +3496,7 @@ mips_o32_push_arguments (int nargs,
 	         arguments will not.  */
 	      /* Write this portion of the argument to a general
                  purpose register.  */
-	      if (argreg <= MIPS_LAST_ARG_REGNUM
+	      if (argreg <= regnums->last_arg_regnum
 		  && !fp_register_arg_p (typecode, arg_type))
 		{
 		  LONGEST regval = extract_signed_integer (val, partial_len);
@@ -3413,7 +3544,7 @@ mips_o32_push_arguments (int nargs,
 
 		  /* Prevent subsequent floating point arguments from
 		     being passed in floating point registers.  */
-		  float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
+		  float_argreg = regnums->last_fp_arg_regnum + 1;
 		}
 
 	      len -= partial_len;
@@ -3452,6 +3583,7 @@ mips_o64_push_arguments (int nargs,
   int argnum;
   int len = 0;
   int stack_offset = 0;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   /* First ensure that the stack and structure return address (if any)
      are properly aligned.  The stack has to be at least 64-bit
@@ -3474,8 +3606,8 @@ mips_o64_push_arguments (int nargs,
 			paddr_nz (sp), ROUND_UP (len, 16));
 
   /* Initialize the integer and float register pointers.  */
-  argreg = A0_REGNUM;
-  float_argreg = FPA0_REGNUM;
+  argreg = regnums->a0_regnum;
+  float_argreg = regnums->first_fp_arg_regnum;
 
   /* The struct_return pointer occupies the first parameter-passing reg.  */
   if (struct_return)
@@ -3530,7 +3662,7 @@ mips_o64_push_arguments (int nargs,
          because those registers are normally skipped.  */
 
       if (fp_register_arg_p (typecode, arg_type)
-	  && float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
+	  && float_argreg <= regnums->last_fp_arg_regnum)
 	{
 	  if (!FP_REGISTER_DOUBLE && len == 8)
 	    {
@@ -3617,7 +3749,7 @@ mips_o64_push_arguments (int nargs,
 				    partial_len);
 
 	      /* Write this portion of the argument to the stack.  */
-	      if (argreg > MIPS_LAST_ARG_REGNUM
+	      if (argreg > regnums->last_arg_regnum
 		  || odd_sized_struct
 		  || fp_register_arg_p (typecode, arg_type))
 		{
@@ -3664,7 +3796,7 @@ mips_o64_push_arguments (int nargs,
 	         arguments will not.  */
 	      /* Write this portion of the argument to a general
                  purpose register.  */
-	      if (argreg <= MIPS_LAST_ARG_REGNUM
+	      if (argreg <= regnums->last_arg_regnum
 		  && !fp_register_arg_p (typecode, arg_type))
 		{
 		  LONGEST regval = extract_signed_integer (val, partial_len);
@@ -3712,7 +3844,7 @@ mips_o64_push_arguments (int nargs,
 
 		  /* Prevent subsequent floating point arguments from
 		     being passed in floating point registers.  */
-		  float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
+		  float_argreg = regnums->last_fp_arg_regnum + 1;
 		}
 
 	      len -= partial_len;
@@ -3740,9 +3872,11 @@ mips_o64_push_arguments (int nargs,
 static CORE_ADDR
 mips_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
 {
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
   /* Set the return address register to point to the entry
      point of the program, where a breakpoint lies in wait.  */
-  write_register (RA_REGNUM, CALL_DUMMY_ADDRESS ());
+  write_register (regnums->ra_regnum, CALL_DUMMY_ADDRESS ());
   return sp;
 }
 
@@ -3753,6 +3887,7 @@ mips_pop_frame (void)
   struct frame_info *frame = get_current_frame ();
   CORE_ADDR new_sp = get_frame_base (frame);
   mips_extra_func_info_t proc_desc;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame), 0, 0))
     {
@@ -3762,17 +3897,18 @@ mips_pop_frame (void)
     }
 
   proc_desc = get_frame_extra_info (frame)->proc_desc;
-  write_register (PC_REGNUM, DEPRECATED_FRAME_SAVED_PC (frame));
+  write_register (regnums->pc_regnum, DEPRECATED_FRAME_SAVED_PC (frame));
   if (get_frame_saved_regs (frame) == NULL)
     DEPRECATED_FRAME_INIT_SAVED_REGS (frame);
   for (regnum = 0; regnum < NUM_REGS; regnum++)
-    if (regnum != SP_REGNUM && regnum != PC_REGNUM
+    if (regnum != regnums->sp_regnum && regnum != regnums->pc_regnum
 	&& get_frame_saved_regs (frame)[regnum])
       {
 	/* Floating point registers must not be sign extended, 
-	   in case MIPS_SAVED_REGSIZE = 4 but sizeof (FP0_REGNUM) == 8.  */
+	   in case MIPS_SAVED_REGSIZE = 4 but
+	   REGISTER_RAW_SIZE (regnums->fp0_regnum)) == 8.  */
 
-	if (FP0_REGNUM <= regnum && regnum < FP0_REGNUM + 32)
+	if (regnums->fp0_regnum <= regnum && regnum < regnums->fplast_regnum)
 	  write_register (regnum,
 			  read_memory_unsigned_integer (get_frame_saved_regs (frame)[regnum],
 							MIPS_SAVED_REGSIZE));
@@ -3782,7 +3918,7 @@ mips_pop_frame (void)
 					       MIPS_SAVED_REGSIZE));
       }
 
-  write_register (SP_REGNUM, new_sp);
+  write_register (regnums->sp_regnum, new_sp);
   flush_cached_frames ();
 
   if (proc_desc && PROC_DESC_IS_DUMMY (proc_desc))
@@ -3807,14 +3943,14 @@ mips_pop_frame (void)
 
       xfree (pi_ptr);
 
-      write_register (HI_REGNUM,
+      write_register (regnums->hi_regnum,
 		      read_memory_integer (new_sp - 2 * MIPS_SAVED_REGSIZE,
 					   MIPS_SAVED_REGSIZE));
-      write_register (LO_REGNUM,
+      write_register (regnums->lo_regnum,
 		      read_memory_integer (new_sp - 3 * MIPS_SAVED_REGSIZE,
 					   MIPS_SAVED_REGSIZE));
       if (MIPS_FPU_TYPE != MIPS_FPU_NONE)
-	write_register (FCRCS_REGNUM,
+	write_register (regnums->fcrcs_regnum,
 			read_memory_integer (new_sp - 4 * MIPS_SAVED_REGSIZE,
 					     MIPS_SAVED_REGSIZE));
     }
@@ -3824,9 +3960,58 @@ static void
 mips_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, 
 		     struct value **args, struct type *type, int gcc_p)
 {
-  write_register(T9_REGNUM, fun);
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+  write_register(regnums->t9_regnum, fun);
+}
+
+/* mips register groups.  We add "raw" to the normal groups.  */
+
+static struct reggroup *mips_raw_reggroup;
+
+static void
+mips_init_reggroups (void)
+{
+  mips_raw_reggroup = reggroup_new ("raw", USER_REGGROUP);
+}
+
+static void
+mips_add_reggroups (struct gdbarch *gdbarch)
+{
+  reggroup_add (gdbarch, mips_raw_reggroup);
+  reggroup_add (gdbarch, general_reggroup);
+  reggroup_add (gdbarch, float_reggroup);
+  reggroup_add (gdbarch, all_reggroup);
+  reggroup_add (gdbarch, save_reggroup);
+  reggroup_add (gdbarch, restore_reggroup);
+  reggroup_add (gdbarch, vector_reggroup);
+  reggroup_add (gdbarch, system_reggroup);
+}
+
+static int
+mips_register_reggroup_p (struct gdbarch *gdbarch, int regno,
+                          struct reggroup *group)
+{
+  int raw_p, float_p;
+  const char *regname;
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+  
+  regname = REGISTER_NAME (regno);
+
+  raw_p = (strncmp (regname, "raw_", 4) == 0);
+  float_p = (cooked_regnums->fp0_regnum <= regno 
+             && regno <= cooked_regnums->fplast_regnum);
+
+  if (group == mips_raw_reggroup)
+    return raw_p;
+  if (group == float_reggroup)
+    return float_p;
+  if (group == general_reggroup)
+    return !float_p && !raw_p && *regname != '\0';
+  return default_register_reggroup_p (gdbarch, regno, group);
 }
 
+
 /* Floating point register management.
 
    Background: MIPS1 & 2 fp registers are 32 bits wide.  To support
@@ -3875,6 +4060,346 @@ mips_double_register_type (void)
     return builtin_type_ieee_double_little;
 }
 
+static int
+mips_is_floating_point_register (int regnum)
+{
+  return gdbarch_register_reggroup_p (current_gdbarch, regnum, float_reggroup);
+}
+
+static int
+mips_is_raw_register (int regnum)
+{
+  return gdbarch_register_reggroup_p (current_gdbarch, regnum, mips_raw_reggroup);
+}
+
+static int
+mips_is_general_purpose_register (int regnum)
+{
+  return gdbarch_register_reggroup_p (current_gdbarch, regnum, general_reggroup);
+}
+
+static struct type *
+build_mips_type_float_double_register_big (void)
+{
+  /* Construct a type for mips floating point registers.  The type we're
+     building is (roughly) this: */
+#if 0
+  union __gdb_mips_type_float_double_register_big
+  {
+    uint64_t i;
+    float f;
+    double d;
+  };
+#endif
+
+  struct type *t;
+  struct field *f;
+
+  t = init_composite_type ("__gdb_mips_type_float_double_register_big",
+                           TYPE_CODE_UNION);
+  append_composite_type_field (t, "i", builtin_type_uint64);
+  append_composite_type_field (t, "f", builtin_type_ieee_single_big);
+  f = &(TYPE_FIELDS (t))[TYPE_NFIELDS (t) - 1];
+  FIELD_BITPOS (f[0]) = 32;
+  append_composite_type_field (t, "d", builtin_type_ieee_double_big);
+
+  TYPE_NAME (t) = "mips_type_float_double_register_big";
+  return t;
+}
+
+static struct type *
+build_mips_type_float_double_register_little (void)
+{
+  /* Construct a type for mips floating point registers.  The type we're
+     building is (roughly) this: */
+#if 0
+  union __gdb_mips_type_float_double_register_little
+  {
+    uint64_t i;
+    float f;
+    double d;
+  };
+#endif
+
+  struct type *t;
+
+  t = init_composite_type ("__gdb_mips_type_float_double_register_little",
+                           TYPE_CODE_UNION);
+  append_composite_type_field (t, "i", builtin_type_uint64);
+  append_composite_type_field (t, "f", builtin_type_ieee_single_little);
+  append_composite_type_field (t, "d", builtin_type_ieee_double_little);
+  TYPE_NAME (t) = "mips_type_float_double_register_little";
+  return t;
+}
+
+static struct type *
+build_mips_type_float_single_register_big (void)
+{
+  /* Construct a type for mips single-precision floating point registers.
+     The type we're building is (roughly) this: */
+#if 0
+  union __gdb_mips_type_float_single_register_big
+  {
+    uint32_t i;
+    float f;
+  };
+#endif
+
+  struct type *t;
+
+  t = init_composite_type ("__gdb_mips_type_float_single_register_big",
+                           TYPE_CODE_UNION);
+  append_composite_type_field (t, "i", builtin_type_uint32);
+  append_composite_type_field (t, "f", builtin_type_ieee_single_big);
+  TYPE_NAME (t) = "mips_type_float_single_register_big";
+  return t;
+}
+
+static struct type *
+build_mips_type_float_single_register_little (void)
+{
+  /* Construct a type for mips single-precision floating point registers.
+     The type we're building is (roughly) this: */
+#if 0
+  union __gdb_mips_type_float_single_register_little
+  {
+    uint32_t i;
+    float f;
+  };
+#endif
+
+  struct type *t;
+
+  t = init_composite_type ("__gdb_mips_type_float_single_register_little",
+                           TYPE_CODE_UNION);
+  append_composite_type_field (t, "i", builtin_type_uint32);
+  append_composite_type_field (t, "f", builtin_type_ieee_single_little);
+  TYPE_NAME (t) = "mips_type_float_single_register_little";
+  return t;
+}
+
+/* Given a cooked regnum, find the corresponding raw regnum which should
+   be used to determine the value of the cooked register.  (Or vice versa
+   if writing to the cooked register...)  Returns the cooked register number
+   or -1 if there is no (known) corresponding raw register number.
+   
+   Note that this could be sped up by caching the results in the gdbarch_tdep
+   struct.  */
+
+static int
+cooked_regnum_to_raw_regnum (struct gdbarch *gdbarch, int cooked_regno)
+{
+  const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+  int raw_regno;
+
+  if (cooked_regnums->fp0_regnum <= cooked_regno
+      && cooked_regno <= cooked_regnums->fplast_regnum)
+    {
+      if (cooked_regnums->fplast_regnum - cooked_regnums->fp0_regnum + 1 == 16)
+	{
+	  raw_regno = 2 * (cooked_regno - cooked_regnums->fp0_regnum) 
+		    + raw_regnums->fp0_regnum;
+	}
+      else
+	{
+	  gdb_assert (cooked_regnums->fplast_regnum - cooked_regnums->fp0_regnum
+	              == raw_regnums->fplast_regnum - raw_regnums->fp0_regnum);
+
+	  raw_regno = raw_regnums->fp0_regnum 
+	              + (cooked_regno - cooked_regnums->fp0_regnum);
+	}
+    }
+  else if (cooked_regno == cooked_regnums->ps_regnum)
+    {
+      gdb_assert (raw_regnums->ps_regnum != -1);
+      raw_regno = raw_regnums->ps_regnum;
+    }
+  else if (cooked_regno == cooked_regnums->fcrcs_regnum)
+    {
+      gdb_assert (raw_regnums->fcrcs_regnum != -1);
+      raw_regno = raw_regnums->fcrcs_regnum;
+    }
+  else if (cooked_regno == cooked_regnums->fcrir_regnum)
+    {
+      gdb_assert (raw_regnums->fcrir_regnum != -1);
+      raw_regno = raw_regnums->fcrir_regnum;
+    }
+  else if (cooked_regnums->first_embed_regnum <= cooked_regno
+           && cooked_regno <= cooked_regnums->last_embed_regnum)
+    {
+      gdb_assert (raw_regnums->first_embed_regnum != -1
+                  && (cooked_regnums->last_embed_regnum 
+		          - cooked_regnums->first_embed_regnum
+		      == raw_regnums->last_embed_regnum
+		          - raw_regnums->first_embed_regnum));
+      raw_regno = raw_regnums->first_embed_regnum
+                  + (cooked_regno - cooked_regnums->first_embed_regnum);
+    }
+  else
+    {
+      raw_regno = -1;
+    }
+
+  return raw_regno;
+}
+
+static void
+mips_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                           int cooked_regno, void *buffer)
+{
+  const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+  int raw_regno;
+  char *raw_buf;
+  int raw_size, raw_offset, cooked_size;
+  
+
+  raw_regno = cooked_regnum_to_raw_regnum (gdbarch, cooked_regno);
+  if (raw_regno == -1)
+    {
+      warning ("mips_pseudo_register_read: Don't know how to read "
+               "register %d [%s]", cooked_regno, REGISTER_NAME (cooked_regno));
+      memset (buffer, 0, REGISTER_RAW_SIZE (cooked_regno));
+      return;
+    }
+
+  cooked_size = REGISTER_VIRTUAL_SIZE (cooked_regno);
+  raw_size = REGISTER_VIRTUAL_SIZE (raw_regno);
+  raw_buf = alloca (raw_size);
+
+  if (raw_regnums->fp0_regnum <= raw_regno
+      && raw_regno <= raw_regnums->fplast_regnum
+      && !FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+    {
+      int cooked_offset0, cooked_offset1;
+
+      gdb_assert (cooked_size == 8
+                  && cooked_regnums->fplast_regnum 
+		     - cooked_regnums->fp0_regnum + 1 == 16);
+
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+	{
+	  if (raw_size == 8)
+	    raw_offset = 4;
+	  else
+	    raw_offset = 0;
+	  cooked_offset0 = 4;
+	  cooked_offset1 = 0;
+	}
+      else
+	{
+	  raw_offset = 0;
+	  cooked_offset0 = 0;
+	  cooked_offset1 = 4;
+	}
+
+      regcache_raw_read (regcache, raw_regno, raw_buf);
+      memcpy ((char *) buffer + cooked_offset0, raw_buf + raw_offset, 4);
+      regcache_raw_read (regcache, raw_regno + 1, raw_buf);
+      memcpy ((char *) buffer + cooked_offset1, raw_buf + raw_offset, 4);
+    }
+  else
+    {
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+	raw_offset = raw_size - cooked_size;
+      else
+	raw_offset = 0;
+
+      gdb_assert (raw_offset >= 0);
+
+      regcache_raw_read (regcache, raw_regno, raw_buf);
+      memcpy (buffer, raw_buf + raw_offset, cooked_size);
+    }
+}
+
+static void
+mips_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+			    int cooked_regno, const void *buffer)
+{
+  const struct mips_regnums *raw_regnums = mips_raw_regnums (gdbarch);
+  const struct mips_regnums *cooked_regnums = mips_cooked_regnums (gdbarch);
+  int raw_regno;
+  char *raw_buf;
+  int raw_size, raw_offset, cooked_size;
+
+  raw_regno = cooked_regnum_to_raw_regnum (gdbarch, cooked_regno);
+  if (raw_regno == -1)
+    {
+      warning ("mips_pseudo_register_write: Don't know how to write "
+               "register %d [%s]", cooked_regno, REGISTER_NAME (cooked_regno));
+      return;
+    }
+
+  cooked_size = REGISTER_VIRTUAL_SIZE (cooked_regno);
+  raw_size = REGISTER_VIRTUAL_SIZE (raw_regno);
+  raw_buf = alloca (raw_size);
+
+  if (raw_regnums->fp0_regnum <= raw_regno
+      && raw_regno <= raw_regnums->fplast_regnum
+      && !FP_REGISTER_DOUBLE && MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
+    {
+      int cooked_offset0, cooked_offset1;
+
+      gdb_assert (cooked_size == 8
+                  && cooked_regnums->fplast_regnum 
+		     - cooked_regnums->fp0_regnum + 1 == 16);
+
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+	{
+	  if (raw_size == 8)
+	    raw_offset = 4;
+	  else
+	    raw_offset = 0;
+	  cooked_offset0 = 4;
+	  cooked_offset1 = 0;
+	}
+      else
+	{
+	  raw_offset = 0;
+	  cooked_offset0 = 0;
+	  cooked_offset1 = 4;
+	}
+
+      if (raw_size > cooked_size)
+	{
+	  /* Read entire contents of register that we're going to write
+	     to so as not to perturb the excess bits.  */
+	  regcache_raw_read (regcache, raw_regno, raw_buf);
+	}
+      memcpy (raw_buf + raw_offset, (char *) buffer + cooked_offset0, 4);
+      regcache_raw_write (regcache, raw_regno, raw_buf);
+
+      if (raw_size > cooked_size)
+	{
+	  /* Read entire contents of register that we're going to write
+	     to so as not to perturb the excess bits.  */
+	  regcache_raw_read (regcache, raw_regno + 1, raw_buf);
+	}
+      memcpy (raw_buf + raw_offset, (char *) buffer + cooked_offset1, 4);
+      regcache_raw_write (regcache, raw_regno + 1, raw_buf);
+    }
+  else
+    {
+      if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
+	raw_offset = raw_size - cooked_size;
+      else
+	raw_offset = 0;
+
+      gdb_assert (raw_offset >= 0);
+
+      if (raw_size > cooked_size)
+	{
+	  /* Read entire contents of register that we're going to write
+	     to so as not to perturb the excess bits.  */
+	  regcache_raw_read (regcache, raw_regno, raw_buf);
+	}
+
+      memcpy (raw_buf + raw_offset, buffer, cooked_size);
+      regcache_raw_write (regcache, raw_regno, raw_buf);
+    }
+}
+
 /* Copy a 32-bit single-precision value from the current frame
    into rare_buffer.  */
 
@@ -3912,35 +4437,8 @@ mips_read_fp_register_single (int regno,
 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 (deprecated_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);
-	}
-    }
+  if (!frame_register_read (deprecated_selected_frame, regno, rare_buffer))
+    error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
 }
 
 static void
@@ -3949,33 +4447,43 @@ mips_print_fp_register (int regnum)
   char *raw_buffer;
   double doub, flt1, flt2;	/* doubles extracted from raw hex data */
   int inv1, inv2, namelen;
+  const char *regname;
+
+  raw_buffer = (char *) alloca (REGISTER_RAW_SIZE (regnum));
 
-  raw_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
+  regname = REGISTER_NAME (regnum);
 
-  printf_filtered ("%s:", REGISTER_NAME (regnum));
-  printf_filtered ("%*s", 4 - (int) strlen (REGISTER_NAME (regnum)), "");
+  /* Print the register name.  */
+  printf_filtered ("%s:", regname);
+  printf_filtered ("%*s", 4 - (int) strlen (regname), "");
 
-  if (REGISTER_RAW_SIZE (regnum) == 4 || mips2_fp_compat ())
+  if (mips2_fp_compat ())
     {
-      /* 4-byte registers: Print hex and floating.  Also print even
-         numbered registers as doubles.  */
+      /* 4-byte registers:
+	  
+	 For even numbered registers in a double precision fpu, print
+	 the even and the next odd as 64-bit hex, print the single
+	 precision float value, and print the even/odd combo as a double.
+
+	 Otherwise, for single precision fpus, print the register both as
+	 32-bit hex and as a float.  */
+	 
       mips_read_fp_register_single (regnum, raw_buffer);
       flt1 = unpack_double (mips_float_register_type (), raw_buffer, &inv1);
 
-      print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w',
-                              gdb_stdout);
-
-      printf_filtered (" flt: ");
-      if (inv1)
-	printf_filtered (" <invalid float> ");
-      else
-	printf_filtered ("%-17.9g", flt1);
-
-      if (regnum % 2 == 0)
+      if (MIPS_FPU_TYPE == MIPS_FPU_DOUBLE)
 	{
 	  mips_read_fp_register_double (regnum, raw_buffer);
 	  doub = unpack_double (mips_double_register_type (), raw_buffer,
 	                        &inv2);
+	  print_scalar_formatted (raw_buffer, builtin_type_uint64, 'x', 'g',
+				  gdb_stdout);
+
+	  printf_filtered (" flt: ");
+	  if (inv1)
+	    printf_filtered (" <invalid float> ");
+	  else
+	    printf_filtered ("%-17.9g", flt1);
 
 	  printf_filtered (" dbl: ");
 	  if (inv2)
@@ -3983,6 +4491,18 @@ mips_print_fp_register (int regnum)
 	  else
 	    printf_filtered ("%-24.17g", doub);
 	}
+      else
+	{
+	  print_scalar_formatted (raw_buffer, builtin_type_uint32, 'x', 'w',
+				  gdb_stdout);
+
+	  printf_filtered (" flt: ");
+	  if (inv1)
+	    printf_filtered (" <invalid float> ");
+	  else
+	    printf_filtered ("%-17.9g", flt1);
+
+	}
     }
   else
     {
@@ -4017,7 +4537,7 @@ mips_print_register (int regnum, int all
   char *raw_buffer = alloca (MAX_REGISTER_RAW_SIZE);
   int offset;
 
-  if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
+  if (mips_is_floating_point_register (regnum))
     {
       mips_print_fp_register (regnum);
       return;
@@ -4047,7 +4567,7 @@ mips_print_register (int regnum, int all
     offset = 0;
 
   print_scalar_formatted (raw_buffer + offset,
-			  REGISTER_VIRTUAL_TYPE (regnum),
+			  register_type (current_gdbarch, regnum),
 			  'x', 0, gdb_stdout);
 }
 
@@ -4057,6 +4577,15 @@ mips_print_register (int regnum, int all
 static int
 do_fp_register_row (int regnum)
 {
+  const char * regname;
+  
+  regname = REGISTER_NAME (regnum);
+  if (regname == NULL || *regname == '\0')
+    {
+      /* Don't print *anything* for the no-name registers.  */
+      return regnum + 1;
+    }
+
   printf_filtered (" ");
   mips_print_fp_register (regnum);
   printf_filtered ("\n");
@@ -4074,7 +4603,7 @@ do_gp_register_row (int regnum)
   int ncols = (MIPS_REGSIZE == 8 ? 4 : 8);	/* display cols per row */
   int col, byte;
   int start_regnum = regnum;
-  int numregs = NUM_REGS;
+  int numregs = NUM_REGS + NUM_PSEUDO_REGS;
 
 
   /* For GP registers, we print a separate row of names above the vals */
@@ -4083,8 +4612,8 @@ do_gp_register_row (int regnum)
     {
       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 */
+      if (!mips_is_general_purpose_register (regnum))
+	continue;		/* end the row: reached FP register */
       printf_filtered (MIPS_REGSIZE == 8 ? "%17s" : "%9s",
 		       REGISTER_NAME (regnum));
       col++;
@@ -4098,8 +4627,8 @@ do_gp_register_row (int regnum)
     {
       if (*REGISTER_NAME (regnum) == '\0')
 	continue;		/* unused register */
-      if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
-	break;			/* end row: reached FP register */
+      if (!mips_is_general_purpose_register (regnum))
+	continue;
       /* OK: get the data in raw format.  */
       if (!frame_register_read (deprecated_selected_frame, regnum, raw_buffer))
 	error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
@@ -4142,16 +4671,28 @@ mips_do_registers_info (int regnum, int 
   else
     /* do all (or most) registers */
     {
+      /* Do the general purpose registers.  */
       regnum = 0;
-      while (regnum < NUM_REGS)
+      while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
 	{
-	  if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
-	    if (fpregs)		/* true for "INFO ALL-REGISTERS" command */
-	      regnum = do_fp_register_row (regnum);	/* FP regs */
-	    else
-	      regnum += MIPS_NUMREGS;	/* skip floating point regs */
-	  else
+	  if (mips_is_general_purpose_register (regnum))
 	    regnum = do_gp_register_row (regnum);	/* GP (int) regs */
+	  else
+	    regnum++;
+	}
+
+      /* Do the floating point registers if requested, i.e, for
+         "info all-registers".  */
+      if (fpregs)		/* true for "INFO ALL-REGISTERS" command */
+	{
+	  regnum = 0;
+	  while (regnum < NUM_REGS + NUM_PSEUDO_REGS)
+	    {
+	      if (mips_is_floating_point_register (regnum))
+		  regnum = do_fp_register_row (regnum);	/* FP regs */
+		else
+		  regnum++;
+	    }
 	}
     }
 }
@@ -4432,6 +4973,7 @@ return_value_location (struct type *valt
 		       struct return_value_word *lo)
 {
   int len = TYPE_LENGTH (valtype);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (TYPE_CODE (valtype) == TYPE_CODE_FLT
       && ((MIPS_FPU_TYPE == MIPS_FPU_DOUBLE && (len == 4 || len == 8))
@@ -4444,11 +4986,11 @@ return_value_location (struct type *valt
 	  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)
+			     && REGISTER_RAW_SIZE (regnums->fp0_regnum) == 8)
 			    ? 4 : 0);
 	  hi->reg_offset = lo->reg_offset;
-	  lo->reg = FP0_REGNUM + 0;
-	  hi->reg = FP0_REGNUM + 1;
+	  lo->reg = regnums->fp0_regnum + 0;
+	  hi->reg = regnums->fp0_regnum + 1;
 	  lo->len = 4;
 	  hi->len = 4;
 	}
@@ -4457,10 +4999,10 @@ return_value_location (struct type *valt
 	  /* The floating point value fits in a single floating-point
 	     register. */
 	  lo->reg_offset = ((TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
-			     && REGISTER_RAW_SIZE (FP0_REGNUM) == 8
+			     && REGISTER_RAW_SIZE (regnums->fp0_regnum) == 8
 			     && len == 4)
 			    ? 4 : 0);
-	  lo->reg = FP0_REGNUM;
+	  lo->reg = regnums->fp0_regnum;
 	  lo->len = len;
 	  lo->buf_offset = 0;
 	  hi->len = 0;
@@ -4622,6 +5164,8 @@ mips_o32_xfer_return_value (struct type 
 			    bfd_byte *in, const bfd_byte *out)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && TYPE_LENGTH (type) == 4
       && tdep->mips_fpu_type != MIPS_FPU_NONE)
@@ -4630,7 +5174,7 @@ mips_o32_xfer_return_value (struct type 
          least significant part of FP0.  */
       if (mips_debug)
 	fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
-      mips_xfer_register (regcache, FP0_REGNUM, TYPE_LENGTH (type),
+      mips_xfer_register (regcache, regnums->fp0_regnum, TYPE_LENGTH (type),
 			  TARGET_BYTE_ORDER, in, out, 0);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_FLT
@@ -4645,15 +5189,15 @@ mips_o32_xfer_return_value (struct type 
       switch (TARGET_BYTE_ORDER)
 	{
 	case BFD_ENDIAN_LITTLE:
-	  mips_xfer_register (regcache, FP0_REGNUM + 0, 4,
+	  mips_xfer_register (regcache, regnums->fp0_regnum + 0, 4,
 			      TARGET_BYTE_ORDER, in, out, 0);
-	  mips_xfer_register (regcache, FP0_REGNUM + 1, 4,
+	  mips_xfer_register (regcache, regnums->fp0_regnum + 1, 4,
 			      TARGET_BYTE_ORDER, in, out, 4);
 	  break;
 	case BFD_ENDIAN_BIG:
-	  mips_xfer_register (regcache, FP0_REGNUM + 1, 4,
+	  mips_xfer_register (regcache, regnums->fp0_regnum + 1, 4,
 			      TARGET_BYTE_ORDER, in, out, 0);
-	  mips_xfer_register (regcache, FP0_REGNUM + 0, 4,
+	  mips_xfer_register (regcache, regnums->fp0_regnum + 0, 4,
 			      TARGET_BYTE_ORDER, in, out, 4);
 	  break;
 	default:
@@ -4680,7 +5224,7 @@ mips_o32_xfer_return_value (struct type 
       bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
       int regnum;
       int field;
-      for (field = 0, regnum = FP0_REGNUM;
+      for (field = 0, regnum = regnums->fp0_regnum;
 	   field < TYPE_NFIELDS (type);
 	   field++, regnum += 2)
 	{
@@ -4702,7 +5246,7 @@ mips_o32_xfer_return_value (struct type 
          mips_xfer_lower.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = regnums->v0_regnum;
 	   offset < TYPE_LENGTH (type);
 	   offset += REGISTER_RAW_SIZE (regnum), regnum++)
 	{
@@ -4724,7 +5268,7 @@ mips_o32_xfer_return_value (struct type 
          the ISA.  mips_stack_argsize controls this.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = regnums->v0_regnum;
 	   offset < TYPE_LENGTH (type);
 	   offset += mips_stack_argsize (), regnum++)
 	{
@@ -4763,6 +5307,8 @@ mips_n32n64_xfer_return_value (struct ty
 			       bfd_byte *in, const bfd_byte *out)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (TYPE_CODE (type) == TYPE_CODE_FLT
       && tdep->mips_fpu_type != MIPS_FPU_NONE)
     {
@@ -4770,7 +5316,7 @@ mips_n32n64_xfer_return_value (struct ty
          of FP0.  */
       if (mips_debug)
 	fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
-      mips_xfer_register (regcache, FP0_REGNUM, TYPE_LENGTH (type),
+      mips_xfer_register (regcache, regnums->fp0_regnum, TYPE_LENGTH (type),
 			  TARGET_BYTE_ORDER, in, out, 0);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_STRUCT
@@ -4792,7 +5338,7 @@ mips_n32n64_xfer_return_value (struct ty
       bfd_byte *reg = alloca (MAX_REGISTER_RAW_SIZE);
       int regnum;
       int field;
-      for (field = 0, regnum = FP0_REGNUM;
+      for (field = 0, regnum = regnums->fp0_regnum;
 	   field < TYPE_NFIELDS (type);
 	   field++, regnum += 2)
 	{
@@ -4812,7 +5358,7 @@ mips_n32n64_xfer_return_value (struct ty
          mips_xfer_lower.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = regnums->v0_regnum;
 	   offset < TYPE_LENGTH (type);
 	   offset += REGISTER_RAW_SIZE (regnum), regnum++)
 	{
@@ -4832,7 +5378,7 @@ mips_n32n64_xfer_return_value (struct ty
          justified.  */
       int offset;
       int regnum;
-      for (offset = 0, regnum = V0_REGNUM;
+      for (offset = 0, regnum = regnums->v0_regnum;
 	   offset < TYPE_LENGTH (type);
 	   offset += REGISTER_RAW_SIZE (regnum), regnum++)
 	{
@@ -4875,9 +5421,10 @@ mips_extract_struct_value_address (struc
   /* FIXME: This will only work at random.  The caller passes the
      struct_return address in V0, but it is not preserved.  It may
      still be there, or this may be a random value.  */
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
   LONGEST val;
 
-  regcache_cooked_read_signed (regcache, V0_REGNUM, &val);
+  regcache_cooked_read_signed (regcache, regnums->v0_regnum, &val);
   return val;
 }
 
@@ -5020,7 +5567,7 @@ mips_set_processor_type (char *str)
       if (strcasecmp (str, mips_processor_type_table[i].name) == 0)
 	{
 	  mips_processor_type = str;
-	  mips_processor_reg_names = mips_processor_type_table[i].regnames;
+	  mips_embed_reg_names = mips_processor_type_table[i].regnames;
 	  return 1;
 	  /* FIXME tweak fpu flag too */
 	}
@@ -5036,8 +5583,12 @@ char *
 mips_read_processor_type (void)
 {
   CORE_ADDR prid;
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+  if (regnums->prid_regnum < 0)
+    return NULL;
 
-  prid = read_register (PRID_REGNUM);
+  prid = read_register (regnums->prid_regnum);
 
   if ((prid & ~0xf) == 0x700)
     return savestring ("r3041", strlen ("r3041"));
@@ -5196,6 +5747,7 @@ mips_skip_stub (CORE_ADDR pc)
 {
   char *name;
   CORE_ADDR start_addr;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   /* Find the starting address and name of the function containing the PC.  */
   if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
@@ -5205,7 +5757,7 @@ mips_skip_stub (CORE_ADDR pc)
      target PC is in $31 ($ra).  */
   if (strcmp (name, "__mips16_ret_sf") == 0
       || strcmp (name, "__mips16_ret_df") == 0)
-    return read_signed_register (RA_REGNUM);
+    return read_signed_register (regnums->ra_regnum);
 
   if (strncmp (name, "__mips16_call_stub_", 19) == 0)
     {
@@ -5426,7 +5978,9 @@ mips_get_saved_register (char *raw_buffe
 static CORE_ADDR
 mips_saved_pc_after_call (struct frame_info *frame)
 {
-  return read_signed_register (RA_REGNUM);
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
+  return read_signed_register (regnums->ra_regnum);
 }
 
 
@@ -5436,14 +5990,21 @@ mips_saved_pc_after_call (struct frame_i
 static int
 mips_stab_reg_to_regnum (int num)
 {
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
   if (num >= 0 && num < 32)
     return num;
   else if (num >= 38 && num < 70)
-    return num + FP0_REGNUM - 38;
+    {
+      if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+	return ((num - 38) / 2) + regnums->fp0_regnum;
+      else
+	return num - 38 + regnums->fp0_regnum;
+    }
   else if (num == 70)
-    return HI_REGNUM;
+    return regnums->hi_regnum;
   else if (num == 71)
-    return LO_REGNUM;
+    return regnums->lo_regnum;
   else
     {
       /* This will hopefully (eventually) provoke a warning.  Should
@@ -5458,14 +6019,21 @@ mips_stab_reg_to_regnum (int num)
 static int
 mips_dwarf_dwarf2_ecoff_reg_to_regnum (int num)
 {
+  const struct mips_regnums *regnums = mips_cooked_regnums (current_gdbarch);
+
   if (num >= 0 && num < 32)
     return num;
   else if (num >= 32 && num < 64)
-    return num + FP0_REGNUM - 32;
+    {
+      if (regnums->fplast_regnum - regnums->fp0_regnum + 1 == 16)
+	return ((num - 32) / 2) + regnums->fp0_regnum;
+      else
+	return num - 32 + regnums->fp0_regnum;
+    }
   else if (num == 64)
-    return HI_REGNUM;
+    return regnums->hi_regnum;
   else if (num == 65)
-    return LO_REGNUM;
+    return regnums->lo_regnum;
   else
     {
       /* This will hopefully (eventually) provoke a warning.  Should
@@ -5540,6 +6108,7 @@ mips_gdbarch_init (struct gdbarch_info i
   struct gdbarch_tdep *tdep;
   int elf_flags;
   enum mips_abi mips_abi, found_abi, wanted_abi;
+  int first_pseudo_regnum, next_available_pseudo_regnum;
 
   /* Reset the disassembly info, in case it was set to something
      non-default.  */
@@ -5692,7 +6261,6 @@ mips_gdbarch_init (struct gdbarch_info i
   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);
   set_gdbarch_deprecated_max_register_raw_size (gdbarch, 8);
   set_gdbarch_deprecated_max_register_virtual_size (gdbarch, 8);
   tdep->found_abi = found_abi;
@@ -5702,9 +6270,54 @@ mips_gdbarch_init (struct gdbarch_info i
 					mips_elf_make_msymbol_special);
 
   if (info.osabi == GDB_OSABI_IRIX)
-    set_gdbarch_num_regs (gdbarch, 71);
+    {
+      set_gdbarch_num_regs (gdbarch, 71);
+      first_pseudo_regnum = 71;
+      next_available_pseudo_regnum = 71;
+
+      tdep->raw_regnums.fp0_regnum = 32;
+      tdep->raw_regnums.pc_regnum = 64;
+      tdep->raw_regnums.cause_regnum = 65;
+      tdep->raw_regnums.badvaddr_regnum = 66;
+      tdep->raw_regnums.hi_regnum = 67;
+      tdep->raw_regnums.lo_regnum = 68;
+      tdep->raw_regnums.fcrcs_regnum = 69;
+      tdep->raw_regnums.fcrir_regnum = 70;
+
+      tdep->raw_regnums.ps_regnum = -1;
+      tdep->raw_regnums.first_embed_regnum = -1;
+      tdep->raw_regnums.last_embed_regnum = -1;
+      tdep->raw_regnums.prid_regnum = -1;
+    }
   else
-    set_gdbarch_num_regs (gdbarch, 90);
+    {
+      set_gdbarch_num_regs (gdbarch, 90);
+      first_pseudo_regnum = 90;
+      next_available_pseudo_regnum = 90;
+
+      tdep->raw_regnums.fp0_regnum = 38;
+      tdep->raw_regnums.ps_regnum = 32;
+      tdep->raw_regnums.hi_regnum = 34;
+      tdep->raw_regnums.lo_regnum = 33;
+      tdep->raw_regnums.badvaddr_regnum = 35;
+      tdep->raw_regnums.cause_regnum = 36;
+      tdep->raw_regnums.pc_regnum = 37;
+      tdep->raw_regnums.fcrcs_regnum = 70;
+      tdep->raw_regnums.fcrir_regnum = 71;
+      tdep->raw_regnums.first_embed_regnum = 74;
+      tdep->raw_regnums.last_embed_regnum = 89;
+      tdep->raw_regnums.prid_regnum = 89;
+    }
+
+  tdep->raw_regnums.fplast_regnum = tdep->raw_regnums.fp0_regnum + 31;
+  tdep->raw_regnums.first_fp_arg_regnum = tdep->raw_regnums.fp0_regnum + 12;
+
+  tdep->raw_regnums.zero_regnum = 0;
+  tdep->raw_regnums.v0_regnum = 2;
+  tdep->raw_regnums.a0_regnum = 4;
+  tdep->raw_regnums.t9_regnum = 25;
+  tdep->raw_regnums.sp_regnum = 29;
+  tdep->raw_regnums.ra_regnum = 31;
 
   switch (mips_abi)
     {
@@ -5715,8 +6328,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 4 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 4 - 1;
       tdep->gdb_target_is_mips64 = 0;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
@@ -5734,8 +6347,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 4 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 4 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 4 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 4 - 1;
       tdep->gdb_target_is_mips64 = 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
@@ -5753,8 +6366,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 4;
       tdep->mips_default_stack_argsize = 4;
       tdep->mips_fp_register_double = 0;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
       tdep->gdb_target_is_mips64 = 0;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
@@ -5772,8 +6385,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
       tdep->gdb_target_is_mips64 = 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 64);
@@ -5791,8 +6404,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
       tdep->gdb_target_is_mips64 = 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 32);
@@ -5810,8 +6423,8 @@ mips_gdbarch_init (struct gdbarch_info i
       tdep->mips_default_saved_regsize = 8;
       tdep->mips_default_stack_argsize = 8;
       tdep->mips_fp_register_double = 1;
-      tdep->mips_last_arg_regnum = A0_REGNUM + 8 - 1;
-      tdep->mips_last_fp_arg_regnum = FPA0_REGNUM + 8 - 1;
+      tdep->raw_regnums.last_arg_regnum = tdep->raw_regnums.a0_regnum + 8 - 1;
+      tdep->raw_regnums.last_fp_arg_regnum = tdep->raw_regnums.first_fp_arg_regnum + 8 - 1;
       tdep->gdb_target_is_mips64 = 1;
       tdep->default_mask_address_p = 0;
       set_gdbarch_long_bit (gdbarch, 64);
@@ -5914,11 +6527,6 @@ mips_gdbarch_init (struct gdbarch_info i
   set_gdbarch_deprecated_push_return_address (gdbarch, mips_push_return_address);
   set_gdbarch_frame_align (gdbarch, mips_frame_align);
   set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
-  set_gdbarch_register_convertible (gdbarch, mips_register_convertible);
-  set_gdbarch_register_convert_to_virtual (gdbarch, 
-					   mips_register_convert_to_virtual);
-  set_gdbarch_register_convert_to_raw (gdbarch, 
-				       mips_register_convert_to_raw);
 
   set_gdbarch_deprecated_frame_chain (gdbarch, mips_frame_chain);
   set_gdbarch_frameless_function_invocation (gdbarch, 
@@ -5942,9 +6550,7 @@ mips_gdbarch_init (struct gdbarch_info i
 
   set_gdbarch_function_start_offset (gdbarch, 0);
 
-  /* There are MIPS targets which do not yet use this since they still
-     define REGISTER_VIRTUAL_TYPE.  */
-  set_gdbarch_register_virtual_type (gdbarch, mips_register_virtual_type);
+  set_gdbarch_register_type (gdbarch, mips_register_type);
   set_gdbarch_register_virtual_size (gdbarch, generic_register_size);
 
   set_gdbarch_deprecated_do_registers_info (gdbarch, mips_do_registers_info);
@@ -5962,6 +6568,72 @@ mips_gdbarch_init (struct gdbarch_info i
   set_gdbarch_in_solib_call_trampoline (gdbarch, mips_in_call_stub);
   set_gdbarch_in_solib_return_trampoline (gdbarch, mips_in_return_stub);
 
+  /* Add mips register groups.  */
+  mips_add_reggroups (gdbarch);
+  set_gdbarch_register_reggroup_p (gdbarch, mips_register_reggroup_p);
+
+  /* For many registers, the cooked and raw register numbers are the same.  */
+  tdep->cooked_regnums = tdep->raw_regnums;
+
+  /* For those that aren't the same, initialize the cooked register numbers.  */
+  if (!tdep->mips_fp_register_double &&
+      tdep->mips_fpu_type == MIPS_FPU_DOUBLE)
+    {
+      /* There are 16 64-bit cooked floating point registers.  */
+      tdep->cooked_regnums.fp0_regnum = next_available_pseudo_regnum;
+      next_available_pseudo_regnum += 16;
+      tdep->cooked_regnums.fplast_regnum = next_available_pseudo_regnum - 1;
+    }
+  else if (tdep->mips_fpu_type == MIPS_FPU_NONE)
+    {
+      /* There aren't any cooked floating point registers.  */
+      tdep->cooked_regnums.fp0_regnum = -1;
+      tdep->cooked_regnums.fplast_regnum = -1;
+    }
+  else
+    {
+      /* There are 32 floating (cooked) point registers.  */
+      tdep->cooked_regnums.fp0_regnum = next_available_pseudo_regnum;
+      next_available_pseudo_regnum += 32;
+      tdep->cooked_regnums.fplast_regnum = next_available_pseudo_regnum - 1;
+    }
+
+  if (tdep->raw_regnums.ps_regnum != -1)
+    tdep->cooked_regnums.ps_regnum = next_available_pseudo_regnum++;
+
+  if (tdep->raw_regnums.fcrcs_regnum != -1)
+    tdep->cooked_regnums.fcrcs_regnum = next_available_pseudo_regnum++;
+
+  if (tdep->raw_regnums.fcrir_regnum != -1)
+    tdep->cooked_regnums.fcrir_regnum = next_available_pseudo_regnum++;
+
+  if (tdep->raw_regnums.first_embed_regnum != -1)
+    {
+      tdep->cooked_regnums.first_embed_regnum = next_available_pseudo_regnum;
+      next_available_pseudo_regnum += (tdep->raw_regnums.last_embed_regnum 
+				       - tdep->raw_regnums.first_embed_regnum);
+      tdep->cooked_regnums.last_embed_regnum = next_available_pseudo_regnum++;
+
+      tdep->cooked_regnums.prid_regnum 
+	= tdep->cooked_regnums.first_embed_regnum
+	  + (tdep->raw_regnums.prid_regnum 
+	     - tdep->raw_regnums.first_embed_regnum);
+    }
+
+  /* Set up the pseudo reg count and the pseudo register reader/writer.  */
+  if (next_available_pseudo_regnum > first_pseudo_regnum)
+    {
+      set_gdbarch_num_pseudo_regs (gdbarch, next_available_pseudo_regnum 
+                                            - first_pseudo_regnum);
+      set_gdbarch_pseudo_register_read (gdbarch, mips_pseudo_register_read);
+      set_gdbarch_pseudo_register_write (gdbarch, mips_pseudo_register_write);
+    }
+
+  /* Set the sp and pc regnums to the cooked numbers.  */
+
+  set_gdbarch_sp_regnum (gdbarch, tdep->cooked_regnums.sp_regnum);
+  set_gdbarch_pc_regnum (gdbarch, tdep->cooked_regnums.pc_regnum);
+
   return gdbarch;
 }
 
@@ -6010,6 +6682,56 @@ show_mips_abi (char *ignore_args, int fr
 }
 
 static void
+mips_dump_regnums (const char *prefix, const struct mips_regnums *regnums,
+                   struct ui_file *file)
+{
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "fp0_regnum", regnums->fp0_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "fplast_regnum", regnums->fplast_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "last_arg_regnum", regnums->last_arg_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "first_fp_arg_regnum", regnums->first_fp_arg_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "last_fp_arg_regnum", regnums->last_fp_arg_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "zero_regnum", regnums->zero_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "v0_regnum", regnums->v0_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "a0_regnum", regnums->a0_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "t9_regnum", regnums->t9_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "sp_regnum", regnums->sp_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "ra_regnum", regnums->ra_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "ps_regnum", regnums->ps_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "hi_regnum", regnums->hi_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "lo_regnum", regnums->lo_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "badvaddr_regnum", regnums->badvaddr_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "cause_regnum", regnums->cause_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "pc_regnum", regnums->pc_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "fcrcs_regnum", regnums->fcrcs_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "fcrir_regnum", regnums->fcrir_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "first_embed_regnum", regnums->first_embed_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "last_embed_regnum", regnums->last_embed_regnum);
+  fprintf_unfiltered (file, "%s%s = %d\n", prefix,
+                      "prid_regnum", regnums->prid_regnum);
+}
+
+static void
 mips_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
@@ -6055,6 +6777,10 @@ mips_dump_tdep (struct gdbarch *current_
 			  "mips_dump_tdep: mips_mask_address_p() %d (default %d)\n",
 			  mips_mask_address_p (),
 			  tdep->default_mask_address_p);
+      mips_dump_regnums ("mips_dump_tdep: tdep->cooked_regnums.",
+                         &tdep->cooked_regnums, file);
+      mips_dump_regnums ("mips_dump_tdep: tdep->raw_regnums.",
+                         &tdep->raw_regnums, file);
     }
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: FP_REGISTER_DOUBLE = %d\n",
@@ -6070,10 +6796,6 @@ mips_dump_tdep (struct gdbarch *current_
 		      "mips_dump_tdep: MIPS_EABI = %d\n",
 		      MIPS_EABI);
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: MIPS_LAST_FP_ARG_REGNUM = %d (%d regs)\n",
-		      MIPS_LAST_FP_ARG_REGNUM,
-		      MIPS_LAST_FP_ARG_REGNUM - FPA0_REGNUM + 1);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: MIPS_FPU_TYPE = %d (%s)\n",
 		      MIPS_FPU_TYPE,
 		      (MIPS_FPU_TYPE == MIPS_FPU_NONE ? "none"
@@ -6096,50 +6818,26 @@ mips_dump_tdep (struct gdbarch *current_
 		      "mips_dump_tdep: MIPS_REGSIZE = %d\n",
 		      MIPS_REGSIZE);
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: A0_REGNUM = %d\n",
-		      A0_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: ADDR_BITS_REMOVE # %s\n",
 		      XSTRING (ADDR_BITS_REMOVE(ADDR)));
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: ATTACH_DETACH # %s\n",
 		      XSTRING (ATTACH_DETACH));
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: BADVADDR_REGNUM = %d\n",
-		      BADVADDR_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: BIG_BREAKPOINT = delete?\n");
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: CAUSE_REGNUM = %d\n",
-		      CAUSE_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: DWARF_REG_TO_REGNUM # %s\n",
 		      XSTRING (DWARF_REG_TO_REGNUM (REGNUM)));
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: ECOFF_REG_TO_REGNUM # %s\n",
 		      XSTRING (ECOFF_REG_TO_REGNUM (REGNUM)));
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: FCRCS_REGNUM = %d\n",
-		      FCRCS_REGNUM);
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: FCRIR_REGNUM = %d\n",
-		      FCRIR_REGNUM);
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: FIRST_EMBED_REGNUM = %d\n",
-		      FIRST_EMBED_REGNUM);
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: FPA0_REGNUM = %d\n",
-		      FPA0_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: GDB_TARGET_IS_MIPS64 = %d\n",
 		      GDB_TARGET_IS_MIPS64);
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: HAVE_NONSTEPPABLE_WATCHPOINT # %s\n",
 		      XSTRING (HAVE_NONSTEPPABLE_WATCHPOINT));
   fprintf_unfiltered (file,
-		      "mips_dump_tdep:  HI_REGNUM = %d\n",
-		      HI_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: IDT_BIG_BREAKPOINT = delete?\n");
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: IDT_LITTLE_BREAKPOINT = delete?\n");
@@ -6155,13 +6853,7 @@ mips_dump_tdep (struct gdbarch *current_
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: IS_MIPS16_ADDR = FIXME!\n");
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: LAST_EMBED_REGNUM = %d\n",
-		      LAST_EMBED_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: LITTLE_BREAKPOINT = delete?\n");
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: LO_REGNUM = %d\n",
-		      LO_REGNUM);
 #ifdef MACHINE_CPROC_FP_OFFSET
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: MACHINE_CPROC_FP_OFFSET = %d\n",
@@ -6194,15 +6886,9 @@ mips_dump_tdep (struct gdbarch *current_
 		      "mips_dump_tdep: MIPS_INSTLEN = %d\n",
 		      MIPS_INSTLEN);
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: MIPS_LAST_ARG_REGNUM = %d (%d regs)\n",
-		      MIPS_LAST_ARG_REGNUM,
-		      MIPS_LAST_ARG_REGNUM - A0_REGNUM + 1);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: MIPS_NUMREGS = %d\n",
 		      MIPS_NUMREGS);
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: MIPS_REGISTER_NAMES = delete?\n");
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: MIPS_SAVED_REGSIZE = %d\n",
 		      MIPS_SAVED_REGSIZE);
   fprintf_unfiltered (file,
@@ -6214,9 +6900,6 @@ mips_dump_tdep (struct gdbarch *current_
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: PMON_LITTLE_BREAKPOINT = delete?\n");
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: PRID_REGNUM = %d\n",
-		      PRID_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: PRINT_EXTRA_FRAME_INFO # %s\n",
 		      XSTRING (PRINT_EXTRA_FRAME_INFO (FRAME)));
   fprintf_unfiltered (file,
@@ -6244,12 +6927,6 @@ mips_dump_tdep (struct gdbarch *current_
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: PROC_SYMBOL = function?\n");
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: PS_REGNUM = %d\n",
-		      PS_REGNUM);
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: RA_REGNUM = %d\n",
-		      RA_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: REGISTER_CONVERT_FROM_TYPE # %s\n",
 		      XSTRING (REGISTER_CONVERT_FROM_TYPE (REGNUM, VALTYPE, RAW_BUFFER)));
   fprintf_unfiltered (file,
@@ -6323,9 +7000,6 @@ mips_dump_tdep (struct gdbarch *current_
 		      "mips_dump_tdep: STOPPED_BY_WATCHPOINT # %s\n",
 		      XSTRING (STOPPED_BY_WATCHPOINT (WS)));
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: T9_REGNUM = %d\n",
-		      T9_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: TABULAR_REGISTER_OUTPUT = used?\n");
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: TARGET_CAN_USE_HARDWARE_WATCHPOINT # %s\n",
@@ -6360,14 +7034,6 @@ mips_dump_tdep (struct gdbarch *current_
 #endif
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: UNMAKE_MIPS16_ADDR = function?\n");
-#ifdef UNUSED_REGNUM
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: UNUSED_REGNUM = %d\n",
-		      UNUSED_REGNUM);
-#endif
-  fprintf_unfiltered (file,
-		      "mips_dump_tdep: V0_REGNUM = %d\n",
-		      V0_REGNUM);
   fprintf_unfiltered (file,
 		      "mips_dump_tdep: VM_MIN_ADDRESS = %ld\n",
 		      (long) VM_MIN_ADDRESS);
@@ -6377,9 +7043,6 @@ mips_dump_tdep (struct gdbarch *current_
 		      VX_NUM_REGS);
 #endif
   fprintf_unfiltered (file,
-		      "mips_dump_tdep: ZERO_REGNUM = %d\n",
-		      ZERO_REGNUM);
-  fprintf_unfiltered (file,
 		      "mips_dump_tdep: _PROC_MAGIC_ = %d\n",
 		      _PROC_MAGIC_);
 }
@@ -6526,4 +7189,15 @@ that would transfer 32 bits for some reg
 				  &mips_debug, "Set mips debugging.\n\
 When non-zero, mips specific debugging is enabled.", &setdebuglist),
 		     &showdebuglist);
+
+  mips_type_float_double_register_big
+    = build_mips_type_float_double_register_big ();
+  mips_type_float_double_register_little
+    = build_mips_type_float_double_register_little ();
+  mips_type_float_single_register_big
+    = build_mips_type_float_single_register_big ();
+  mips_type_float_single_register_little
+    = build_mips_type_float_single_register_little ();
+
+  mips_init_reggroups ();
 }
Index: mips-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.h,v
retrieving revision 1.2
diff -u -p -r1.2 mips-tdep.h
--- mips-tdep.h	12 Apr 2003 17:41:25 -0000	1.2
+++ mips-tdep.h	9 May 2003 23:36:34 -0000
@@ -40,4 +40,40 @@ enum mips_abi
 /* Return the MIPS ABI associated with GDBARCH.  */
 enum mips_abi mips_abi (struct gdbarch *gdbarch);
 
+struct mips_regnums
+  {
+    int fp0_regnum;		/* First floating point register.  */
+    int fplast_regnum;		/* Last floating point register.  */
+    int last_arg_regnum;	/* Last general purpose register used for
+    				   passing arguments.  (a0_regnum is the
+				   first.)  */
+    int first_fp_arg_regnum;	/* First floating point register used for
+    				   passing floating point arguments.  */
+    int last_fp_arg_regnum;	/* Last floating point register used for
+    				   passing floating point arguments.  */
+    int zero_regnum;		/* The zero register; read-only, always 0.  */
+    int v0_regnum;		/* Function return value.  */
+    int a0_regnum;		/* First GPR used for passing arguments.  */
+    int t9_regnum;		/* Contains address of callee in PIC code.  */
+    int sp_regnum;		/* Stack pointer.  */
+    int ra_regnum;		/* Return address.  */
+    int ps_regnum;		/* Processor status.  */
+    int hi_regnum;		/* High portion of internal multiply/divide
+				   register.  */
+    int lo_regnum;		/* Low portion of internal multiply/divide
+    				   register.  */
+    int badvaddr_regnum;	/* Address associated with
+    				   addressing exception.  */
+    int cause_regnum;		/* Describes last exception.  */
+    int pc_regnum;		/* Program counter.  */
+    int fcrcs_regnum;		/* FP control/status.  */
+    int fcrir_regnum;		/* FP implementation/revision.  */
+    int first_embed_regnum;	/* First CP0 register for embedded use.  */
+    int last_embed_regnum;	/* Last CP0 register for embedded use.  */
+    int prid_regnum;		/* Processor ID.  */
+  };
+
+const struct mips_regnums *mips_raw_regnums (struct gdbarch *gdbarch);
+const struct mips_regnums *mips_cooked_regnums (struct gdbarch *gdbarch);
+
 #endif /* MIPS_TDEP_H */
Index: mipsnbsd-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mipsnbsd-nat.c,v
retrieving revision 1.1
diff -u -p -r1.1 mipsnbsd-nat.c
--- mipsnbsd-nat.c	21 May 2002 15:58:40 -0000	1.1
+++ mipsnbsd-nat.c	9 May 2003 23:36:34 -0000
@@ -22,6 +22,7 @@
 #include "inferior.h"
 #include "regcache.h"
 
+#include "mips-tdep.h"
 #include "mipsnbsd-tdep.h"
 
 #include <sys/types.h>
@@ -32,12 +33,16 @@
 static int
 getregs_supplies (int regno)
 {
-  return ((regno) >= ZERO_REGNUM && (regno) <= PC_REGNUM);
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
+  return (regno >= regnums->zero_regnum && regno <= regnums->pc_regnum);
 }
 
 void
 fetch_inferior_registers (int regno)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (regno == -1 || getregs_supplies (regno))
     {
       struct reg regs;
@@ -51,7 +56,7 @@ fetch_inferior_registers (int regno)
 	return;
     }
 
-  if (regno == -1 || regno >= FP0_REGNUM)
+  if (regno == -1 || regno >= regnums->fp0_regnum)
     {
       struct fpreg fpregs;
 
@@ -66,6 +71,8 @@ fetch_inferior_registers (int regno)
 void
 store_inferior_registers (int regno)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (regno == -1 || getregs_supplies (regno))
     {
       struct reg regs;
@@ -84,7 +91,7 @@ store_inferior_registers (int regno)
 	return;
     }
 
-  if (regno == -1 || regno >= FP0_REGNUM)
+  if (regno == -1 || regno >= regnums->fp0_regnum)
     {
       struct fpreg fpregs; 
 
Index: remote-mips.c
===================================================================
RCS file: /cvs/src/src/gdb/remote-mips.c,v
retrieving revision 1.33
diff -u -p -r1.33 remote-mips.c
--- remote-mips.c	29 Apr 2003 01:49:47 -0000	1.33
+++ remote-mips.c	9 May 2003 23:36:35 -0000
@@ -36,6 +36,7 @@
 #include "gdb_stat.h"
 #include "regcache.h"
 #include <ctype.h>
+#include "mips-tdep.h"
 
 
 /* Breakpoint types.  Values 0, 1, and 2 must agree with the watch
@@ -1750,6 +1751,7 @@ mips_wait (ptid_t ptid, struct target_wa
   char flags[20];
   int nfields;
   int i;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   interrupt_count = 0;
   hit_watchpoint = 0;
@@ -1793,14 +1795,14 @@ mips_wait (ptid_t ptid, struct target_wa
     {
       char *buf = alloca (max_register_size (current_gdbarch));
 
-      store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rpc);
-      supply_register (PC_REGNUM, buf);
+      store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->pc_regnum), rpc);
+      supply_register (regnums->pc_regnum, buf);
 
-      store_unsigned_integer (buf, REGISTER_RAW_SIZE (PC_REGNUM), rfp);
+      store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->pc_regnum), rfp);
       supply_register (30, buf);	/* This register they are avoiding and so it is unnamed */
 
-      store_unsigned_integer (buf, REGISTER_RAW_SIZE (SP_REGNUM), rsp);
-      supply_register (SP_REGNUM, buf);
+      store_unsigned_integer (buf, REGISTER_RAW_SIZE (regnums->sp_regnum), rsp);
+      supply_register (regnums->sp_regnum, buf);
 
       store_unsigned_integer (buf, REGISTER_RAW_SIZE (DEPRECATED_FP_REGNUM), 0);
       supply_register (DEPRECATED_FP_REGNUM, buf);
@@ -1904,25 +1906,26 @@ mips_wait (ptid_t ptid, struct target_wa
 static int
 mips_map_regno (int regno)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   if (regno < 32)
     return regno;
-  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
-    return regno - FP0_REGNUM + 32;
-  switch (regno)
-    {
-    case PC_REGNUM:
-      return REGNO_OFFSET + 0;
-    case CAUSE_REGNUM:
-      return REGNO_OFFSET + 1;
-    case HI_REGNUM:
-      return REGNO_OFFSET + 2;
-    case LO_REGNUM:
-      return REGNO_OFFSET + 3;
-    case FCRCS_REGNUM:
-      return REGNO_OFFSET + 4;
-    case FCRIR_REGNUM:
-      return REGNO_OFFSET + 5;
-    default:
+  if (regno >= regnums->fp0_regnum && regno < regnums->fp0_regnum + 32)
+    return regno - regnums->fp0_regnum + 32;
+  else if (regno == regnums->pc_regnum)
+    return REGNO_OFFSET + 0;
+  else if (regno == regnums->cause_regnum)
+    return REGNO_OFFSET + 1;
+  else if (regno == regnums->hi_regnum)
+    return REGNO_OFFSET + 2;
+  else if (regno == regnums->lo_regnum)
+    return REGNO_OFFSET + 3;
+  else if (regno == regnums->fcrcs_regnum)
+    return REGNO_OFFSET + 4;
+  else if (regno == regnums->fcrir_regnum)
+    return REGNO_OFFSET + 5;
+  else
+    {
       /* FIXME: Is there a way to get the status register?  */
       return 0;
     }
@@ -1935,6 +1938,7 @@ mips_fetch_registers (int regno)
 {
   unsigned LONGEST val;
   int err;
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
 
   if (regno == -1)
     {
@@ -1943,7 +1947,7 @@ mips_fetch_registers (int regno)
       return;
     }
 
-  if (regno == DEPRECATED_FP_REGNUM || regno == ZERO_REGNUM)
+  if (regno == DEPRECATED_FP_REGNUM || regno == regnums->zero_regnum)
     /* DEPRECATED_FP_REGNUM on the mips is a hack which is just
        supposed to read zero (see also mips-nat.c).  */
     val = 0;
@@ -3426,6 +3430,8 @@ pmon_load_fast (char *file)
 static void
 mips_load (char *file, int from_tty)
 {
+  const struct mips_regnums *regnums = mips_raw_regnums (current_gdbarch);
+
   /* Get the board out of remote debugging mode.  */
   if (mips_exit_debug ())
     error ("mips_load:  Couldn't get into monitor mode.");
@@ -3443,7 +3449,7 @@ mips_load (char *file, int from_tty)
       /* Work around problem where PMON monitor updates the PC after a load
          to a different value than GDB thinks it has. The following ensures
          that the write_pc() WILL update the PC value: */
-      deprecated_register_valid[PC_REGNUM] = 0;
+      deprecated_register_valid[regnums->pc_regnum] = 0;
     }
   if (exec_bfd)
     write_pc (bfd_get_start_address (exec_bfd));
Index: config/mips/nm-riscos.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/nm-riscos.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 nm-riscos.h
--- config/mips/nm-riscos.h	7 Jul 1999 20:15:18 -0000	1.1.1.2
+++ config/mips/nm-riscos.h	9 May 2003 23:36:36 -0000
@@ -29,27 +29,27 @@
 #define KERNEL_U_ADDR BSD43_UADDR
 
 #define REGISTER_U_ADDR(addr, blockend, regno) 		\
-	      if (regno < FP0_REGNUM) \
+	      if (regno < mips_raw_regnums (current_gdbarch)->fp0_regnum) \
 		  addr =  UPAGES*NBPG-EF_SIZE+4*((regno)+EF_AT-1); \
-	      else if (regno < PC_REGNUM) \
-		  addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
-              else if (regno == PS_REGNUM) \
+	      else if (regno < mips_raw_regnums (current_gdbarch)->pc_regnum) \
+		  addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-mips_raw_regnums (current_gdbarch)->fp0_regnum); \
+              else if (regno == mips_raw_regnums (current_gdbarch)->ps_regnum) \
                   addr = UPAGES*NBPG-EF_SIZE+4*EF_SR; \
-              else if (regno == BADVADDR_REGNUM) \
+              else if (regno == mips_raw_regnums (current_gdbarch)->badvaddr_regnum) \
   		  addr = UPAGES*NBPG-EF_SIZE+4*EF_BADVADDR; \
-	      else if (regno == LO_REGNUM) \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->lo_regnum) \
 		  addr = UPAGES*NBPG-EF_SIZE+4*EF_MDLO; \
-	      else if (regno == HI_REGNUM) \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->hi_regnum) \
 		  addr = UPAGES*NBPG-EF_SIZE+4*EF_MDHI; \
-	      else if (regno == CAUSE_REGNUM) \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->cause_regnum) \
 		  addr = UPAGES*NBPG-EF_SIZE+4*EF_CAUSE; \
-	      else if (regno == PC_REGNUM) \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->pc_regnum) \
 		  addr = UPAGES*NBPG-EF_SIZE+4*EF_EPC; \
-              else if (regno < FCRCS_REGNUM) \
-		  addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-FP0_REGNUM); \
-	      else if (regno == FCRCS_REGNUM) \
+              else if (regno < mips_raw_regnums (current_gdbarch)->fcrcs_regnum) \
+		  addr = PCB_OFFSET(pcb_fpregs[0]) + 4*(regno-mips_raw_regnums (current_gdbarch)->fp0_regnum); \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->fcrcs_regnum) \
 		  addr = PCB_OFFSET(pcb_fpc_csr); \
-	      else if (regno == FCRIR_REGNUM) \
+	      else if (regno == mips_raw_regnums (current_gdbarch)->fcrir_regnum) \
 		  addr = PCB_OFFSET(pcb_fpc_eir); \
               else \
                   addr = 0;
Index: config/mips/tm-irix3.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix3.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-irix3.h
--- config/mips/tm-irix3.h	19 Mar 2003 06:21:14 -0000	1.5
+++ config/mips/tm-irix3.h	9 May 2003 23:36:36 -0000
@@ -21,44 +21,6 @@
 
 #include "mips/tm-bigmips.h"
 
-/* Redefine register numbers for SGI. */
-
-#undef MIPS_REGISTER_NAMES
-#undef FP0_REGNUM
-#undef PC_REGNUM
-#undef HI_REGNUM
-#undef LO_REGNUM
-#undef CAUSE_REGNUM
-#undef BADVADDR_REGNUM
-#undef FCRCS_REGNUM
-#undef FCRIR_REGNUM
-
-/* Initializer for an array of names for registers 32 and above.
-   There should be NUM_REGS-32 strings in this initializer.  */
-
-#define MIPS_REGISTER_NAMES 	\
-    {	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
-	"pc",	"cause", "bad",	"hi",	"lo",	"fsr",  "fir" \
-    }
-
-/* Register numbers of various important registers.
-   Note that some of these values are "real" register numbers,
-   and correspond to the general registers of the machine,
-   and some are "phony" register numbers which are too large
-   to be actual register numbers as far as the user is concerned
-   but do serve to get the desired values when passed to read_register.  */
-
-#define FP0_REGNUM 32		/* Floating point register 0 (single float) */
-#define PC_REGNUM 64		/* Contains program counter */
-#define CAUSE_REGNUM 65		/* describes last exception */
-#define BADVADDR_REGNUM 66	/* bad vaddr for addressing exception */
-#define HI_REGNUM 67		/* Multiple/divide temp */
-#define LO_REGNUM 68		/* ... */
-#define FCRCS_REGNUM 69		/* FP control/status */
-#define FCRIR_REGNUM 70		/* FP implementation/revision */
 
 /* Offsets for register values in _sigtramp frame.
    sigcontext is immediately above the _sigtramp frame on Irix.  */
Index: config/mips/tm-irix5.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix5.h,v
retrieving revision 1.8
diff -u -p -r1.8 tm-irix5.h
--- config/mips/tm-irix5.h	20 Aug 2002 13:17:55 -0000	1.8
+++ config/mips/tm-irix5.h	9 May 2003 23:36:39 -0000
@@ -21,36 +21,6 @@
 
 #include "mips/tm-irix3.h"
 
-/* FIXME: cagney/2000-04-04: Testing the _MIPS_SIM_NABI32 and
-   _MIPS_SIM in a tm-*.h file is simply wrong!  Those are
-   host-dependant macros (provided by /usr/include) and stop any
-   chance of the target being cross compiled */
-#if defined (_MIPS_SIM_NABI32) && _MIPS_SIM == _MIPS_SIM_NABI32
-/*
- * Irix 6 (n32 ABI) has 32-bit GP regs and 64-bit FP regs
- */
-
-#undef  REGISTER_BYTES
-#define REGISTER_BYTES (MIPS_NUMREGS * 8 + (NUM_REGS - MIPS_NUMREGS) * MIPS_REGSIZE)
-
-#undef  REGISTER_BYTE
-#define REGISTER_BYTE(N) \
-     (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \
-      ((N) < FP0_REGNUM + 32) ?     \
-      FP0_REGNUM * MIPS_REGSIZE + \
-      ((N) - FP0_REGNUM) * sizeof(double) : \
-      32 * sizeof(double) + ((N) - 32) * MIPS_REGSIZE)
-
-#undef  REGISTER_VIRTUAL_TYPE
-#define REGISTER_VIRTUAL_TYPE(N) \
-	(((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
-	 : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
-	 : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
-	 : builtin_type_int)
-
-#endif /* N32 */
-
-
 /* The signal handler trampoline is called _sigtramp.  */
 #undef IN_SIGTRAMP
 #define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
Index: config/mips/tm-irix6.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-irix6.h,v
retrieving revision 1.10
diff -u -p -r1.10 tm-irix6.h
--- config/mips/tm-irix6.h	19 Mar 2003 06:21:14 -0000	1.10
+++ config/mips/tm-irix6.h	9 May 2003 23:36:39 -0000
@@ -24,55 +24,9 @@
 
 /* Redefine register numbers for SGI. */
 
-#undef MIPS_REGISTER_NAMES
-#undef FP0_REGNUM
-#undef PC_REGNUM
-#undef HI_REGNUM
-#undef LO_REGNUM
-#undef CAUSE_REGNUM
-#undef BADVADDR_REGNUM
-#undef FCRCS_REGNUM
-#undef FCRIR_REGNUM
-
-/* Initializer for an array of names for registers 32 and above.
-   There should be NUM_REGS-32 strings in this initializer.  */
-
-#define MIPS_REGISTER_NAMES 	\
-    {	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
-	"pc",	"cause", "bad",	"hi",	"lo",	"fsr",  "fir" \
-    }
-
-/* Register numbers of various important registers.
-   Note that some of these values are "real" register numbers,
-   and correspond to the general registers of the machine,
-   and some are "phony" register numbers which are too large
-   to be actual register numbers as far as the user is concerned
-   but do serve to get the desired values when passed to read_register.  */
-
-#define FP0_REGNUM 32		/* Floating point register 0 (single float) */
-#define PC_REGNUM 64		/* Contains program counter */
-#define CAUSE_REGNUM 65		/* describes last exception */
-#define BADVADDR_REGNUM 66	/* bad vaddr for addressing exception */
-#define HI_REGNUM 67		/* Multiple/divide temp */
-#define LO_REGNUM 68		/* ... */
-#define FCRCS_REGNUM 69		/* FP control/status */
-#define FCRIR_REGNUM 70		/* FP implementation/revision */
-
-
 #undef  REGISTER_BYTES
 #define REGISTER_BYTES (MIPS_NUMREGS * 8 + (NUM_REGS - MIPS_NUMREGS) * MIPS_REGSIZE)
 
-#undef  REGISTER_BYTE
-#define REGISTER_BYTE(N) \
-     (((N) < FP0_REGNUM) ? (N) * MIPS_REGSIZE : \
-      ((N) < FP0_REGNUM + 32) ?     \
-      FP0_REGNUM * MIPS_REGSIZE + \
-      ((N) - FP0_REGNUM) * sizeof(double) : \
-      32 * sizeof(double) + ((N) - 32) * MIPS_REGSIZE)
-
 /* The signal handler trampoline is called _sigtramp.  */
 #undef IN_SIGTRAMP
 #define IN_SIGTRAMP(pc, name) ((name) && STREQ ("_sigtramp", name))
@@ -99,6 +53,3 @@
 /* Select the disassembler */
 #undef TM_PRINT_INSN_MACH
 #define TM_PRINT_INSN_MACH bfd_mach_mips8000
-
-/* Undefine those methods which have been multiarched.  */
-#undef REGISTER_VIRTUAL_TYPE
Index: config/mips/tm-mips.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-mips.h,v
retrieving revision 1.48
diff -u -p -r1.48 tm-mips.h
--- config/mips/tm-mips.h	5 May 2003 17:56:56 -0000	1.48
+++ config/mips/tm-mips.h	9 May 2003 23:36:39 -0000
@@ -59,88 +59,10 @@ extern int mips_step_skips_delay (CORE_A
 #define MIPS_REGSIZE 4
 #endif
 
-/* Initializer for an array of names for registers 32 and above.
-   There should be NUM_REGS-32 strings in this initializer.  */
-
-#ifndef MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES 	\
-    {	"sr",	"lo",	"hi",	"bad",	"cause","pc",    \
-	"f0",   "f1",   "f2",   "f3",   "f4",   "f5",   "f6",   "f7", \
-	"f8",   "f9",   "f10",  "f11",  "f12",  "f13",  "f14",  "f15", \
-	"f16",  "f17",  "f18",  "f19",  "f20",  "f21",  "f22",  "f23",\
-	"f24",  "f25",  "f26",  "f27",  "f28",  "f29",  "f30",  "f31",\
-	"fsr",  "fir",  ""/*"fp"*/,	"", \
-	"",	"",	"",	"",	"",	"",	"",	"", \
-	"",	"",	"",	"",	"",	"",	"",	"", \
-    }
-#endif
-
-/* Register numbers of various important registers.
-   Note that some of these values are "real" register numbers,
-   and correspond to the general registers of the machine,
-   and some are "phony" register numbers which are too large
-   to be actual register numbers as far as the user is concerned
-   but do serve to get the desired values when passed to read_register.  */
-
-#define ZERO_REGNUM 0		/* read-only register, always 0 */
-#define V0_REGNUM 2		/* Function integer return value */
-#define A0_REGNUM 4		/* Loc of first arg during a subr call */
-#define T9_REGNUM 25		/* Contains address of callee in PIC */
-#define SP_REGNUM 29		/* Contains address of top of stack */
-#define RA_REGNUM 31		/* Contains return address value */
-#define PS_REGNUM 32		/* Contains processor status */
-#define HI_REGNUM 34		/* Multiple/divide temp */
-#define LO_REGNUM 33		/* ... */
-#define BADVADDR_REGNUM 35	/* bad vaddr for addressing exception */
-#define CAUSE_REGNUM 36		/* describes last exception */
-#define PC_REGNUM 37		/* Contains program counter */
-#define FP0_REGNUM 38		/* Floating point register 0 (single float) */
-#define FPA0_REGNUM (FP0_REGNUM+12)	/* First float argument register */
-#define FCRCS_REGNUM 70		/* FP control/status */
-#define FCRIR_REGNUM 71		/* FP implementation/revision */
-#define	UNUSED_REGNUM 73	/* Never used, FIXME */
-#define	FIRST_EMBED_REGNUM 74	/* First CP0 register for embedded use */
-#define	PRID_REGNUM 89		/* Processor ID */
-#define	LAST_EMBED_REGNUM 89	/* Last one */
-
 /* Total amount of space needed to store our copies of the machine's
    register state, the array `registers'.  */
 
 #define REGISTER_BYTES (NUM_REGS*MIPS_REGSIZE)
-
-/* Index within `registers' of the first byte of the space for
-   register N.  */
-
-#define REGISTER_BYTE(N) ((N) * MIPS_REGSIZE)
-
-/* Return the GDB type object for the "standard" data type of data in
-   register N.  */
-
-#ifndef REGISTER_VIRTUAL_TYPE
-#define REGISTER_VIRTUAL_TYPE(N) \
-	(((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_float \
-	 : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
-	 : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
-	 : builtin_type_int)
-#endif
-
-/* All mips targets store doubles in a register pair with the least
-   significant register in the lower numbered register.
-   If the target is big endian, double register values need conversion
-   between memory and register formats.  */
-
-extern void mips_register_convert_to_type (int regnum, 
-					   struct type *type,
-					   char *buffer);
-extern void mips_register_convert_from_type (int regnum, 
-					     struct type *type,
-					     char *buffer);
-
-#define REGISTER_CONVERT_TO_TYPE(n, type, buffer)	\
-  mips_register_convert_to_type ((n), (type), (buffer))
-
-#define REGISTER_CONVERT_FROM_TYPE(n, type, buffer)	\
-  mips_register_convert_from_type ((n), (type), (buffer))
 
 
 /* Special symbol found in blocks associated with routines.  We can hang
Index: config/mips/tm-mips64.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-mips64.h,v
retrieving revision 1.5
diff -u -p -r1.5 tm-mips64.h
--- config/mips/tm-mips64.h	5 Jun 2002 19:18:25 -0000	1.5
+++ config/mips/tm-mips64.h	9 May 2003 23:36:39 -0000
@@ -22,13 +22,6 @@
 /* Use eight byte registers.  */
 #define MIPS_REGSIZE 8
 
-/* define 8 byte register type */
-#define REGISTER_VIRTUAL_TYPE(N) \
-        (((N) >= FP0_REGNUM && (N) < FP0_REGNUM+32) ? builtin_type_double \
-	 : ((N) == 32 /*SR*/) ? builtin_type_uint32 \
-	 : ((N) >= 70 && (N) <= 89) ? builtin_type_uint32 \
-	 : builtin_type_long_long)
-
 /* Load double words in CALL_DUMMY.  */
 #define OP_LDFPR 065		/* ldc1 */
 #define OP_LDGPR 067		/* ld */
Index: config/mips/tm-tx39.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-tx39.h,v
retrieving revision 1.6
diff -u -p -r1.6 tm-tx39.h
--- config/mips/tm-tx39.h	19 Mar 2003 06:21:14 -0000	1.6
+++ config/mips/tm-tx39.h	9 May 2003 23:36:39 -0000
@@ -18,15 +18,3 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "mips/tm-bigmips.h"
-
-#undef  MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES 	\
-    {	"sr",	"lo",	"hi",	"bad",	"cause","pc", \
-	"",   	"",   	"",   	"",   	"",   	"",   	"",   	"", \
-	"",   	"",   	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",	"", \
-	"",	"",	"",	"",	"",	"",	"",	"", \
-	"",	"", "config", "cache", "debug", "depc", "epc",	"" \
-    }
Index: config/mips/tm-tx39l.h
===================================================================
RCS file: /cvs/src/src/gdb/config/mips/tm-tx39l.h,v
retrieving revision 1.6
diff -u -p -r1.6 tm-tx39l.h
--- config/mips/tm-tx39l.h	19 Mar 2003 06:21:14 -0000	1.6
+++ config/mips/tm-tx39l.h	9 May 2003 23:36:39 -0000
@@ -18,15 +18,3 @@
    Boston, MA 02111-1307, USA.  */
 
 #include "mips/tm-mips.h"
-
-#undef  MIPS_REGISTER_NAMES
-#define MIPS_REGISTER_NAMES 	\
-    {	"sr",	"lo",	"hi",	"bad",	"cause","pc", \
-	"",   	"",   	"",   	"",   	"",   	"",   	"",   	"", \
-	"",   	"",   	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",  	"",  	"",  	"",  	"",  	"", \
-	"",  	"",  	"",	"", \
-	"",	"",	"",	"",	"",	"",	"",	"", \
-	"",	"", "config", "cache", "debug", "depc", "epc",	"" \
-    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]