Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* MIPS: Handle the DSP registers
@ 2007-12-10 16:33 Maciej W. Rozycki
  2007-12-18 13:42 ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Maciej W. Rozycki @ 2007-12-10 16:33 UTC (permalink / raw)
  To: gdb-patches; +Cc: Chris Dearman, Maciej W. Rozycki

Hello,

 Here is code to support DSP registers as defined by the DSP ASE to the 
MIPS Architecture.  This piece of code handles Linux and provides for 
adding such support to embedded targets.  The ASE is optional (as are all 
ASEs) and therefore some steps have been taken to handle this correctly.

 In particular, ptrace() calls may return a failure when called on a 
system that does not support the ASE.  In such a case the registers are 
marked as unavailable in the cache which has the effect of them being 
hardwired to zero (I have a patch in the queue that would mark them 
specially in the output; I will submit it later).

 The offsets and layout of DSP registers vary between Linux and bare-iron 
-- this has been taken account of (by shuffling some code around in 
mips_gdbarch_init(), which I believe has actually made it a little bit 
more readable) and it is also the reason some minimal support for these 
registers with the bare-iron has been included here (and which effectively 
amounts to the addition of more MIPS_EMBED_* enum definitions and their 
use in mips-tdep.c).  Full support for bare-iron relies on cp0 register 
discovery which I plan to propose later on (once I have found a reasonable 
way to port the old piece of code so that it fits the XML target 
description model).

 As a small benefit on top of these changes, there is no need to provide 
null strings in the tables holding register names for offsets 
corresponding to inexistent registers anymore -- mips_register_name() now 
returns a null string when the entry requested holds a null pointer.

 Tested using the mipsisa32-sde-elf target, with the mips-sim-sde32/-EB 
and mips-sim-sde32/-EL boards with no regressions.  Tested natively with 
the mips-linux-gnu host/target (with the o32 ABI) using a MIPS64 (no DSP 
ASE) and a MIPS32r2 (DSP-enabled) processor with no regressions in either.  
I have no access to the IRIX host, but I hope I have not broken anything 
-- the support for no-DSP there should keep working as it is.

gdb/:
2007-12-10  Maciej W. Rozycki  <macro@mips.com>
            Chris Dearman  <chris@mips.com>

	* features/mips-dsp.xml: New file.
	* features/mips64-dsp.xml: Likewise.
	* features/mips-linux.xml: Include mips-dsp.xml.
	* features/mips64-linux.xml: Include mips64-dsp.xml.
	* features/mips-linux.c: Regenerate.
	* features/mips64-linux.c: Regenerate.
	* inf-ptrace.c (inf_ptrace_fetch_register): Don't bail out
	having attempted to read an inexistent register; mark it as
	inaccessible in the cache instead.
	(inf_ptrace_store_register): Don't bail out having attempted to
	write an inexistent register.
	* mips-linux-nat.c (super_fetch_registers): Mark static.
	(super_store_registers): Likewise.
	(mips_linux_register_addr): Handle DSP registers.
	(mips64_linux_register_addr): Likewise.
	(mips64_linux_regsets_fetch_registers): Likewise.
	(mips64_linux_regsets_store_registers): Likewise.
	* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
	Remove padding as the register array does not use the layout
	defined for embedded targets anymore.
	* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
	* mips-tdep.c (NUM_MIPS_PROCESSOR_REGS): Set from
	MIPS_LAST_EMBED_REGNUM.
	(mips_generic_reg_names): Remove trailing null strings.
	(mips_tx39_reg_names): Likewise.
	(mips_linux_reg_names): New array of register names for Linux
	targets.
	(mips_register_name): Check for a null pointer in
	mips_processor_reg_names and return an empty string.
	(mips_stab_reg_to_regnum): Handle DSP accumulators.
	(mips_dwarf_dwarf2_ecoff_reg_to_regnum): Likewise.
	(mips_gdbarch_init): Likewise.  Initialize internal register
	indices for Linux.  Use MIPS_LAST_EMBED_REGNUM as appropriate.
	* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.
	(MIPS_EMBED_CP2_REGNUM): Offset to CP2 registers.
	(MIPS_EMBED_DSPACC_REGNUM): Offset to DSP accumulator registers.
	(MIPS_EMBED_DSPCTL_REGNUM): Offset to DSP control registers.
	(MIPS_LAST_EMBED_REGNUM): Update accordingly.
	(MIPS_EMBED_NUM_REGS): New value to make sure that an even
	number of registers is used.
	* regcache.c (regcache_invalidate): Allow for an arbitrary
	setting of the cache state and replace with a wrapper to call
	the original function renamed to...
	(regcache_set_valid_p): ... this.
	* regcache.h (regcache_set_valid_p): New prototype.

gdb/testsuite/:
2007-12-10  Maciej W. Rozycki  <macro@mips.com>

	* gdb.xml/tdesc-regs.exp: Add "mips-dsp.xml" to the list of MIPS
	core registers.

 Ok to apply?

  Maciej

14607.diff
Index: binutils-quilt/src/gdb/mips-linux-nat.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-nat.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-nat.c	2007-12-07 15:13:02.000000000 +0000
@@ -47,8 +47,8 @@
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
-void (*super_fetch_registers) (struct regcache *, int);
-void (*super_store_registers) (struct regcache *, int);
+static void (*super_fetch_registers) (struct regcache *, int);
+static void (*super_store_registers) (struct regcache *, int);
 
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are normally defined in <asm/ptrace.h>. 
@@ -84,6 +84,11 @@
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+  else if ((regno >= mips_regnum (gdbarch)->dspacc)
+	   && (regno < mips_regnum (gdbarch)->dspacc + 6))
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -119,6 +124,11 @@
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+  else if ((regno >= mips_regnum (gdbarch)->dspacc)
+	   && (regno < mips_regnum (gdbarch)->dspacc + 6))
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -192,7 +202,8 @@
 mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -205,11 +216,20 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if ((regno >= mips_regnum (gdbarch)->dspacc)
+      && (regno < mips_regnum (gdbarch)->dspacc + 6))
+    is_dsp = 1;
+  else if (regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -245,16 +265,28 @@
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      for (regi = mips_regnum (gdbarch)->dspacc;
+	   regi < mips_regnum (gdbarch)->dspacc + 6;
+	   regi++)
+	super_fetch_registers (regcache, regi);
+      super_fetch_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
    using PTRACE_SETREGS et al.  */
 
 static void
-mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
+mips64_linux_regsets_store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -267,11 +299,20 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if ((regno >= mips_regnum (gdbarch)->dspacc)
+      && (regno < mips_regnum (gdbarch)->dspacc + 6))
+    is_dsp = 1;
+  else if (regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -298,6 +339,17 @@
 		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
+
+  if (is_dsp)
+    super_store_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      for (regi = mips_regnum (gdbarch)->dspacc;
+	   regi < mips_regnum (gdbarch)->dspacc + 6;
+	   regi++)
+	super_store_registers (regcache, regi);
+      super_store_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
Index: binutils-quilt/src/gdb/mips-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.c	2007-12-07 15:10:04.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c	2007-12-07 15:13:02.000000000 +0000
@@ -436,7 +436,7 @@
    are listed in the following tables.  */
 
 enum
-{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+{ NUM_MIPS_PROCESSOR_REGS = (MIPS_LAST_EMBED_REGNUM + 1 - 32) };
 
 /* Generic MIPS.  */
 
@@ -446,9 +446,7 @@
   "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" */ , "",
-  "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "",
+  "fsr", "fir",
 };
 
 /* Names of IDT R3041 registers.  */
@@ -474,7 +472,7 @@
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -486,6 +484,17 @@
   "pc", "cause", "bad", "hi", "lo", "fsr", "fir"
 };
 
+/* Names of Linux registers.  */
+static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
+  "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", "hi1", "lo1", "hi2", "lo2", "hi3", "lo3",
+  "dspctl",
+};
+
 
 /* Return the name of the register corresponding to REGNO.  */
 static const char *
@@ -531,7 +540,9 @@
   else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
     {
       gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
-      return tdep->mips_processor_reg_names[rawnum - 32];
+      if (tdep->mips_processor_reg_names[rawnum - 32])
+	return tdep->mips_processor_reg_names[rawnum - 32];
+      return "";
     }
   else
     internal_error (__FILE__, __LINE__,
@@ -5076,6 +5087,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 72 && num < 78)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 72;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
@@ -5099,6 +5112,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 66 && num < 72)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 66;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
@@ -5232,10 +5247,66 @@
   struct gdbarch_tdep *tdep;
   int elf_flags;
   enum mips_abi mips_abi, found_abi, wanted_abi;
-  int i, num_regs;
+  int i, num_regs, dsp_space;
   enum mips_fpu_type fpu_type;
   struct tdesc_arch_data *tdesc_data = NULL;
   int elf_fpu_type = 0;
+  const char **reg_names;
+  struct mips_regnum mips_regnum, *regnum;
+
+  /* Fill in the OS dependant register numbers and names.  */
+  if (info.osabi == GDB_OSABI_IRIX)
+    {
+      mips_regnum.fp0 = 32;
+      mips_regnum.pc = 64;
+      mips_regnum.cause = 65;
+      mips_regnum.badvaddr = 66;
+      mips_regnum.hi = 67;
+      mips_regnum.lo = 68;
+      mips_regnum.fp_control_status = 69;
+      mips_regnum.fp_implementation_revision = 70;
+      mips_regnum.dspacc = -1;
+      mips_regnum.dspctl = -1;
+      dsp_space = 0;
+      num_regs = 71;
+      reg_names = mips_irix_reg_names;
+    }
+  else if (info.osabi == GDB_OSABI_LINUX)
+    {
+      mips_regnum.fp0 = 38;
+      mips_regnum.pc = 37;
+      mips_regnum.cause = 36;
+      mips_regnum.badvaddr = 35;
+      mips_regnum.hi = 34;
+      mips_regnum.lo = 33;
+      mips_regnum.fp_control_status = 70;
+      mips_regnum.fp_implementation_revision = 71;
+      mips_regnum.dspacc = 72;
+      mips_regnum.dspctl = 78;
+      dsp_space = 0;
+      num_regs = 79;
+      reg_names = mips_linux_reg_names;
+    }
+  else
+    {
+      mips_regnum.lo = MIPS_EMBED_LO_REGNUM;
+      mips_regnum.hi = MIPS_EMBED_HI_REGNUM;
+      mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
+      mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM;
+      mips_regnum.pc = MIPS_EMBED_PC_REGNUM;
+      mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM;
+      mips_regnum.fp_control_status = 70;
+      mips_regnum.fp_implementation_revision = 71;
+      mips_regnum.dspacc = MIPS_EMBED_DSPACC_REGNUM;
+      mips_regnum.dspctl = MIPS_EMBED_DSPCTL_REGNUM;
+      dsp_space = 1;
+      num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+      if (info.bfd_arch_info != NULL
+          && info.bfd_arch_info->mach == bfd_mach_mips3900)
+        reg_names = mips_tx39_reg_names;
+      else
+        reg_names = mips_generic_reg_names;
+    }
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -5270,11 +5341,11 @@
 
 
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_LO_REGNUM, "lo");
+					  mips_regnum.lo, "lo");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_HI_REGNUM, "hi");
+					  mips_regnum.hi, "hi");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_PC_REGNUM, "pc");
+					  mips_regnum.pc, "pc");
 
       if (!valid_p)
 	{
@@ -5292,12 +5363,11 @@
 
       valid_p = 1;
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_BADVADDR_REGNUM,
-					  "badvaddr");
+					  mips_regnum.badvaddr, "badvaddr");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					  MIPS_PS_REGNUM, "status");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_CAUSE_REGNUM, "cause");
+					  mips_regnum.cause, "cause");
 
       if (!valid_p)
 	{
@@ -5318,13 +5388,15 @@
       valid_p = 1;
       for (i = 0; i < 32; i++)
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					    i + MIPS_EMBED_FP0_REGNUM,
-					    mips_fprs[i]);
+					    i + mips_regnum.fp0, mips_fprs[i]);
 
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_FP0_REGNUM + 32, "fcsr");
-      valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_FP0_REGNUM + 33, "fir");
+					  mips_regnum.fp_control_status,
+					  "fcsr");
+      valid_p
+	&= tdesc_numbered_register (feature, tdesc_data,
+				    mips_regnum.fp_implementation_revision,
+				    "fir");
 
       if (!valid_p)
 	{
@@ -5332,8 +5404,46 @@
 	  return NULL;
 	}
 
+      if (mips_regnum.dspacc >= 0)
+	{
+	  feature = tdesc_find_feature (info.target_desc,
+					"org.gnu.gdb.mips.dsp");
+	  if (feature == NULL)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+
+	  valid_p = 1;
+	  i = dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo1");
+	  i += dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo2");
+	  i += dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo3");
+
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspctl, "dspctl");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
+      reg_names = NULL;
     }
 
   /* First of all, extract the elf_flags, if available.  */
@@ -5572,66 +5682,19 @@
   set_gdbarch_elf_make_msymbol_special (gdbarch,
 					mips_elf_make_msymbol_special);
 
-  /* Fill in the OS dependant register numbers and names.  */
-  {
-    const char **reg_names;
-    struct mips_regnum *regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch,
-							 struct mips_regnum);
-    if (tdesc_has_registers (info.target_desc))
-      {
-	regnum->lo = MIPS_EMBED_LO_REGNUM;
-	regnum->hi = MIPS_EMBED_HI_REGNUM;
-	regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
-	regnum->cause = MIPS_EMBED_CAUSE_REGNUM;
-	regnum->pc = MIPS_EMBED_PC_REGNUM;
-	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
-	regnum->fp_control_status = 70;
-	regnum->fp_implementation_revision = 71;
-	num_regs = MIPS_LAST_EMBED_REGNUM + 1;
-	reg_names = NULL;
-      }
-    else if (info.osabi == GDB_OSABI_IRIX)
-      {
-	regnum->fp0 = 32;
-	regnum->pc = 64;
-	regnum->cause = 65;
-	regnum->badvaddr = 66;
-	regnum->hi = 67;
-	regnum->lo = 68;
-	regnum->fp_control_status = 69;
-	regnum->fp_implementation_revision = 70;
-	num_regs = 71;
-	reg_names = mips_irix_reg_names;
-      }
-    else
-      {
-	regnum->lo = MIPS_EMBED_LO_REGNUM;
-	regnum->hi = MIPS_EMBED_HI_REGNUM;
-	regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
-	regnum->cause = MIPS_EMBED_CAUSE_REGNUM;
-	regnum->pc = MIPS_EMBED_PC_REGNUM;
-	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
-	regnum->fp_control_status = 70;
-	regnum->fp_implementation_revision = 71;
-	num_regs = 90;
-	if (info.bfd_arch_info != NULL
-	    && info.bfd_arch_info->mach == bfd_mach_mips3900)
-	  reg_names = mips_tx39_reg_names;
-	else
-	  reg_names = mips_generic_reg_names;
-      }
-    /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been
-       replaced by read_pc?  */
-    set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
-    set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
-    set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
-    set_gdbarch_num_regs (gdbarch, num_regs);
-    set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
-    set_gdbarch_register_name (gdbarch, mips_register_name);
-    set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer);
-    tdep->mips_processor_reg_names = reg_names;
-    tdep->regnum = regnum;
-  }
+  regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum);
+  *regnum = mips_regnum;
+  /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been
+     replaced by read_pc?  */
+  set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
+  set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
+  set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
+  set_gdbarch_num_regs (gdbarch, num_regs);
+  set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
+  set_gdbarch_register_name (gdbarch, mips_register_name);
+  set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer);
+  tdep->mips_processor_reg_names = reg_names;
+  tdep->regnum = regnum;
 
   switch (mips_abi)
     {
Index: binutils-quilt/src/gdb/mips-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.h	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.h	2007-12-07 15:13:02.000000000 +0000
@@ -53,6 +53,8 @@
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
   int lo;		/* ...  */
+  int dspacc;		/* SmartMIPS/DSP accumulators.  */
+  int dspctl;		/* DSP control.  */
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
@@ -75,9 +77,26 @@
   MIPS_EMBED_PC_REGNUM = 37,
   MIPS_EMBED_FP0_REGNUM = 38,
   MIPS_UNUSED_REGNUM = 73,	/* Never used, FIXME */
-  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP0 register for embedded use.  */
-  MIPS_PRID_REGNUM = 89,	/* Processor ID.  */
-  MIPS_LAST_EMBED_REGNUM = 89	/* Last one.  */
+  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP register for embedded use.  */
+  MIPS_EMBED_CP0_REGNUM = MIPS_FIRST_EMBED_REGNUM,
+				/* CP0 data registers: 8 banks of 32.  */
+  MIPS_PRID_REGNUM = (MIPS_EMBED_CP0_REGNUM + 15),
+				/* Processor ID.  */
+  MIPS_EMBED_CP2_REGNUM = (MIPS_EMBED_CP0_REGNUM + 8 * 32),
+				/* CP2 data registers: 8 banks of 32.  */
+  MIPS_EMBED_CP2CTL_REGNUM = (MIPS_EMBED_CP2_REGNUM + 8 * 32),
+				/* CP2 control registers: 32.  */
+  MIPS_EMBED_DSPACC_REGNUM = (MIPS_EMBED_CP2CTL_REGNUM + 32),
+				/* DSP/SmartMIPS registers:
+				   ACX, Hi1, Lo1, ACX1,
+				   Hi2, Lo2, ACX2, Hi3, Lo3, ACX3.  */
+  MIPS_EMBED_DSPCTL_REGNUM = (MIPS_EMBED_DSPACC_REGNUM + 10),
+				/* DSP DSPCTL0..1 registers.  */
+  MIPS_EMBED_NUM_REGS = (MIPS_EMBED_DSPCTL_REGNUM + 2),
+				/* Total number of actual registers.  */
+  MIPS_LAST_EMBED_REGNUM
+    = ((MIPS_EMBED_NUM_REGS + MIPS_EMBED_NUM_REGS % 2) - 1)
+				/* Last one, including padding to even.  */
 };
 
 /* Defined in mips-tdep.c and used in remote-mips.c */
Index: binutils-quilt/src/gdb/mips-linux-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.c	2007-12-07 15:13:02.000000000 +0000
@@ -112,14 +112,6 @@
   supply_32bit_reg (regcache, MIPS_PS_REGNUM, regp + EF_CP0_STATUS);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into an elf_gregset_t.  */
@@ -325,14 +317,6 @@
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
Index: binutils-quilt/src/gdb/mips-linux-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.h	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.h	2007-12-07 15:13:02.000000000 +0000
@@ -36,6 +36,8 @@
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71
+#define DSP_CONTROL	77
 
 #define EF_REG0			6
 #define EF_REG31		37
Index: binutils-quilt/src/gdb/inf-ptrace.c
===================================================================
--- binutils-quilt.orig/src/gdb/inf-ptrace.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/inf-ptrace.c	2007-12-07 15:13:02.000000000 +0000
@@ -647,7 +647,12 @@
     {
       errno = 0;
       buf[i] = ptrace (PT_READ_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, 0);
-      if (errno != 0)
+      if (errno == EIO)
+	{
+	  regcache_set_valid_p (regcache, regnum, -1);
+	  return;
+	}
+      else if (errno != 0)
 	error (_("Couldn't read register %s (#%d): %s."),
 	       gdbarch_register_name (gdbarch, regnum),
 	       regnum, safe_strerror (errno));
@@ -705,7 +710,9 @@
     {
       errno = 0;
       ptrace (PT_WRITE_U, pid, (PTRACE_TYPE_ARG3)(uintptr_t)addr, buf[i]);
-      if (errno != 0)
+      if (errno == EIO)
+	return;
+      else if (errno != 0)
 	error (_("Couldn't write register %s (#%d): %s."),
 	       gdbarch_register_name (gdbarch, regnum),
 	       regnum, safe_strerror (errno));
Index: binutils-quilt/src/gdb/features/mips-linux.xml
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips-linux.xml	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-linux.xml	2007-12-07 15:13:02.000000000 +0000
@@ -11,6 +11,7 @@
   <xi:include href="mips-cpu.xml"/>
   <xi:include href="mips-cp0.xml"/>
   <xi:include href="mips-fpu.xml"/>
+  <xi:include href="mips-dsp.xml"/>
 
   <feature name="org.gnu.gdb.mips.linux">
     <reg name="restart" bitsize="32" group="system"/>
Index: binutils-quilt/src/gdb/features/mips64-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp.xml	2007-12-07 15:13:02.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="64" regnum="72"/>
+  <reg name="lo1" bitsize="64" regnum="73"/>
+  <reg name="hi2" bitsize="64" regnum="74"/>
+  <reg name="lo2" bitsize="64" regnum="75"/>
+  <reg name="hi3" bitsize="64" regnum="76"/>
+  <reg name="lo3" bitsize="64" regnum="77"/>
+
+  <reg name="dspctl" bitsize="32" regnum="78"/>
+</feature>
Index: binutils-quilt/src/gdb/features/mips64-linux.xml
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips64-linux.xml	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-linux.xml	2007-12-07 15:13:02.000000000 +0000
@@ -11,6 +11,7 @@
   <xi:include href="mips64-cpu.xml"/>
   <xi:include href="mips64-cp0.xml"/>
   <xi:include href="mips64-fpu.xml"/>
+  <xi:include href="mips64-dsp.xml"/>
 
   <feature name="org.gnu.gdb.mips.linux">
     <reg name="restart" bitsize="64" group="system"/>
Index: binutils-quilt/src/gdb/features/mips-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp.xml	2007-12-07 15:13:02.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="32" regnum="72"/>
+  <reg name="lo1" bitsize="32" regnum="73"/>
+  <reg name="hi2" bitsize="32" regnum="74"/>
+  <reg name="lo2" bitsize="32" regnum="75"/>
+  <reg name="hi3" bitsize="32" regnum="76"/>
+  <reg name="lo3" bitsize="32" regnum="77"/>
+
+  <reg name="dspctl" bitsize="32" regnum="78"/>
+</feature>
Index: binutils-quilt/src/gdb/regcache.c
===================================================================
--- binutils-quilt.orig/src/gdb/regcache.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/regcache.c	2007-12-07 15:13:02.000000000 +0000
@@ -398,16 +398,24 @@
   return regcache->register_valid_p[regnum];
 }
 
+/* Record that REGNUM's value is cached if STATE is >0, uncached but
+   fetchable if STATE is 0, and uncached and unfetchable if STATE is <0.  */
+
 void
-regcache_invalidate (struct regcache *regcache, int regnum)
+regcache_set_valid_p (struct regcache *regcache, int regnum, int state)
 {
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0);
   gdb_assert (!regcache->readonly_p);
   gdb_assert (regnum < regcache->descr->nr_raw_registers);
-  regcache->register_valid_p[regnum] = 0;
+  regcache->register_valid_p[regnum] = state;
 }
 
+void
+regcache_invalidate (struct regcache *regcache, int regnum)
+{
+  regcache_set_valid_p (regcache, regnum, 0);
+}
 
 /* Global structure containing the current regcache.  */
 /* FIXME: cagney/2002-05-11: The two global arrays registers[] and
Index: binutils-quilt/src/gdb/regcache.h
===================================================================
--- binutils-quilt.orig/src/gdb/regcache.h	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/regcache.h	2007-12-07 15:13:02.000000000 +0000
@@ -60,6 +60,8 @@
 
 int regcache_valid_p (const struct regcache *regcache, int regnum);
 
+void regcache_set_valid_p (struct regcache *regcache, int regnum, int state);
+
 void regcache_invalidate (struct regcache *regcache, int regnum);
 
 /* Transfer a cooked register [0..NUM_REGS+NUM_PSEUDO_REGS).  */
Index: binutils-quilt/src/gdb/features/mips64-linux.c
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips64-linux.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-linux.c	2007-12-07 15:13:02.000000000 +0000
@@ -92,8 +92,17 @@
   tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
   tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
 
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 64, "int");
 
   tdesc_mips64_linux = result;
 }
Index: binutils-quilt/src/gdb/features/mips-linux.c
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips-linux.c	2007-12-07 15:08:21.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-linux.c	2007-12-07 15:13:02.000000000 +0000
@@ -92,8 +92,17 @@
   tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
   tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
 
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 32, "int");
 
   tdesc_mips_linux = result;
 }
Index: binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp
===================================================================
--- binutils-quilt.orig/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:01:40.000000000 +0000
+++ binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:02:17.000000000 +0000
@@ -33,7 +33,7 @@
         set core-regs {arm-core.xml}
     }
     "mips*-*-*" {
-	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml}
+	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml mips-dsp.xml}
     }
     "powerpc*-*-*" {
 	set regdir "rs6000/"


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2007-12-10 16:33 MIPS: Handle the DSP registers Maciej W. Rozycki
@ 2007-12-18 13:42 ` Daniel Jacobowitz
  2007-12-18 13:56   ` Nigel Stephens
  2008-03-19 17:07   ` Maciej W. Rozycki
  0 siblings, 2 replies; 13+ messages in thread
From: Daniel Jacobowitz @ 2007-12-18 13:42 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Mon, Dec 10, 2007 at 03:51:55PM +0000, Maciej W. Rozycki wrote:
> Hello,
> 
>  Here is code to support DSP registers as defined by the DSP ASE to the 
> MIPS Architecture.  This piece of code handles Linux and provides for 
> adding such support to embedded targets.  The ASE is optional (as are all 
> ASEs) and therefore some steps have been taken to handle this correctly.
> 
>  In particular, ptrace() calls may return a failure when called on a 
> system that does not support the ASE.  In such a case the registers are 
> marked as unavailable in the cache which has the effect of them being 
> hardwired to zero (I have a patch in the queue that would mark them 
> specially in the output; I will submit it later).

We have an even better way to handle this, nowadays.  Take a look at
arm-linux-nat.c:arm_linux_read_description.  This lets the registers
be completely hidden when they are not available.

> +/* Names of Linux registers.  */
> +static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
> +  "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", "hi1", "lo1", "hi2", "lo2", "hi3", "lo3",
> +  "dspctl",
> +};

If you're using a target description wherever you support these
registers, then you shouldn't need another copy of them here.

> @@ -5270,11 +5341,11 @@
>  
>  
>        valid_p &= tdesc_numbered_register (feature, tdesc_data,
> -					  MIPS_EMBED_LO_REGNUM, "lo");
> +					  mips_regnum.lo, "lo");

I went to a bit of trouble to be able to use constants here, please
don't go back the other direction.  When all the raw registers use
constant numbering, it's much easier to manage the GDB backend.

> +      if (mips_regnum.dspacc >= 0)
> +	{
> +	  feature = tdesc_find_feature (info.target_desc,
> +					"org.gnu.gdb.mips.dsp");

Please add this to the manual section describing MIPS target features.

> Index: binutils-quilt/src/gdb/inf-ptrace.c
> ===================================================================
> --- binutils-quilt.orig/src/gdb/inf-ptrace.c	2007-12-07 15:08:21.000000000 +0000
> +++ binutils-quilt/src/gdb/inf-ptrace.c	2007-12-07 15:13:02.000000000 +0000

Using a target description that accurately describes the target should
eliminate the need for these.

> Index: binutils-quilt/src/gdb/features/mips-linux.xml
> ===================================================================
> --- binutils-quilt.orig/src/gdb/features/mips-linux.xml	2007-12-07 15:08:21.000000000 +0000
> +++ binutils-quilt/src/gdb/features/mips-linux.xml	2007-12-07 15:13:02.000000000 +0000
> @@ -11,6 +11,7 @@
>    <xi:include href="mips-cpu.xml"/>
>    <xi:include href="mips-cp0.xml"/>
>    <xi:include href="mips-fpu.xml"/>
> +  <xi:include href="mips-dsp.xml"/>

And a corrolary of that is that we'll have two mips-linux
descriptions, with and without the DSP registers.

> Index: binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp
> ===================================================================
> --- binutils-quilt.orig/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:01:40.000000000 +0000
> +++ binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:02:17.000000000 +0000
> @@ -33,7 +33,7 @@
>          set core-regs {arm-core.xml}
>      }
>      "mips*-*-*" {
> -	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml}
> +	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml mips-dsp.xml}
>      }
>      "powerpc*-*-*" {
>  	set regdir "rs6000/"

No need for this, since a MIPS target without the DSP registers is
still valid.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2007-12-18 13:42 ` Daniel Jacobowitz
@ 2007-12-18 13:56   ` Nigel Stephens
  2007-12-18 15:15     ` Daniel Jacobowitz
  2008-03-19 17:07   ` Maciej W. Rozycki
  1 sibling, 1 reply; 13+ messages in thread
From: Nigel Stephens @ 2007-12-18 13:56 UTC (permalink / raw)
  To: drow; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki



Daniel Jacobowitz wrote:
>
>   
>> Index: binutils-quilt/src/gdb/features/mips-linux.xml
>> ===================================================================
>> --- binutils-quilt.orig/src/gdb/features/mips-linux.xml	2007-12-07 15:08:21.000000000 +0000
>> +++ binutils-quilt/src/gdb/features/mips-linux.xml	2007-12-07 15:13:02.000000000 +0000
>> @@ -11,6 +11,7 @@
>>    <xi:include href="mips-cpu.xml"/>
>>    <xi:include href="mips-cp0.xml"/>
>>    <xi:include href="mips-fpu.xml"/>
>> +  <xi:include href="mips-dsp.xml"/>
>>     
>
> And a corrolary of that is that we'll have two mips-linux
> descriptions, with and without the DSP registers.
>   

Sounds like this mechanism could rapidly get unwieldy if there were many
disjoint, optional register sets supported by an architecture -- would
you need a different description for each possible permutation? For
example with a bare-iron target you might want to omit the
floating-point register descriptions for CPUs which don't have a h/w
FPU, so then we've got Base, Base+FPU, Base+DSP, Base+FPU+DSP. Then
double again for 32-bit vs 64-bit, and so on. Or have I missed something.

Nigel


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2007-12-18 13:56   ` Nigel Stephens
@ 2007-12-18 15:15     ` Daniel Jacobowitz
  2007-12-18 16:06       ` Nigel Stephens
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2007-12-18 15:15 UTC (permalink / raw)
  To: Nigel Stephens; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Tue, Dec 18, 2007 at 01:41:44PM +0000, Nigel Stephens wrote:
> Sounds like this mechanism could rapidly get unwieldy if there were many
> disjoint, optional register sets supported by an architecture -- would
> you need a different description for each possible permutation? For
> example with a bare-iron target you might want to omit the
> floating-point register descriptions for CPUs which don't have a h/w
> FPU, so then we've got Base, Base+FPU, Base+DSP, Base+FPU+DSP. Then
> double again for 32-bit vs 64-bit, and so on. Or have I missed something.

You have, but it's a very small thing.

The hand-written descriptions in the GDB source code serve three
purposes.  They are used for gdbserver (which could be made smarter);
they are used for GDB (but only to eliminate the build dependency on
expat); and they are used as canonical examples for stub writers.

There's at least two ways we could support a large set of combinations
in GDB.  One is to require expat, provide XML files at the feature
level, and generate the top level target description using strcat
(one of CodeSourcery's stubs does it this way).   The other is to
adjust the precompiling process, which currently generates a callable
C function per target description, to generate functions at the
feature level and call those from within GDB.  That's a bit nicer.

Since so far we only support MIPS with an attached FPU (due to change
somewhere in MTI's GDB patch collection, I think?) there's only four
descriptions, so no one's bothered to do that flexibility yet.  But
the framework is there when we need it :-)

gdbserver is not very bright; its register set is selected entirely at
compile time and the C parts know a bit about the layout of the XML
parts.  Eventually, it's going to grow multiple description support
just like GDB, I think.  I just haven't needed it yet.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2007-12-18 15:15     ` Daniel Jacobowitz
@ 2007-12-18 16:06       ` Nigel Stephens
  0 siblings, 0 replies; 13+ messages in thread
From: Nigel Stephens @ 2007-12-18 16:06 UTC (permalink / raw)
  To: drow; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki



Daniel Jacobowitz wrote:
> On Tue, Dec 18, 2007 at 01:41:44PM +0000, Nigel Stephens wrote:
>   
>> Sounds like this mechanism could rapidly get unwieldy if there were many
>> disjoint, optional register sets supported by an architecture -- would
>> you need a different description for each possible permutation? For
>> example with a bare-iron target you might want to omit the
>> floating-point register descriptions for CPUs which don't have a h/w
>> FPU, so then we've got Base, Base+FPU, Base+DSP, Base+FPU+DSP. Then
>> double again for 32-bit vs 64-bit, and so on. Or have I missed something.
>>     
>
> You have, but it's a very small thing.
>
> The hand-written descriptions in the GDB source code serve three
> purposes.  They are used for gdbserver (which could be made smarter);
> they are used for GDB (but only to eliminate the build dependency on
> expat); and they are used as canonical examples for stub writers.
>
> There's at least two ways we could support a large set of combinations
> in GDB.  One is to require expat, provide XML files at the feature
> level, and generate the top level target description using strcat
> (one of CodeSourcery's stubs does it this way).   The other is to
> adjust the precompiling process, which currently generates a callable
> C function per target description, to generate functions at the
> feature level and call those from within GDB.  That's a bit nicer.
>   

Yes, FWIW my vote would be for function per feature.


> Since so far we only support MIPS with an attached FPU (due to change
> somewhere in MTI's GDB patch collection, I think?) there's only four
> descriptions, so no one's bothered to do that flexibility yet.  But
> the framework is there when we need it :-)
>
> gdbserver is not very bright; its register set is selected entirely at
> compile time and the C parts know a bit about the layout of the XML
> parts.  Eventually, it's going to grow multiple description support
> just like GDB, I think.  I just haven't needed it yet.
>
>   

OK, thanks.

Nigel


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2007-12-18 13:42 ` Daniel Jacobowitz
  2007-12-18 13:56   ` Nigel Stephens
@ 2008-03-19 17:07   ` Maciej W. Rozycki
  2008-03-21 18:44     ` Daniel Jacobowitz
  1 sibling, 1 reply; 13+ messages in thread
From: Maciej W. Rozycki @ 2008-03-19 17:07 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Mon, 17 Dec 2007, Daniel Jacobowitz wrote:

> >  In particular, ptrace() calls may return a failure when called on a 
> > system that does not support the ASE.  In such a case the registers are 
> > marked as unavailable in the cache which has the effect of them being 
> > hardwired to zero (I have a patch in the queue that would mark them 
> > specially in the output; I will submit it later).
> 
> We have an even better way to handle this, nowadays.  Take a look at
> arm-linux-nat.c:arm_linux_read_description.  This lets the registers
> be completely hidden when they are not available.

 Thanks for the hint -- I have taken it into account.

> > +/* Names of Linux registers.  */
> > +static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
> > +  "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", "hi1", "lo1", "hi2", "lo2", "hi3", "lo3",
> > +  "dspctl",
> > +};
> 
> If you're using a target description wherever you support these
> registers, then you shouldn't need another copy of them here.

 Well, I would have thought so, but before "run" is used 
mips_gdbarch_init() is called with the target description being 
unavailable.  I feel a bit uneasy about some default target configuration 
being selected in this case.

> > @@ -5270,11 +5341,11 @@
> >  
> >  
> >        valid_p &= tdesc_numbered_register (feature, tdesc_data,
> > -					  MIPS_EMBED_LO_REGNUM, "lo");
> > +					  mips_regnum.lo, "lo");
> 
> I went to a bit of trouble to be able to use constants here, please
> don't go back the other direction.  When all the raw registers use
> constant numbering, it's much easier to manage the GDB backend.

 The offsets are different for Linux and bare-iron; there is no way to go 
back as far as I can tell.  Suggestions are welcome.

> > +      if (mips_regnum.dspacc >= 0)
> > +	{
> > +	  feature = tdesc_find_feature (info.target_desc,
> > +					"org.gnu.gdb.mips.dsp");
> 
> Please add this to the manual section describing MIPS target features.

 Certainly.

> > Index: binutils-quilt/src/gdb/inf-ptrace.c
> > ===================================================================
> > --- binutils-quilt.orig/src/gdb/inf-ptrace.c	2007-12-07 15:08:21.000000000 +0000
> > +++ binutils-quilt/src/gdb/inf-ptrace.c	2007-12-07 15:13:02.000000000 +0000
> 
> Using a target description that accurately describes the target should
> eliminate the need for these.

 Done.

> > Index: binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp
> > ===================================================================
> > --- binutils-quilt.orig/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:01:40.000000000 +0000
> > +++ binutils-quilt/src/gdb/testsuite/gdb.xml/tdesc-regs.exp	2007-12-07 17:02:17.000000000 +0000
> > @@ -33,7 +33,7 @@
> >          set core-regs {arm-core.xml}
> >      }
> >      "mips*-*-*" {
> > -	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml}
> > +	set core-regs {mips-cpu.xml mips-cp0.xml mips-fpu.xml mips-dsp.xml}
> >      }
> >      "powerpc*-*-*" {
> >  	set regdir "rs6000/"
> 
> No need for this, since a MIPS target without the DSP registers is
> still valid.

 Removed now.

 Thanks for you review.  Here is a new version.

gdb:/
2008-03-19  Maciej W. Rozycki  <macro@mips.com>
            Chris Dearman  <chris@mips.com>

	* features/mips-dsp.xml: New file for DSP ASE registers.
	* features/mips64-dsp.xml: Likewise.
	* features/mips-linux.xml: Specify "regnum" for "restart"
	explicitly.
	* features/mips64-linux.xml: Likewise.
	* features/mips-dsp-linux.xml: New file for a DSP-enabled
	target.
	* features/mips64-dsp-linux.xml: Likewise.
	* features/mips-linux.c: Regenerate.
	* features/mips64-linux.c: Regenerate.
	* features/mips-dsp-linux.c: New generated file.
	* features/mips64-dsp-linux.c: Likewise.
	* mips-linux-nat.c: Include the new DSP target descriptions.
	(super_fetch_registers): Mark static.
	(super_store_registers): Likewise.
	(mips_linux_register_addr): Handle DSP registers.
	(mips64_linux_register_addr): Likewise.
	(mips64_linux_regsets_fetch_registers): Likewise.
	(mips64_linux_regsets_store_registers): Likewise.
	(mips_linux_read_description): Check for the presence of the
	DSP ASE and select the target description accordingly.
	(_initialize_mips_linux_nat): Initialize the new DSP target
	descriptions.
	* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
	Remove padding as the register array does not use the layout
	defined for embedded targets anymore.
	* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
	* mips-tdep.c (NUM_MIPS_PROCESSOR_REGS): Set from
	MIPS_LAST_EMBED_REGNUM.
	(mips_generic_reg_names): Remove trailing null strings.
	(mips_tx39_reg_names): Likewise.
	(mips_linux_reg_names): New array of register names for Linux
	targets.
	(mips_register_name): Check for a null pointer in
	mips_processor_reg_names and return an empty string.
	(mips_stab_reg_to_regnum): Handle the DSP accumulators.
	(mips_dwarf_dwarf2_ecoff_reg_to_regnum): Likewise.
	(mips_gdbarch_init): Likewise.  Handle the DSP ASE control
	register.  Initialize internal register indices for Linux.  Use
	MIPS_LAST_EMBED_REGNUM as appropriate.
	* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.
	(MIPS_EMBED_CP2_REGNUM): Offset to CP2 registers.
	(MIPS_EMBED_DSPACC_REGNUM): Offset to DSP accumulator registers.
	(MIPS_EMBED_DSPCTL_REGNUM): Offset to DSP control registers.
	(MIPS_LAST_EMBED_REGNUM): Update accordingly.
	(MIPS_EMBED_NUM_REGS): New value to make sure that an even
	number of registers is used.
	* regcache.c (regcache_invalidate): Allow for an arbitrary
	setting of the cache state and replace with a wrapper to call
	the original function renamed to...
	(regcache_set_valid_p): ... this.
	* regcache.h (regcache_set_valid_p): New prototype.
	* Makefile.in (mips_dsp_linux_c): New variable.
	(mips64_dsp_linux_c): Likewise.
	(mips-linux-nat.o): Depend on $(mips_dsp_linux_c) and
	$(mips64_dsp_linux_c).
	* features/Makefile (WHICH): Add "mips-dsp-linux" and
	"mips64-dsp-linux".
	(mips-dsp-linux-expedite): New variable.
	(mips64-dsp-linux-expedite): Likewise.

gdb/doc/:
2008-03-19  Maciej W. Rozycki  <macro@mips.com>

	* gdb.texinfo (MIPS Features): Document org.gnu.gdb.mips.dsp.

  Maciej

14607.diff
Index: binutils-quilt/src/gdb/mips-linux-nat.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-nat.c	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-nat.c	2008-03-18 16:57:45.000000000 +0000
@@ -19,6 +19,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdb_assert.h"
+#include "gdb_stdint.h"
 #include "inferior.h"
 #include "mips-tdep.h"
 #include "target.h"
@@ -34,7 +36,9 @@
 #include <sys/ptrace.h>
 
 #include "features/mips-linux.c"
+#include "features/mips-dsp-linux.c"
 #include "features/mips64-linux.c"
+#include "features/mips64-dsp-linux.c"
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
@@ -47,8 +51,8 @@
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
-void (*super_fetch_registers) (struct regcache *, int);
-void (*super_store_registers) (struct regcache *, int);
+static void (*super_fetch_registers) (struct regcache *, int);
+static void (*super_store_registers) (struct regcache *, int);
 
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are normally defined in <asm/ptrace.h>. 
@@ -84,6 +88,13 @@
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 6)
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -119,6 +130,13 @@
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 6)
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -192,7 +210,8 @@
 mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -205,11 +224,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 6)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -245,16 +275,30 @@
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 6;
+	     regi++)
+	  super_fetch_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_fetch_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
    using PTRACE_SETREGS et al.  */
 
 static void
-mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
+mips64_linux_regsets_store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -267,11 +311,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 6)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -298,6 +353,19 @@
 		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
+
+  if (is_dsp)
+    super_store_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 6;
+	     regi++)
+	  super_store_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_store_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
@@ -347,12 +415,29 @@
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  struct gdbarch *gdbarch = current_gdbarch;
+  CORE_ADDR addr;
+  int has_dsp;
+  int tid;
+
+  addr = mips_linux_register_u_offset (gdbarch,
+				       mips_regnum (gdbarch)->dspctl, 0);
+  gdb_assert (addr != (CORE_ADDR) -1);
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  errno = 0;
+  ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (uintptr_t) addr, 0);
+  has_dsp = (errno == 0);
+
   /* Report that target registers are a size we know for sure
      that we can get from ptrace.  */
-  if (_MIPS_SIM == _ABIO32)
-    return tdesc_mips_linux;
+  if (mips_abi_regsize (gdbarch) == 8)
+    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
   else
-    return tdesc_mips64_linux;
+    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
 }
 
 void _initialize_mips_linux_nat (void);
@@ -374,5 +459,7 @@
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
+  initialize_tdesc_mips_dsp_linux ();
   initialize_tdesc_mips64_linux ();
+  initialize_tdesc_mips64_dsp_linux ();
 }
Index: binutils-quilt/src/gdb/mips-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.c	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c	2008-03-18 16:57:45.000000000 +0000
@@ -436,7 +436,7 @@
    are listed in the following tables.  */
 
 enum
-{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+{ NUM_MIPS_PROCESSOR_REGS = (MIPS_LAST_EMBED_REGNUM + 1 - 32) };
 
 /* Generic MIPS.  */
 
@@ -446,9 +446,7 @@
   "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" */ , "",
-  "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "",
+  "fsr", "fir",
 };
 
 /* Names of IDT R3041 registers.  */
@@ -474,7 +472,7 @@
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -486,6 +484,17 @@
   "pc", "cause", "bad", "hi", "lo", "fsr", "fir"
 };
 
+/* Names of Linux registers.  */
+static const char *mips_linux_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
+  "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", "hi1", "lo1", "hi2", "lo2", "hi3", "lo3",
+  "dspctl",
+};
+
 
 /* Return the name of the register corresponding to REGNO.  */
 static const char *
@@ -531,7 +540,9 @@
   else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
     {
       gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
-      return tdep->mips_processor_reg_names[rawnum - 32];
+      if (tdep->mips_processor_reg_names[rawnum - 32])
+	return tdep->mips_processor_reg_names[rawnum - 32];
+      return "";
     }
   else
     internal_error (__FILE__, __LINE__,
@@ -5085,6 +5096,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 72 && num < 78)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 72;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
@@ -5108,6 +5121,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 66 && num < 72)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 66;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
@@ -5241,10 +5256,66 @@
   struct gdbarch_tdep *tdep;
   int elf_flags;
   enum mips_abi mips_abi, found_abi, wanted_abi;
-  int i, num_regs;
+  int i, num_regs, dsp_space;
   enum mips_fpu_type fpu_type;
   struct tdesc_arch_data *tdesc_data = NULL;
   int elf_fpu_type = 0;
+  const char **reg_names;
+  struct mips_regnum mips_regnum, *regnum;
+
+  /* Fill in the OS dependant register numbers and names.  */
+  if (info.osabi == GDB_OSABI_IRIX)
+    {
+      mips_regnum.fp0 = 32;
+      mips_regnum.pc = 64;
+      mips_regnum.cause = 65;
+      mips_regnum.badvaddr = 66;
+      mips_regnum.hi = 67;
+      mips_regnum.lo = 68;
+      mips_regnum.fp_control_status = 69;
+      mips_regnum.fp_implementation_revision = 70;
+      mips_regnum.dspacc = 0;
+      mips_regnum.dspctl = 0;
+      dsp_space = 0;
+      num_regs = 71;
+      reg_names = mips_irix_reg_names;
+    }
+  else if (info.osabi == GDB_OSABI_LINUX)
+    {
+      mips_regnum.fp0 = 38;
+      mips_regnum.pc = 37;
+      mips_regnum.cause = 36;
+      mips_regnum.badvaddr = 35;
+      mips_regnum.hi = 34;
+      mips_regnum.lo = 33;
+      mips_regnum.fp_control_status = 70;
+      mips_regnum.fp_implementation_revision = 71;
+      mips_regnum.dspacc = 72;
+      mips_regnum.dspctl = 78;
+      dsp_space = 0;
+      num_regs = 79;
+      reg_names = mips_linux_reg_names;
+    }
+  else
+    {
+      mips_regnum.lo = MIPS_EMBED_LO_REGNUM;
+      mips_regnum.hi = MIPS_EMBED_HI_REGNUM;
+      mips_regnum.badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
+      mips_regnum.cause = MIPS_EMBED_CAUSE_REGNUM;
+      mips_regnum.pc = MIPS_EMBED_PC_REGNUM;
+      mips_regnum.fp0 = MIPS_EMBED_FP0_REGNUM;
+      mips_regnum.fp_control_status = 70;
+      mips_regnum.fp_implementation_revision = 71;
+      mips_regnum.dspacc = MIPS_EMBED_DSPACC_REGNUM;
+      mips_regnum.dspctl = MIPS_EMBED_DSPCTL_REGNUM;
+      dsp_space = 1;
+      num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+      if (info.bfd_arch_info != NULL
+          && info.bfd_arch_info->mach == bfd_mach_mips3900)
+        reg_names = mips_tx39_reg_names;
+      else
+        reg_names = mips_generic_reg_names;
+    }
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -5279,11 +5350,11 @@
 
 
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_LO_REGNUM, "lo");
+					  mips_regnum.lo, "lo");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_HI_REGNUM, "hi");
+					  mips_regnum.hi, "hi");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_PC_REGNUM, "pc");
+					  mips_regnum.pc, "pc");
 
       if (!valid_p)
 	{
@@ -5301,12 +5372,11 @@
 
       valid_p = 1;
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_BADVADDR_REGNUM,
-					  "badvaddr");
+					  mips_regnum.badvaddr, "badvaddr");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
 					  MIPS_PS_REGNUM, "status");
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_CAUSE_REGNUM, "cause");
+					  mips_regnum.cause, "cause");
 
       if (!valid_p)
 	{
@@ -5327,13 +5397,15 @@
       valid_p = 1;
       for (i = 0; i < 32; i++)
 	valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					    i + MIPS_EMBED_FP0_REGNUM,
-					    mips_fprs[i]);
+					    i + mips_regnum.fp0, mips_fprs[i]);
 
       valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_FP0_REGNUM + 32, "fcsr");
-      valid_p &= tdesc_numbered_register (feature, tdesc_data,
-					  MIPS_EMBED_FP0_REGNUM + 33, "fir");
+					  mips_regnum.fp_control_status,
+					  "fcsr");
+      valid_p
+	&= tdesc_numbered_register (feature, tdesc_data,
+				    mips_regnum.fp_implementation_revision,
+				    "fir");
 
       if (!valid_p)
 	{
@@ -5341,8 +5413,48 @@
 	  return NULL;
 	}
 
+      /* The DSP registers are optional.  Handle the lack of them
+         gracefully.  */
+      feature = tdesc_find_feature (info.target_desc,
+				    "org.gnu.gdb.mips.dsp");
+      if (feature == NULL)
+	{
+	  mips_regnum.dspacc = 0;
+	  mips_regnum.dspctl = 0;
+	}
+
+      if (mips_regnum.dspacc != 0)
+	{
+	  valid_p = 1;
+	  i = dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo1");
+	  i += dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo2");
+	  i += dsp_space;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "hi3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspacc + i++, "lo3");
+
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      mips_regnum.dspctl, "dspctl");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
+      reg_names = NULL;
     }
 
   /* First of all, extract the elf_flags, if available.  */
@@ -5581,66 +5693,19 @@
   set_gdbarch_elf_make_msymbol_special (gdbarch,
 					mips_elf_make_msymbol_special);
 
-  /* Fill in the OS dependant register numbers and names.  */
-  {
-    const char **reg_names;
-    struct mips_regnum *regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch,
-							 struct mips_regnum);
-    if (tdesc_has_registers (info.target_desc))
-      {
-	regnum->lo = MIPS_EMBED_LO_REGNUM;
-	regnum->hi = MIPS_EMBED_HI_REGNUM;
-	regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
-	regnum->cause = MIPS_EMBED_CAUSE_REGNUM;
-	regnum->pc = MIPS_EMBED_PC_REGNUM;
-	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
-	regnum->fp_control_status = 70;
-	regnum->fp_implementation_revision = 71;
-	num_regs = MIPS_LAST_EMBED_REGNUM + 1;
-	reg_names = NULL;
-      }
-    else if (info.osabi == GDB_OSABI_IRIX)
-      {
-	regnum->fp0 = 32;
-	regnum->pc = 64;
-	regnum->cause = 65;
-	regnum->badvaddr = 66;
-	regnum->hi = 67;
-	regnum->lo = 68;
-	regnum->fp_control_status = 69;
-	regnum->fp_implementation_revision = 70;
-	num_regs = 71;
-	reg_names = mips_irix_reg_names;
-      }
-    else
-      {
-	regnum->lo = MIPS_EMBED_LO_REGNUM;
-	regnum->hi = MIPS_EMBED_HI_REGNUM;
-	regnum->badvaddr = MIPS_EMBED_BADVADDR_REGNUM;
-	regnum->cause = MIPS_EMBED_CAUSE_REGNUM;
-	regnum->pc = MIPS_EMBED_PC_REGNUM;
-	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
-	regnum->fp_control_status = 70;
-	regnum->fp_implementation_revision = 71;
-	num_regs = 90;
-	if (info.bfd_arch_info != NULL
-	    && info.bfd_arch_info->mach == bfd_mach_mips3900)
-	  reg_names = mips_tx39_reg_names;
-	else
-	  reg_names = mips_generic_reg_names;
-      }
-    /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been
-       replaced by read_pc?  */
-    set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
-    set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
-    set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
-    set_gdbarch_num_regs (gdbarch, num_regs);
-    set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
-    set_gdbarch_register_name (gdbarch, mips_register_name);
-    set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer);
-    tdep->mips_processor_reg_names = reg_names;
-    tdep->regnum = regnum;
-  }
+  regnum = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct mips_regnum);
+  *regnum = mips_regnum;
+  /* FIXME: cagney/2003-11-15: For MIPS, hasn't gdbarch_pc_regnum been
+     replaced by read_pc?  */
+  set_gdbarch_pc_regnum (gdbarch, regnum->pc + num_regs);
+  set_gdbarch_sp_regnum (gdbarch, MIPS_SP_REGNUM + num_regs);
+  set_gdbarch_fp0_regnum (gdbarch, regnum->fp0);
+  set_gdbarch_num_regs (gdbarch, num_regs);
+  set_gdbarch_num_pseudo_regs (gdbarch, num_regs);
+  set_gdbarch_register_name (gdbarch, mips_register_name);
+  set_gdbarch_virtual_frame_pointer (gdbarch, mips_virtual_frame_pointer);
+  tdep->mips_processor_reg_names = reg_names;
+  tdep->regnum = regnum;
 
   switch (mips_abi)
     {
Index: binutils-quilt/src/gdb/mips-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.h	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.h	2008-03-18 16:57:45.000000000 +0000
@@ -53,6 +53,8 @@
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
   int lo;		/* ...  */
+  int dspacc;		/* SmartMIPS/DSP accumulators.  */
+  int dspctl;		/* DSP control.  */
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
@@ -75,9 +77,26 @@
   MIPS_EMBED_PC_REGNUM = 37,
   MIPS_EMBED_FP0_REGNUM = 38,
   MIPS_UNUSED_REGNUM = 73,	/* Never used, FIXME */
-  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP0 register for embedded use.  */
-  MIPS_PRID_REGNUM = 89,	/* Processor ID.  */
-  MIPS_LAST_EMBED_REGNUM = 89	/* Last one.  */
+  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP register for embedded use.  */
+  MIPS_EMBED_CP0_REGNUM = MIPS_FIRST_EMBED_REGNUM,
+				/* CP0 data registers: 8 banks of 32.  */
+  MIPS_PRID_REGNUM = (MIPS_EMBED_CP0_REGNUM + 15),
+				/* Processor ID.  */
+  MIPS_EMBED_CP2_REGNUM = (MIPS_EMBED_CP0_REGNUM + 8 * 32),
+				/* CP2 data registers: 8 banks of 32.  */
+  MIPS_EMBED_CP2CTL_REGNUM = (MIPS_EMBED_CP2_REGNUM + 8 * 32),
+				/* CP2 control registers: 32.  */
+  MIPS_EMBED_DSPACC_REGNUM = (MIPS_EMBED_CP2CTL_REGNUM + 32),
+				/* DSP/SmartMIPS registers:
+				   ACX, Hi1, Lo1, ACX1,
+				   Hi2, Lo2, ACX2, Hi3, Lo3, ACX3.  */
+  MIPS_EMBED_DSPCTL_REGNUM = (MIPS_EMBED_DSPACC_REGNUM + 10),
+				/* DSP DSPCTL0..1 registers.  */
+  MIPS_EMBED_NUM_REGS = (MIPS_EMBED_DSPCTL_REGNUM + 2),
+				/* Total number of actual registers.  */
+  MIPS_LAST_EMBED_REGNUM
+    = ((MIPS_EMBED_NUM_REGS + MIPS_EMBED_NUM_REGS % 2) - 1)
+				/* Last one, including padding to even.  */
 };
 
 /* Defined in mips-tdep.c and used in remote-mips.c */
Index: binutils-quilt/src/gdb/mips-linux-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.c	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.c	2008-03-18 16:57:45.000000000 +0000
@@ -112,14 +112,6 @@
   supply_32bit_reg (regcache, MIPS_PS_REGNUM, regp + EF_CP0_STATUS);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into an elf_gregset_t.  */
@@ -325,14 +317,6 @@
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
Index: binutils-quilt/src/gdb/mips-linux-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.h	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.h	2008-03-18 16:57:45.000000000 +0000
@@ -36,6 +36,8 @@
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71
+#define DSP_CONTROL	77
 
 #define EF_REG0			6
 #define EF_REG31		37
Index: binutils-quilt/src/gdb/features/mips-linux.xml
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips-linux.xml	2008-03-18 16:48:10.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-linux.xml	2008-03-18 16:57:45.000000000 +0000
@@ -13,6 +13,6 @@
   <xi:include href="mips-fpu.xml"/>
 
   <feature name="org.gnu.gdb.mips.linux">
-    <reg name="restart" bitsize="32" group="system"/>
+    <reg name="restart" bitsize="32" group="system" regnum="79"/>
   </feature>
 </target>
Index: binutils-quilt/src/gdb/features/mips64-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp.xml	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="64" regnum="72"/>
+  <reg name="lo1" bitsize="64" regnum="73"/>
+  <reg name="hi2" bitsize="64" regnum="74"/>
+  <reg name="lo2" bitsize="64" regnum="75"/>
+  <reg name="hi3" bitsize="64" regnum="76"/>
+  <reg name="lo3" bitsize="64" regnum="77"/>
+
+  <reg name="dspctl" bitsize="32" regnum="78"/>
+</feature>
Index: binutils-quilt/src/gdb/features/mips64-linux.xml
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips64-linux.xml	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-linux.xml	2008-03-18 16:57:45.000000000 +0000
@@ -13,6 +13,6 @@
   <xi:include href="mips64-fpu.xml"/>
 
   <feature name="org.gnu.gdb.mips.linux">
-    <reg name="restart" bitsize="64" group="system"/>
+    <reg name="restart" bitsize="64" group="system" regnum="79"/>
   </feature>
 </target>
Index: binutils-quilt/src/gdb/features/mips-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp.xml	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="32" regnum="72"/>
+  <reg name="lo1" bitsize="32" regnum="73"/>
+  <reg name="hi2" bitsize="32" regnum="74"/>
+  <reg name="lo2" bitsize="32" regnum="75"/>
+  <reg name="hi3" bitsize="32" regnum="76"/>
+  <reg name="lo3" bitsize="32" regnum="77"/>
+
+  <reg name="dspctl" bitsize="32" regnum="78"/>
+</feature>
Index: binutils-quilt/src/gdb/regcache.c
===================================================================
--- binutils-quilt.orig/src/gdb/regcache.c	2008-03-18 16:48:10.000000000 +0000
+++ binutils-quilt/src/gdb/regcache.c	2008-03-18 16:57:45.000000000 +0000
@@ -398,16 +398,24 @@
   return regcache->register_valid_p[regnum];
 }
 
+/* Record that REGNUM's value is cached if STATE is >0, uncached but
+   fetchable if STATE is 0, and uncached and unfetchable if STATE is <0.  */
+
 void
-regcache_invalidate (struct regcache *regcache, int regnum)
+regcache_set_valid_p (struct regcache *regcache, int regnum, int state)
 {
   gdb_assert (regcache != NULL);
   gdb_assert (regnum >= 0);
   gdb_assert (!regcache->readonly_p);
   gdb_assert (regnum < regcache->descr->nr_raw_registers);
-  regcache->register_valid_p[regnum] = 0;
+  regcache->register_valid_p[regnum] = state;
 }
 
+void
+regcache_invalidate (struct regcache *regcache, int regnum)
+{
+  regcache_set_valid_p (regcache, regnum, 0);
+}
 
 /* Global structure containing the current regcache.  */
 /* FIXME: cagney/2002-05-11: The two global arrays registers[] and
Index: binutils-quilt/src/gdb/regcache.h
===================================================================
--- binutils-quilt.orig/src/gdb/regcache.h	2008-03-18 16:48:10.000000000 +0000
+++ binutils-quilt/src/gdb/regcache.h	2008-03-18 16:57:45.000000000 +0000
@@ -60,6 +60,8 @@
 
 int regcache_valid_p (const struct regcache *regcache, int regnum);
 
+void regcache_set_valid_p (struct regcache *regcache, int regnum, int state);
+
 void regcache_invalidate (struct regcache *regcache, int regnum);
 
 /* Transfer a cooked register [0..NUM_REGS+NUM_PSEUDO_REGS).  */
Index: binutils-quilt/src/gdb/features/mips64-linux.c
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips64-linux.c	2008-03-18 16:48:10.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-linux.c	2008-03-18 16:57:45.000000000 +0000
@@ -93,7 +93,7 @@
   tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 64, "int");
 
   tdesc_mips64_linux = result;
 }
Index: binutils-quilt/src/gdb/features/mips-linux.c
===================================================================
--- binutils-quilt.orig/src/gdb/features/mips-linux.c	2008-03-18 16:48:10.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-linux.c	2008-03-18 16:57:45.000000000 +0000
@@ -93,7 +93,7 @@
   tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
-  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 32, "int");
 
   tdesc_mips_linux = result;
 }
Index: binutils-quilt/src/gdb/Makefile.in
===================================================================
--- binutils-quilt.orig/src/gdb/Makefile.in	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/Makefile.in	2008-03-18 16:57:45.000000000 +0000
@@ -960,7 +960,9 @@
 features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
 arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
 mips_linux_c = $(srcdir)/features/mips-linux.c $(features_headers)
+mips_dsp_linux_c = $(srcdir)/features/mips-dsp-linux.c $(features_headers)
 mips64_linux_c = $(srcdir)/features/mips64-linux.c $(features_headers)
+mips64_dsp_linux_c = $(srcdir)/features/mips64-dsp-linux.c $(features_headers)
 powerpc_32_c = $(srcdir)/features/rs6000/powerpc-32.c $(features_headers)
 powerpc_403_c = $(srcdir)/features/rs6000/powerpc-403.c $(features_headers)
 powerpc_403gc_c = $(srcdir)/features/rs6000/powerpc-403gc.c $(features_headers)
@@ -2472,7 +2474,8 @@
 mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \
 	$(regcache_h) $(linux_nat_h) $(gdb_proc_service_h) $(gregset_h) \
 	$(mips_linux_tdep_h) $(inferior_h) $(target_descriptions_h) \
-	$(mips_linux_c) $(mips64_linux_c)
+	$(mips_linux_c) $(mips_dsp_linux_c) \
+	$(mips64_dsp_linux_c) $(mips64_dsp_linux_c)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
 	$(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \
Index: binutils-quilt/src/gdb/features/Makefile
===================================================================
--- binutils-quilt.orig/src/gdb/features/Makefile	2008-03-18 16:48:09.000000000 +0000
+++ binutils-quilt/src/gdb/features/Makefile	2008-03-18 16:57:45.000000000 +0000
@@ -31,13 +31,16 @@
 # in the GDB repository.  To generate C files:
 #   make GDB=/path/to/gdb XMLTOC="xml files" cfiles
 
-WHICH = arm-with-iwmmxt mips-linux mips64-linux \
+WHICH = arm-with-iwmmxt \
+	mips-linux mips-dsp-linux mips64-linux mips64-dsp-linux \
 	rs6000/powerpc-32 rs6000/powerpc-e500 rs6000/powerpc-64
 
 # Record which registers should be sent to GDB by default after stop.
 arm-with-iwmmxt-expedite = r11,sp,pc
 mips-linux-expedite = r29,pc
+mips-dsp-linux-expedite = r29,pc
 mips64-linux-expedite = r29,pc
+mips64-dsp-linux-expedite = r29,pc
 rs6000/powerpc-32-expedite = r1,pc
 rs6000/powerpc-e500-expedite = r1,pc
 rs6000/powerpc-64-expedite = r1,pc
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.c	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_dsp_linux;
+static void
+initialize_tdesc_mips_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 32, "int");
+
+  tdesc_mips_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.xml	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu.xml"/>
+  <xi:include href="mips-dsp.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system" regnum="79"/>
+  </feature>
+</target>
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.c	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips64-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_dsp_linux;
+static void
+initialize_tdesc_mips64_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 72, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 78, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 79, 1, "system", 64, "int");
+
+  tdesc_mips64_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.xml	2008-03-18 16:57:45.000000000 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+  <xi:include href="mips64-dsp.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system" regnum="79"/>
+  </feature>
+</target>
Index: binutils-quilt/src/gdb/doc/gdb.texinfo
===================================================================
--- binutils-quilt.orig/src/gdb/doc/gdb.texinfo	2008-03-18 16:43:42.000000000 +0000
+++ binutils-quilt/src/gdb/doc/gdb.texinfo	2008-03-18 16:57:45.000000000 +0000
@@ -26803,6 +26803,10 @@
 contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and
 @samp{fir}.  They may be 32-bit or 64-bit depending on the target.
 
+The @samp{org.gnu.gdb.mips.dsp} feature is optional.  If present, it
+should contain registers @samp{lo1} through @samp{lo3}, @samp{hi1}
+through @samp{hi3}, and @samp{dspctl}.
+
 The @samp{org.gnu.gdb.mips.linux} feature is optional.  It should
 contain a single register, @samp{restart}, which is used by the
 Linux kernel to control restartable syscalls.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-19 17:07   ` Maciej W. Rozycki
@ 2008-03-21 18:44     ` Daniel Jacobowitz
  2008-03-26 16:59       ` Maciej W. Rozycki
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2008-03-21 18:44 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Wed, Mar 19, 2008 at 05:06:01PM +0000, Maciej W. Rozycki wrote:
>  Well, I would have thought so, but before "run" is used 
> mips_gdbarch_init() is called with the target description being 
> unavailable.  I feel a bit uneasy about some default target configuration 
> being selected in this case.

That's how our initialization is supposed to work, though.  A minimal
description is used until we know exactly what we're talking to.  If
you need that minimal description to include the new DSP registers,
one way to do it is to rely on the XML description by default if none
is provided - that's what I did for PowerPC.

Anyway, this is a small issue.  Except it's tangled up with...

> > > @@ -5270,11 +5341,11 @@
> > >  
> > >  
> > >        valid_p &= tdesc_numbered_register (feature, tdesc_data,
> > > -					  MIPS_EMBED_LO_REGNUM, "lo");
> > > +					  mips_regnum.lo, "lo");
> > 
> > I went to a bit of trouble to be able to use constants here, please
> > don't go back the other direction.  When all the raw registers use
> > constant numbering, it's much easier to manage the GDB backend.
> 
>  The offsets are different for Linux and bare-iron; there is no way to go 
> back as far as I can tell.  Suggestions are welcome.

...this.  The register numbers don't have to be different.  You've
added a new internal register numbering for Linux; that isn't
necessary.  Where are Linux and bare metal different?  Is it in an
existing stub, and if so, what registers does that stub report?

GDB internal register numbers are used for two purposes.  They are the
default for the remote P/p and T packet numbering, and the g/G packet
ordering.  If a target description describes the registers,
tdesc_remote_register_number is used instead.  And they are passed to
GDB functions and determine the register cache layout.  This is
internal; just be consistent.

If you use fixed numbering, you don't need to juggle gdbarches and
tdeps everywhere you want a register number.  It makes things IMO
much easier to read and maintain.

The regcache.c/regcache.h bits are now unused; they were for your
inf-ptrace.c change.

Are the DSP registers always 32-bit?  It looks that way from the
current kernel.  I moved away from peekuser/pokeuser register access
because of n32 debugging issues (ptrace uses "long"), but that's not
a problem for registers which are never 64-bit.  You've added them
to 64-bit configuration XML files as 64-bit registers, which doesn't
match the kernel.

> @@ -347,12 +415,29 @@
>  static const struct target_desc *
>  mips_linux_read_description (struct target_ops *ops)
>  {
> +  struct gdbarch *gdbarch = current_gdbarch;
> +  CORE_ADDR addr;
> +  int has_dsp;
> +  int tid;
> +
> +  addr = mips_linux_register_u_offset (gdbarch,
> +				       mips_regnum (gdbarch)->dspctl, 0);
> +  gdb_assert (addr != (CORE_ADDR) -1);

We're trying to eliminate uses of the global current_gdbarch, and the
current gdbarch at this point doesn't much matter; that's why we're
about to replace it with a new gdbarch.  This is just DSP_CONTROL.

>    /* Report that target registers are a size we know for sure
>       that we can get from ptrace.  */
> -  if (_MIPS_SIM == _ABIO32)
> -    return tdesc_mips_linux;
> +  if (mips_abi_regsize (gdbarch) == 8)
> +    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
>    else
> -    return tdesc_mips64_linux;
> +    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;

And the comment still applies.  The gdbarch doesn't matter; if GDB is
built as an o32 program, then on pre-regset kernels it will not be
able to fetch 64-bit registers and all sorts of things will go wrong.
Why did you need this?

> +  MIPS_EMBED_DSPCTL_REGNUM = (MIPS_EMBED_DSPACC_REGNUM + 10),
> +				/* DSP DSPCTL0..1 registers.  */

Are there two of these?  We only handle one.  Since the internal
register numbers have no compatibility issues we can add another when
we want it.

Also, what are the the ACX registers?  You reserve space for them, but
nothing ever fills them in.  And there's no XML bits for them.

Anyway, in the interests of progress, that leaves me with the attached
patch.  This adds the DSP registers to native Linux GDB without
touching anything else.  If you also want them for an embedded stub
which does not supply XML, or for gdbserver, we can do that
separately.  I can't test this patch, so take it with a grain of salt;
I only compiled it.

-- 
Daniel Jacobowitz
CodeSourcery

Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.993
diff -u -p -r1.993 Makefile.in
--- Makefile.in	16 Mar 2008 08:50:43 -0000	1.993
+++ Makefile.in	21 Mar 2008 18:42:41 -0000
@@ -958,7 +958,9 @@ tui_winsource_h = $(srcdir)/tui/tui-wins
 features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
 arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
 mips_linux_c = $(srcdir)/features/mips-linux.c $(features_headers)
+mips_dsp_linux_c = $(srcdir)/features/mips-dsp-linux.c $(features_headers)
 mips64_linux_c = $(srcdir)/features/mips64-linux.c $(features_headers)
+mips64_dsp_linux_c = $(srcdir)/features/mips64-dsp-linux.c $(features_headers)
 powerpc_32_c = $(srcdir)/features/rs6000/powerpc-32.c $(features_headers)
 powerpc_403_c = $(srcdir)/features/rs6000/powerpc-403.c $(features_headers)
 powerpc_403gc_c = $(srcdir)/features/rs6000/powerpc-403gc.c $(features_headers)
@@ -2471,7 +2473,8 @@ mips-irix-tdep.o: mips-irix-tdep.c $(def
 mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \
 	$(regcache_h) $(linux_nat_h) $(gdb_proc_service_h) $(gregset_h) \
 	$(mips_linux_tdep_h) $(inferior_h) $(target_descriptions_h) \
-	$(mips_linux_c) $(mips64_linux_c)
+	$(mips_linux_c) $(mips_dsp_linux_c) \
+	$(mips64_dsp_linux_c) $(mips64_dsp_linux_c)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
 	$(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \
Index: mips-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-nat.c,v
retrieving revision 1.29
diff -u -p -r1.29 mips-linux-nat.c
--- mips-linux-nat.c	1 Jan 2008 22:53:12 -0000	1.29
+++ mips-linux-nat.c	21 Mar 2008 18:42:41 -0000
@@ -19,6 +19,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdb_assert.h"
+#include "gdb_stdint.h"
 #include "inferior.h"
 #include "mips-tdep.h"
 #include "target.h"
@@ -34,7 +36,9 @@
 #include <sys/ptrace.h>
 
 #include "features/mips-linux.c"
+#include "features/mips-dsp-linux.c"
 #include "features/mips64-linux.c"
+#include "features/mips64-dsp-linux.c"
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
@@ -47,8 +51,8 @@ static int have_ptrace_regsets = 1;
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
-void (*super_fetch_registers) (struct regcache *, int);
-void (*super_store_registers) (struct regcache *, int);
+static void (*super_fetch_registers) (struct regcache *, int);
+static void (*super_store_registers) (struct regcache *, int);
 
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are normally defined in <asm/ptrace.h>. 
@@ -84,6 +88,13 @@ mips_linux_register_addr (struct gdbarch
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 6)
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -119,6 +130,13 @@ mips64_linux_register_addr (struct gdbar
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 6)
+    regaddr = DSP_BASE + (regno - mips_regnum (gdbarch)->dspacc);
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -192,7 +210,8 @@ static void
 mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -205,11 +224,22 @@ mips64_linux_regsets_fetch_registers (st
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 6)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -245,16 +275,30 @@ mips64_linux_regsets_fetch_registers (st
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 6;
+	     regi++)
+	  super_fetch_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_fetch_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
    using PTRACE_SETREGS et al.  */
 
 static void
-mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
+mips64_linux_regsets_store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -267,11 +311,22 @@ mips64_linux_regsets_store_registers (co
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 6)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -298,6 +353,19 @@ mips64_linux_regsets_store_registers (co
 		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
+
+  if (is_dsp)
+    super_store_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 6;
+	     regi++)
+	  super_store_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_store_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
@@ -347,12 +415,23 @@ mips_linux_register_u_offset (struct gdb
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  int has_dsp;
+  int tid;
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  errno = 0;
+  ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (uintptr_t) DSP_CONTROL, 0);
+  has_dsp = (errno == 0);
+
   /* Report that target registers are a size we know for sure
      that we can get from ptrace.  */
   if (_MIPS_SIM == _ABIO32)
-    return tdesc_mips_linux;
+    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
   else
-    return tdesc_mips64_linux;
+    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
 }
 
 void _initialize_mips_linux_nat (void);
@@ -374,5 +453,7 @@ _initialize_mips_linux_nat (void)
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
+  initialize_tdesc_mips_dsp_linux ();
   initialize_tdesc_mips64_linux ();
+  initialize_tdesc_mips64_dsp_linux ();
 }
Index: mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.69
diff -u -p -r1.69 mips-linux-tdep.c
--- mips-linux-tdep.c	15 Feb 2008 04:50:58 -0000	1.69
+++ mips-linux-tdep.c	21 Mar 2008 18:42:41 -0000
@@ -112,14 +112,6 @@ mips_supply_gregset (struct regcache *re
   supply_32bit_reg (regcache, MIPS_PS_REGNUM, regp + EF_CP0_STATUS);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into an elf_gregset_t.  */
@@ -325,14 +317,6 @@ mips64_supply_gregset (struct regcache *
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
Index: mips-linux-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.h,v
retrieving revision 1.7
diff -u -p -r1.7 mips-linux-tdep.h
--- mips-linux-tdep.h	1 Jan 2008 22:53:12 -0000	1.7
+++ mips-linux-tdep.h	21 Mar 2008 18:42:41 -0000
@@ -36,6 +36,8 @@ typedef mips_elf_fpreg_t mips_elf_fpregs
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71
+#define DSP_CONTROL	77
 
 #define EF_REG0			6
 #define EF_REG31		37
@@ -94,7 +96,7 @@ void mips64_fill_fpregset (const struct 
 enum {
   /* The Linux kernel stores an error code from any interrupted
      syscall in a "register" (in $0's save slot).  */
-  MIPS_RESTART_REGNUM = MIPS_LAST_EMBED_REGNUM + 1
+  MIPS_RESTART_REGNUM = MIPS_NUM_REGS
 };
 
 /* Return 1 if MIPS_RESTART_REGNUM is usable.  */
Index: mips-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.c,v
retrieving revision 1.471
diff -u -p -r1.471 mips-tdep.c
--- mips-tdep.c	15 Mar 2008 00:00:48 -0000	1.471
+++ mips-tdep.c	21 Mar 2008 18:42:42 -0000
@@ -408,7 +408,7 @@ static struct cmd_list_element *showmips
    are listed in the following tables.  */
 
 enum
-{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+{ NUM_MIPS_PROCESSOR_REGS = (MIPS_LAST_EMBED_REGNUM + 1 - 32) };
 
 /* Generic MIPS.  */
 
@@ -418,9 +418,7 @@ static const char *mips_generic_reg_name
   "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" */ , "",
-  "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "",
+  "fsr", "fir",
 };
 
 /* Names of IDT R3041 registers.  */
@@ -446,7 +444,7 @@ static const char *mips_tx39_reg_names[N
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -500,11 +498,15 @@ mips_register_name (struct gdbarch *gdba
     }
   else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
     return tdesc_register_name (gdbarch, rawnum);
-  else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
+  else if (32 <= rawnum && rawnum - 32 < NUM_MIPS_PROCESSOR_REGS)
     {
-      gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
-      return tdep->mips_processor_reg_names[rawnum - 32];
+      if (tdep->mips_processor_reg_names[rawnum - 32])
+	return tdep->mips_processor_reg_names[rawnum - 32];
+      return "";
     }
+  else if (rawnum < gdbarch_num_regs (gdbarch))
+    /* Other known registers are always handled by an XML description.  */
+    return "";
   else
     internal_error (__FILE__, __LINE__,
 		    _("mips_register_name: bad register number %d"), rawnum);
@@ -5068,6 +5070,8 @@ mips_stab_reg_to_regnum (struct gdbarch 
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 72 && num < 78)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 72;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
@@ -5091,6 +5095,8 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (s
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 66 && num < 72)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 66;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
@@ -5228,6 +5234,7 @@ mips_gdbarch_init (struct gdbarch_info i
   enum mips_fpu_type fpu_type;
   struct tdesc_arch_data *tdesc_data = NULL;
   int elf_fpu_type = 0;
+  int have_dsp = 0;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -5324,6 +5331,37 @@ mips_gdbarch_init (struct gdbarch_info i
 	  return NULL;
 	}
 
+      /* The DSP registers are optional.  Handle the lack of them
+         gracefully.  */
+      feature = tdesc_find_feature (info.target_desc,
+				    "org.gnu.gdb.mips.dsp");
+      if (feature != NULL)
+	{
+	  valid_p = 1;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 1, "hi1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 2, "lo1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 4, "hi2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 5, "lo2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 7, "hi3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 8, "lo3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPCTL_REGNUM, "dspctl");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+
+	  have_dsp = 1;
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
     }
@@ -5579,6 +5617,8 @@ mips_gdbarch_init (struct gdbarch_info i
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
+	regnum->dspacc = have_dsp ? MIPS_DSPACC_REGNUM : 0;
+	regnum->dspctl = have_dsp ? MIPS_DSPCTL_REGNUM : 0;
 	num_regs = MIPS_LAST_EMBED_REGNUM + 1;
 	reg_names = NULL;
       }
@@ -5592,6 +5632,8 @@ mips_gdbarch_init (struct gdbarch_info i
 	regnum->lo = 68;
 	regnum->fp_control_status = 69;
 	regnum->fp_implementation_revision = 70;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
 	num_regs = 71;
 	reg_names = mips_irix_reg_names;
       }
@@ -5605,6 +5647,8 @@ mips_gdbarch_init (struct gdbarch_info i
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
 	num_regs = 90;
 	if (info.bfd_arch_info != NULL
 	    && info.bfd_arch_info->mach == bfd_mach_mips3900)
Index: mips-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/mips-tdep.h,v
retrieving revision 1.27
diff -u -p -r1.27 mips-tdep.h
--- mips-tdep.h	1 Jan 2008 22:53:12 -0000	1.27
+++ mips-tdep.h	21 Mar 2008 18:42:42 -0000
@@ -53,6 +53,8 @@ struct mips_regnum
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
   int lo;		/* ...  */
+  int dspacc;		/* SmartMIPS/DSP accumulators.  */
+  int dspctl;		/* DSP control.  */
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
@@ -77,7 +79,12 @@ enum
   MIPS_UNUSED_REGNUM = 73,	/* Never used, FIXME */
   MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP0 register for embedded use.  */
   MIPS_PRID_REGNUM = 89,	/* Processor ID.  */
-  MIPS_LAST_EMBED_REGNUM = 89	/* Last one.  */
+  MIPS_LAST_EMBED_REGNUM = 89,	/* Last one.  */
+  MIPS_DSPACC_REGNUM = 90,	/* DSP/SmartMIPS registers:
+				   ACX, Hi1, Lo1, ACX1,
+				   Hi2, Lo2, ACX2, Hi3, Lo3, ACX3.  */
+  MIPS_DSPCTL_REGNUM = MIPS_DSPACC_REGNUM + 10,
+  MIPS_NUM_REGS
 };
 
 /* Defined in mips-tdep.c and used in remote-mips.c */
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.476
diff -u -p -r1.476 gdb.texinfo
--- doc/gdb.texinfo	21 Mar 2008 15:02:37 -0000	1.476
+++ doc/gdb.texinfo	21 Mar 2008 18:42:44 -0000
@@ -26883,6 +26883,10 @@ it may be optional in a future version o
 contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and
 @samp{fir}.  They may be 32-bit or 64-bit depending on the target.
 
+The @samp{org.gnu.gdb.mips.dsp} feature is optional.  If present, it
+should contain registers @samp{lo1} through @samp{lo3}, @samp{hi1}
+through @samp{hi3}, and @samp{dspctl}.
+
 The @samp{org.gnu.gdb.mips.linux} feature is optional.  It should
 contain a single register, @samp{restart}, which is used by the
 Linux kernel to control restartable syscalls.
Index: features/mips-dsp-linux.c
===================================================================
RCS file: features/mips-dsp-linux.c
diff -N features/mips-dsp-linux.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips-dsp-linux.c	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_dsp_linux;
+static void
+initialize_tdesc_mips_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips_dsp_linux = result;
+}
Index: features/mips-dsp-linux.xml
===================================================================
RCS file: features/mips-dsp-linux.xml
diff -N features/mips-dsp-linux.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips-dsp-linux.xml	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+
+  <xi:include href="mips-dsp.xml"/>
+</target>
Index: features/mips-dsp.xml
===================================================================
RCS file: features/mips-dsp.xml
diff -N features/mips-dsp.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips-dsp.xml	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="32"/>
+  <reg name="lo1" bitsize="32"/>
+  <reg name="hi2" bitsize="32"/>
+  <reg name="lo2" bitsize="32"/>
+  <reg name="hi3" bitsize="32"/>
+  <reg name="lo3" bitsize="32"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
Index: features/mips64-dsp-linux.c
===================================================================
RCS file: features/mips64-dsp-linux.c
diff -N features/mips64-dsp-linux.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips64-dsp-linux.c	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips64-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_dsp_linux;
+static void
+initialize_tdesc_mips64_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips64_dsp_linux = result;
+}
Index: features/mips64-dsp-linux.xml
===================================================================
RCS file: features/mips64-dsp-linux.xml
diff -N features/mips64-dsp-linux.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips64-dsp-linux.xml	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+
+  <xi:include href="mips64-dsp.xml"/>
+</target>
Index: features/mips64-dsp.xml
===================================================================
RCS file: features/mips64-dsp.xml
diff -N features/mips64-dsp.xml
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ features/mips64-dsp.xml	21 Mar 2008 18:42:44 -0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="64"/>
+  <reg name="lo1" bitsize="64"/>
+  <reg name="hi2" bitsize="64"/>
+  <reg name="lo2" bitsize="64"/>
+  <reg name="hi3" bitsize="64"/>
+  <reg name="lo3" bitsize="64"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-21 18:44     ` Daniel Jacobowitz
@ 2008-03-26 16:59       ` Maciej W. Rozycki
  2008-03-26 17:59         ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Maciej W. Rozycki @ 2008-03-26 16:59 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Fri, 21 Mar 2008, Daniel Jacobowitz wrote:

> >  Well, I would have thought so, but before "run" is used 
> > mips_gdbarch_init() is called with the target description being 
> > unavailable.  I feel a bit uneasy about some default target configuration 
> > being selected in this case.
> 
> That's how our initialization is supposed to work, though.  A minimal
> description is used until we know exactly what we're talking to.  If
> you need that minimal description to include the new DSP registers,
> one way to do it is to rely on the XML description by default if none
> is provided - that's what I did for PowerPC.

 Well, I am actually unsure whether I really *need* it (which probably 
means I do not), but it does not look like a good engineering practice to 
have this initial meta-state.  I suppose no description should be 
available before a target has been connected to or a native debuggee 
process started so that it is seen when some code somewhere tries to 
access this effectively inexistent state.

> Anyway, this is a small issue.  Except it's tangled up with...
> 
> > > > @@ -5270,11 +5341,11 @@
> > > >  
> > > >  
> > > >        valid_p &= tdesc_numbered_register (feature, tdesc_data,
> > > > -					  MIPS_EMBED_LO_REGNUM, "lo");
> > > > +					  mips_regnum.lo, "lo");
> > > 
> > > I went to a bit of trouble to be able to use constants here, please
> > > don't go back the other direction.  When all the raw registers use
> > > constant numbering, it's much easier to manage the GDB backend.
> > 
> >  The offsets are different for Linux and bare-iron; there is no way to go 
> > back as far as I can tell.  Suggestions are welcome.
> 
> ...this.  The register numbers don't have to be different.  You've
> added a new internal register numbering for Linux; that isn't
> necessary.  Where are Linux and bare metal different?  Is it in an
> existing stub, and if so, what registers does that stub report?

 DSP registers were added pretty late in the game when CP0 registers had 
already been defined for bare iron, so there is no way to have the same 
numbers for Linux and bare iron (unless we want to have a hole in the 
Linux register space).  They were added at the end of the already defined 
ranges, respectively which is I think reasonable.  And these numbers have 
to match ptrace() and the existing remote debug stubs (e.g. YAMON), don't 
they?

> GDB internal register numbers are used for two purposes.  They are the
> default for the remote P/p and T packet numbering, and the g/G packet
> ordering.  If a target description describes the registers,
> tdesc_remote_register_number is used instead.  And they are passed to
> GDB functions and determine the register cache layout.  This is
> internal; just be consistent.

 Obviously the numbers returned by tdesc_remote_register_number() are 
purely internal, but the "legacy" ones are seen externally as mentioned 
above; or am I getting confused here?

> If you use fixed numbering, you don't need to juggle gdbarches and
> tdeps everywhere you want a register number.  It makes things IMO
> much easier to read and maintain.

 No argument, but is it still doable?

> The regcache.c/regcache.h bits are now unused; they were for your
> inf-ptrace.c change.

 The MDI change still relies on these -- I'll migrate them there, thanks 
for spotting.

 Hmm, actually I have just spotted I have already committed a build-fix 
change to remote-mips.c that I submitted a while ago that makes the file 
rely on the function; still it is not built without the MDI change, so I 
propose not to take them out and wait for MDI to get in.

> Are the DSP registers always 32-bit?  It looks that way from the
> current kernel.  I moved away from peekuser/pokeuser register access
> because of n32 debugging issues (ptrace uses "long"), but that's not
> a problem for registers which are never 64-bit.  You've added them
> to 64-bit configuration XML files as 64-bit registers, which doesn't
> match the kernel.

 The kernel is wrong -- with MIPS64 processors additional HIx/LOx 
registers are 64-bit as the traditional HI/LO ones (which, if you notice 
instruction encoding, could as well be called HI0/LO0 now) -- all the four 
provide the same semantics.  The control register is 32-bit-wide in all 
cases.

> > @@ -347,12 +415,29 @@
> >  static const struct target_desc *
> >  mips_linux_read_description (struct target_ops *ops)
> >  {
> > +  struct gdbarch *gdbarch = current_gdbarch;
> > +  CORE_ADDR addr;
> > +  int has_dsp;
> > +  int tid;
> > +
> > +  addr = mips_linux_register_u_offset (gdbarch,
> > +				       mips_regnum (gdbarch)->dspctl, 0);
> > +  gdb_assert (addr != (CORE_ADDR) -1);
> 
> We're trying to eliminate uses of the global current_gdbarch, and the
> current gdbarch at this point doesn't much matter; that's why we're
> about to replace it with a new gdbarch.  This is just DSP_CONTROL.

 Good point -- DSP_CONTROL is indeed fine here.

> >    /* Report that target registers are a size we know for sure
> >       that we can get from ptrace.  */
> > -  if (_MIPS_SIM == _ABIO32)
> > -    return tdesc_mips_linux;
> > +  if (mips_abi_regsize (gdbarch) == 8)
> > +    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
> >    else
> > -    return tdesc_mips64_linux;
> > +    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
> 
> And the comment still applies.  The gdbarch doesn't matter; if GDB is
> built as an o32 program, then on pre-regset kernels it will not be
> able to fetch 64-bit registers and all sorts of things will go wrong.
> Why did you need this?

 It just looked wrong to me to depend on a preprocessor macro where we 
strive to make GDB multi-platform.  Your point is of course valid, but 
after a little thought I believe my change is right anyway.  Given a 
64-bit kernel and an (n)64 or n32 GDB binary you may want to debug an o32 
executable; I have not investigated how ptrace() is meant to work in such 
a scenario and I do not insist on getting rid of the macro dependency with 
this patch, but this is something to be kept in mind in my opinion.

> > +  MIPS_EMBED_DSPCTL_REGNUM = (MIPS_EMBED_DSPACC_REGNUM + 10),
> > +				/* DSP DSPCTL0..1 registers.  */
> 
> Are there two of these?  We only handle one.  Since the internal
> register numbers have no compatibility issues we can add another when
> we want it.

 Well-spotted, thanks -- this is an obsolete reference to DSPCTL1 which 
has never happened.  All the relevant associated bits of code have been 
already removed.

> Also, what are the the ACX registers?  You reserve space for them, but
> nothing ever fills them in.  And there's no XML bits for them.

 These are the "ACcumulator eXtension" registers as defined by the 
SmartMIPS ASE.  One is added per each HI/LO pair; though to the best of my 
knowledge nobody has manufactured a MIPS core with the DSP and SmartMIPS 
ASEs both included at the same time, hence only a single ACX register (for 
the traditional HI/LO pair) has ever been in implemented in existing 
hardware.

> Anyway, in the interests of progress, that leaves me with the attached
> patch.  This adds the DSP registers to native Linux GDB without
> touching anything else.  If you also want them for an embedded stub
> which does not supply XML, or for gdbserver, we can do that
> separately.  I can't test this patch, so take it with a grain of salt;
> I only compiled it.

 Thanks for your effort.  As you may have noticed the bare-iron bits 
merely provide definitions so that register offsets are correctly 
allocated, given some of them are trivially used here.  The actual part 
providing support for CP0/DSP registers stays in my queue pending a 
rewrite to use target descriptions (CP0 subsetting making it a reasonably 
complicated task, as mentioned a while ago); support for "legacy" stubs is 
indeed essential too.

 I have noticed I missed register format descriptions (what are they for 
anyway? -- that don't seem to be documented in the obvious places) and 
fixed a couple of issues that I discovered in testing too.  Here is a new 
version.  As native regression testing takes quite a while, I will do this 
once we agree on a reasonable candidate for commission.

2008-03-26  Maciej W. Rozycki  <macro@mips.com>
            Daniel Jacobowitz <drow@false.org>
            Chris Dearman  <chris@mips.com>

	* features/mips-dsp.xml: New file for DSP ASE registers.
	* features/mips64-dsp.xml: Likewise.
	* features/mips-dsp-linux.xml: New file for a DSP-enabled
	target.
	* features/mips64-dsp-linux.xml: Likewise.
	* features/mips-dsp-linux.c: New generated file.
	* features/mips64-dsp-linux.c: Likewise.
	* regformats/mips-dsp-linux.dat: Likewise.
	* regformats/mips64-dsp-linux.dat: Likewise.
	* mips-linux-nat.c: Include the new DSP target descriptions.
	(super_fetch_registers): Mark static.
	(super_store_registers): Likewise.
	(mips_linux_register_addr): Handle DSP registers.
	(mips64_linux_register_addr): Likewise.
	(mips64_linux_regsets_fetch_registers): Likewise.
	(mips64_linux_regsets_store_registers): Likewise.
	(mips_linux_read_description): Check for the presence of the
	DSP ASE and select the target description accordingly.
	(_initialize_mips_linux_nat): Initialize the new DSP target
	descriptions.
	* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
	Remove padding as the register array does not use the layout
	defined for embedded targets anymore.
	* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
	(MIPS_RESTART_REGNUM): Set from MIPS_NUM_REGS.
	* mips-tdep.c (NUM_MIPS_PROCESSOR_REGS): Set from
	MIPS_LAST_CP0SEL0_REGNUM.
	(mips_generic_reg_names): Remove trailing null strings.
	(mips_tx39_reg_names): Likewise.
	(mips_r3041_reg_names): Add missing size specifier.
	(mips_register_name): Check for a null pointer in
	mips_processor_reg_names and return an empty string.  Handle
	missing XML-described registers.
	(mips_register_type): Handle the DSP control register.
	(mips_pseudo_register_type): Likewise.
	(mips_stab_reg_to_regnum): Handle the DSP accumulators.
	(mips_dwarf_dwarf2_ecoff_reg_to_regnum): Likewise.
	(mips_gdbarch_init): Likewise.  Handle the DSP ASE control
	register.  Use MIPS_NUM_REGS as appropriate.
	* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.
	(MIPS_EMBED_CP0_REGNUM): Offset to CP0 registers.
	(MIPS_LAST_CP0SEL0_REGNUM): Offset to the last CP0 select 0
	register.
	(MIPS_EMBED_CP2_REGNUM): Offset to CP2 registers.
	(MIPS_EMBED_CP2CTL_REGNUM): Offset to CP2 control registers.
	(MIPS_LAST_EMBED_REGNUM): Update accordingly.
	(MIPS_DSPACC_REGNUM): Offset to DSP accumulator registers.
	(MIPS_DSPCTL_REGNUM): Offset to the DSP control register.
	(MIPS_NUM_REGS): New value for total register count.
	* Makefile.in (mips_dsp_linux_c): New variable.
	(mips64_dsp_linux_c): Likewise.
	(mips-linux-nat.o): Depend on $(mips_dsp_linux_c) and
	$(mips64_dsp_linux_c).
	* features/Makefile (WHICH): Add "mips-dsp-linux" and
	"mips64-dsp-linux".
	(mips-dsp-linux-expedite): New variable.
	(mips64-dsp-linux-expedite): Likewise.

	* gdb.texinfo (MIPS Features): Document org.gnu.gdb.mips.dsp.

 Comments?

  Maciej

14607.diff
Index: binutils-quilt/src/gdb/mips-linux-nat.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-nat.c	2008-03-26 16:46:08.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-nat.c	2008-03-26 16:47:35.000000000 +0000
@@ -19,6 +19,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdb_assert.h"
+#include "gdb_stdint.h"
 #include "inferior.h"
 #include "mips-tdep.h"
 #include "target.h"
@@ -34,7 +36,9 @@
 #include <sys/ptrace.h>
 
 #include "features/mips-linux.c"
+#include "features/mips-dsp-linux.c"
 #include "features/mips64-linux.c"
+#include "features/mips64-dsp-linux.c"
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
@@ -47,8 +51,8 @@
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
-void (*super_fetch_registers) (struct regcache *, int);
-void (*super_store_registers) (struct regcache *, int);
+static void (*super_fetch_registers) (struct regcache *, int);
+static void (*super_store_registers) (struct regcache *, int);
 
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are normally defined in <asm/ptrace.h>. 
@@ -84,6 +88,21 @@
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 10)
+    {
+      if ((regno - mips_regnum (gdbarch)->dspacc) % 3 == 0)
+	regaddr = (CORE_ADDR) -1;		/* ACX registers unhandled.  */
+      else
+	regaddr = DSP_BASE
+		  + (regno - mips_regnum (gdbarch)->dspacc)
+		  - (regno - mips_regnum (gdbarch)->dspacc) / 3
+		  - 1;
+    }
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -119,6 +138,21 @@
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 10)
+    {
+      if ((regno - mips_regnum (gdbarch)->dspacc) % 3 == 0)
+	regaddr = (CORE_ADDR) -1;		/* ACX registers unhandled.  */
+      else
+	regaddr = DSP_BASE
+		  + (regno - mips_regnum (gdbarch)->dspacc)
+		  - (regno - mips_regnum (gdbarch)->dspacc) / 3
+		  - 1;
+    }
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -192,7 +226,8 @@
 mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -205,11 +240,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 10)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -245,16 +291,30 @@
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 10;
+	     regi++)
+	  super_fetch_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_fetch_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
    using PTRACE_SETREGS et al.  */
 
 static void
-mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
+mips64_linux_regsets_store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -267,11 +327,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 10)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -298,6 +369,19 @@
 		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
+
+  if (is_dsp)
+    super_store_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 10;
+	     regi++)
+	  super_store_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_store_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
@@ -347,12 +431,23 @@
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  int has_dsp;
+  int tid;
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  errno = 0;
+  ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (uintptr_t) DSP_CONTROL, 0);
+  has_dsp = (errno == 0);
+
   /* Report that target registers are a size we know for sure
      that we can get from ptrace.  */
   if (_MIPS_SIM == _ABIO32)
-    return tdesc_mips_linux;
+    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
   else
-    return tdesc_mips64_linux;
+    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
 }
 
 void _initialize_mips_linux_nat (void);
@@ -374,5 +469,7 @@
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
+  initialize_tdesc_mips_dsp_linux ();
   initialize_tdesc_mips64_linux ();
+  initialize_tdesc_mips64_dsp_linux ();
 }
Index: binutils-quilt/src/gdb/mips-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.c	2008-03-26 16:47:35.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c	2008-03-26 16:47:35.000000000 +0000
@@ -436,7 +436,7 @@
    are listed in the following tables.  */
 
 enum
-{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+{ NUM_MIPS_PROCESSOR_REGS = (MIPS_LAST_CP0SEL0_REGNUM + 1 - 32) };
 
 /* Generic MIPS.  */
 
@@ -446,14 +446,12 @@
   "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" */ , "",
-  "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "",
+  "fsr", "fir",
 };
 
 /* Names of IDT R3041 registers.  */
 
-static const char *mips_r3041_reg_names[] = {
+static const char *mips_r3041_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
   "sr", "lo", "hi", "bad", "cause", "pc",
   "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
   "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
@@ -474,7 +472,7 @@
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -528,11 +526,15 @@
     }
   else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
     return tdesc_register_name (gdbarch, rawnum);
-  else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
+  else if (32 <= rawnum && rawnum - 32 < NUM_MIPS_PROCESSOR_REGS)
     {
-      gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
-      return tdep->mips_processor_reg_names[rawnum - 32];
+      if (tdep->mips_processor_reg_names[rawnum - 32])
+	return tdep->mips_processor_reg_names[rawnum - 32];
+      return "";
     }
+  else if (rawnum < gdbarch_num_regs (gdbarch))
+    /* Other known registers are always handled by an XML description.  */
+    return "";
   else
     internal_error (__FILE__, __LINE__,
 		    _("mips_register_name: bad register number %d"), rawnum);
@@ -741,9 +743,12 @@
     {
       /* The cooked or ABI registers.  These are sized according to
 	 the ABI (with a few complications).  */
-      if (regnum >= (gdbarch_num_regs (gdbarch)
-		     + mips_regnum (gdbarch)->fp_control_status)
-	  && regnum <= gdbarch_num_regs (gdbarch) + MIPS_LAST_EMBED_REGNUM)
+      if ((regnum >= (gdbarch_num_regs (gdbarch)
+		      + mips_regnum (gdbarch)->fp_control_status)
+	   && regnum < gdbarch_num_regs (gdbarch) + MIPS_LAST_EMBED_REGNUM)
+	  || (mips_regnum (gdbarch)->dspctl != 0
+	      && regnum == (gdbarch_num_regs (gdbarch)
+			    + mips_regnum (gdbarch)->dspctl)))
 	/* The pseudo/cooked view of the embedded registers is always
 	   32-bit.  The raw view is handled below.  */
 	return builtin_type_int32;
@@ -787,7 +792,10 @@
        do not try to convert between FPU layouts.  */
     return rawtype;
 
-  if (rawnum >= MIPS_EMBED_FP0_REGNUM + 32 && rawnum <= MIPS_LAST_EMBED_REGNUM)
+  if ((rawnum >= MIPS_EMBED_FP0_REGNUM + 32
+       && rawnum <= MIPS_LAST_EMBED_REGNUM)
+      || (mips_regnum (gdbarch)->dspctl != 0
+	  && rawnum == mips_regnum (gdbarch)->dspctl))
     {
       /* The pseudo/cooked view of embedded registers is always
 	 32-bit, even if the target transfers 64-bit values for them.
@@ -5089,6 +5097,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 72 && num < 78)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 72;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
@@ -5112,6 +5122,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 66 && num < 72)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 66;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
@@ -5249,6 +5261,7 @@
   enum mips_fpu_type fpu_type;
   struct tdesc_arch_data *tdesc_data = NULL;
   int elf_fpu_type = 0;
+  int have_dsp = 0;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -5345,6 +5358,37 @@
 	  return NULL;
 	}
 
+      /* The DSP registers are optional.  Handle the lack of them
+         gracefully.  */
+      feature = tdesc_find_feature (info.target_desc,
+				    "org.gnu.gdb.mips.dsp");
+      if (feature != NULL)
+	{
+	  valid_p = 1;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 1, "hi1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 2, "lo1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 4, "hi2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 5, "lo2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 7, "hi3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 8, "lo3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPCTL_REGNUM, "dspctl");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+
+	  have_dsp = 1;
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
     }
@@ -5600,7 +5644,9 @@
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
-	num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+	regnum->dspacc = have_dsp ? MIPS_DSPACC_REGNUM : 0;
+	regnum->dspctl = have_dsp ? MIPS_DSPCTL_REGNUM : 0;
+	num_regs = MIPS_NUM_REGS;
 	reg_names = NULL;
       }
     else if (info.osabi == GDB_OSABI_IRIX)
@@ -5613,6 +5659,8 @@
 	regnum->lo = 68;
 	regnum->fp_control_status = 69;
 	regnum->fp_implementation_revision = 70;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
 	num_regs = 71;
 	reg_names = mips_irix_reg_names;
       }
@@ -5626,6 +5674,8 @@
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
 	num_regs = 90;
 	if (info.bfd_arch_info != NULL
 	    && info.bfd_arch_info->mach == bfd_mach_mips3900)
Index: binutils-quilt/src/gdb/mips-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.h	2008-03-26 16:46:08.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.h	2008-03-26 16:47:35.000000000 +0000
@@ -53,6 +53,8 @@
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
   int lo;		/* ...  */
+  int dspacc;		/* SmartMIPS/DSP accumulators.  */
+  int dspctl;		/* DSP control.  */
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
@@ -75,9 +77,26 @@
   MIPS_EMBED_PC_REGNUM = 37,
   MIPS_EMBED_FP0_REGNUM = 38,
   MIPS_UNUSED_REGNUM = 73,	/* Never used, FIXME */
-  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP0 register for embedded use.  */
-  MIPS_PRID_REGNUM = 89,	/* Processor ID.  */
-  MIPS_LAST_EMBED_REGNUM = 89	/* Last one.  */
+  MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP register for embedded use.  */
+  MIPS_EMBED_CP0_REGNUM = MIPS_FIRST_EMBED_REGNUM,
+				/* CP0 data registers: 8 banks of 32.  */
+  MIPS_PRID_REGNUM = MIPS_EMBED_CP0_REGNUM + 15,
+				/* Processor ID.  */
+  MIPS_LAST_CP0SEL0_REGNUM = MIPS_EMBED_CP0_REGNUM + 31,
+				/* Last CP0 select 0 register.  */
+  MIPS_EMBED_CP2_REGNUM = MIPS_EMBED_CP0_REGNUM + 8 * 32,
+				/* CP2 data registers: 8 banks of 32.  */
+  MIPS_EMBED_CP2CTL_REGNUM = MIPS_EMBED_CP2_REGNUM + 8 * 32,
+				/* CP2 control registers: 32.  */
+  MIPS_LAST_EMBED_REGNUM = MIPS_EMBED_CP2CTL_REGNUM + 31,
+				/* Last CP register for embedded use.  */
+  MIPS_DSPACC_REGNUM = MIPS_LAST_EMBED_REGNUM + 1,
+				/* DSP/SmartMIPS registers:
+				   ACX, Hi1, Lo1, ACX1,
+				   Hi2, Lo2, ACX2, Hi3, Lo3, ACX3.  */
+  MIPS_DSPCTL_REGNUM = MIPS_DSPACC_REGNUM + 10,
+				/* DSP DSPCTL register.  */
+  MIPS_NUM_REGS
 };
 
 /* Defined in mips-tdep.c and used in remote-mips.c */
Index: binutils-quilt/src/gdb/mips-linux-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.c	2008-03-26 16:46:08.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.c	2008-03-26 16:47:35.000000000 +0000
@@ -112,14 +112,6 @@
   supply_32bit_reg (regcache, MIPS_PS_REGNUM, regp + EF_CP0_STATUS);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into an elf_gregset_t.  */
@@ -325,14 +317,6 @@
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
Index: binutils-quilt/src/gdb/mips-linux-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.h	2008-03-26 16:46:08.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.h	2008-03-26 16:47:35.000000000 +0000
@@ -36,6 +36,8 @@
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71
+#define DSP_CONTROL	77
 
 #define EF_REG0			6
 #define EF_REG31		37
@@ -94,7 +96,7 @@
 enum {
   /* The Linux kernel stores an error code from any interrupted
      syscall in a "register" (in $0's save slot).  */
-  MIPS_RESTART_REGNUM = MIPS_LAST_EMBED_REGNUM + 1
+  MIPS_RESTART_REGNUM = MIPS_NUM_REGS
 };
 
 /* Return 1 if MIPS_RESTART_REGNUM is usable.  */
Index: binutils-quilt/src/gdb/features/mips64-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp.xml	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="64"/>
+  <reg name="lo1" bitsize="64"/>
+  <reg name="hi2" bitsize="64"/>
+  <reg name="lo2" bitsize="64"/>
+  <reg name="hi3" bitsize="64"/>
+  <reg name="lo3" bitsize="64"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
Index: binutils-quilt/src/gdb/features/mips-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp.xml	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="32"/>
+  <reg name="lo1" bitsize="32"/>
+  <reg name="hi2" bitsize="32"/>
+  <reg name="lo2" bitsize="32"/>
+  <reg name="hi3" bitsize="32"/>
+  <reg name="lo3" bitsize="32"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
Index: binutils-quilt/src/gdb/Makefile.in
===================================================================
--- binutils-quilt.orig/src/gdb/Makefile.in	2008-03-26 16:47:35.000000000 +0000
+++ binutils-quilt/src/gdb/Makefile.in	2008-03-26 16:47:35.000000000 +0000
@@ -960,7 +960,9 @@
 features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
 arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
 mips_linux_c = $(srcdir)/features/mips-linux.c $(features_headers)
+mips_dsp_linux_c = $(srcdir)/features/mips-dsp-linux.c $(features_headers)
 mips64_linux_c = $(srcdir)/features/mips64-linux.c $(features_headers)
+mips64_dsp_linux_c = $(srcdir)/features/mips64-dsp-linux.c $(features_headers)
 powerpc_32_c = $(srcdir)/features/rs6000/powerpc-32.c $(features_headers)
 powerpc_403_c = $(srcdir)/features/rs6000/powerpc-403.c $(features_headers)
 powerpc_403gc_c = $(srcdir)/features/rs6000/powerpc-403gc.c $(features_headers)
@@ -2473,7 +2475,8 @@
 mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \
 	$(regcache_h) $(linux_nat_h) $(gdb_proc_service_h) $(gregset_h) \
 	$(mips_linux_tdep_h) $(inferior_h) $(target_descriptions_h) \
-	$(mips_linux_c) $(mips64_linux_c)
+	$(mips_linux_c) $(mips_dsp_linux_c) \
+	$(mips64_dsp_linux_c) $(mips64_dsp_linux_c)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
 	$(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \
Index: binutils-quilt/src/gdb/features/Makefile
===================================================================
--- binutils-quilt.orig/src/gdb/features/Makefile	2008-03-26 16:46:08.000000000 +0000
+++ binutils-quilt/src/gdb/features/Makefile	2008-03-26 16:47:35.000000000 +0000
@@ -31,13 +31,16 @@
 # in the GDB repository.  To generate C files:
 #   make GDB=/path/to/gdb XMLTOC="xml files" cfiles
 
-WHICH = arm-with-iwmmxt mips-linux mips64-linux \
+WHICH = arm-with-iwmmxt \
+	mips-linux mips-dsp-linux mips64-linux mips64-dsp-linux \
 	rs6000/powerpc-32 rs6000/powerpc-e500 rs6000/powerpc-64
 
 # Record which registers should be sent to GDB by default after stop.
 arm-with-iwmmxt-expedite = r11,sp,pc
 mips-linux-expedite = r29,pc
+mips-dsp-linux-expedite = r29,pc
 mips64-linux-expedite = r29,pc
+mips64-dsp-linux-expedite = r29,pc
 rs6000/powerpc-32-expedite = r1,pc
 rs6000/powerpc-e500-expedite = r1,pc
 rs6000/powerpc-64-expedite = r1,pc
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.c	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_dsp_linux;
+static void
+initialize_tdesc_mips_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.xml	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+
+  <xi:include href="mips-dsp.xml"/>
+</target>
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.c	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips64-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_dsp_linux;
+static void
+initialize_tdesc_mips64_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips64_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.xml	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+
+  <xi:include href="mips64-dsp.xml"/>
+</target>
Index: binutils-quilt/src/gdb/doc/gdb.texinfo
===================================================================
--- binutils-quilt.orig/src/gdb/doc/gdb.texinfo	2008-03-26 16:46:07.000000000 +0000
+++ binutils-quilt/src/gdb/doc/gdb.texinfo	2008-03-26 16:47:35.000000000 +0000
@@ -26881,6 +26881,10 @@
 contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and
 @samp{fir}.  They may be 32-bit or 64-bit depending on the target.
 
+The @samp{org.gnu.gdb.mips.dsp} feature is optional.  If present, it
+should contain registers @samp{lo1} through @samp{lo3}, @samp{hi1}
+through @samp{hi3}, and @samp{dspctl}.
+
 The @samp{org.gnu.gdb.mips.linux} feature is optional.  It should
 contain a single register, @samp{restart}, which is used by the
 Linux kernel to control restartable syscalls.
Index: binutils-quilt/src/gdb/regformats/mips-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/regformats/mips-dsp-linux.dat	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,84 @@
+# DO NOT EDIT: generated from mips-dsp-linux.xml
+name:mips_dsp_linux
+xmltarget:mips-dsp-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:f0
+32:f1
+32:f2
+32:f3
+32:f4
+32:f5
+32:f6
+32:f7
+32:f8
+32:f9
+32:f10
+32:f11
+32:f12
+32:f13
+32:f14
+32:f15
+32:f16
+32:f17
+32:f18
+32:f19
+32:f20
+32:f21
+32:f22
+32:f23
+32:f24
+32:f25
+32:f26
+32:f27
+32:f28
+32:f29
+32:f30
+32:f31
+32:fcsr
+32:fir
+32:restart
+32:hi1
+32:lo1
+32:hi2
+32:lo2
+32:hi3
+32:lo3
+32:dspctl
Index: binutils-quilt/src/gdb/regformats/mips64-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/regformats/mips64-dsp-linux.dat	2008-03-26 16:47:35.000000000 +0000
@@ -0,0 +1,84 @@
+# DO NOT EDIT: generated from mips64-dsp-linux.xml
+name:mips64_dsp_linux
+xmltarget:mips64-dsp-linux.xml
+expedite:r29,pc
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:r16
+64:r17
+64:r18
+64:r19
+64:r20
+64:r21
+64:r22
+64:r23
+64:r24
+64:r25
+64:r26
+64:r27
+64:r28
+64:r29
+64:r30
+64:r31
+64:status
+64:lo
+64:hi
+64:badvaddr
+64:cause
+64:pc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+64:fcsr
+64:fir
+64:restart
+64:hi1
+64:lo1
+64:hi2
+64:lo2
+64:hi3
+64:lo3
+32:dspctl


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-26 16:59       ` Maciej W. Rozycki
@ 2008-03-26 17:59         ` Daniel Jacobowitz
  2008-03-27 17:13           ` Maciej W. Rozycki
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2008-03-26 17:59 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Wed, Mar 26, 2008 at 04:58:28PM +0000, Maciej W. Rozycki wrote:
>  Well, I am actually unsure whether I really *need* it (which probably 
> means I do not), but it does not look like a good engineering practice to 
> have this initial meta-state.  I suppose no description should be 
> available before a target has been connected to or a native debuggee 
> process started so that it is seen when some code somewhere tries to 
> access this effectively inexistent state.

There will be no description unless the architecture supplies a
default one.

The initialization sequence does not look like it would if I'd been
writing a debugger from scratch, I admit.  It was very tangled up
but this is the best compromise I could come up with.

> > ...this.  The register numbers don't have to be different.  You've
> > added a new internal register numbering for Linux; that isn't
> > necessary.  Where are Linux and bare metal different?  Is it in an
> > existing stub, and if so, what registers does that stub report?
> 
>  DSP registers were added pretty late in the game when CP0 registers had 
> already been defined for bare iron, so there is no way to have the same 
> numbers for Linux and bare iron (unless we want to have a hole in the 
> Linux register space).  They were added at the end of the already defined 
> ranges, respectively which is I think reasonable.  And these numbers have 
> to match ptrace() and the existing remote debug stubs (e.g. YAMON), don't 
> they?
> 
> > GDB internal register numbers are used for two purposes.  They are the
> > default for the remote P/p and T packet numbering, and the g/G packet
> > ordering.  If a target description describes the registers,
> > tdesc_remote_register_number is used instead.  And they are passed to
> > GDB functions and determine the register cache layout.  This is
> > internal; just be consistent.
> 
>  Obviously the numbers returned by tdesc_remote_register_number() are 
> purely internal, but the "legacy" ones are seen externally as mentioned 
> above; or am I getting confused here?

You've got this backwards.  The numbers _taken_ by
tdesc_remote_register_number are internal.  The numbers returned by it
are the external interface with a remote stub.

If the remote stub implements the new registers and p/P, or returns
the new registers in T responses (both reasonably unlikely) then the
numbers matter.  If it only implements the new registers and g/G,
the numbers do not matter but the ordering of non-zero-sized registers
determines the layout of the g/G packet.

Ptrace isn't affected by these numbers at all; translation is done
by mips_linux_register_addr for instance.

If there are no existing remote stubs (ignoring gdbserver, here, newer
versions of gdbserver will use XML) that transmit the new
registers, then there's no need to give them any particular numbers.
If there are existing stubs you want to preserve, then we can add
a translation method if you can tell us what the actual register
layout you want is.

> > The regcache.c/regcache.h bits are now unused; they were for your
> > inf-ptrace.c change.
> 
>  The MDI change still relies on these -- I'll migrate them there, thanks 
> for spotting.
> 
>  Hmm, actually I have just spotted I have already committed a build-fix 
> change to remote-mips.c that I submitted a while ago that makes the file 
> rely on the function; still it is not built without the MDI change, so I 
> propose not to take them out and wait for MDI to get in.

Does the MDI patch rely on passing "1" to the new function?  If not,
please just use regcache_invalidate.  Speaking about good engineering
design, a function which marks cached data as valid without putting
in any data is pretty suspicious.

>  The kernel is wrong -- with MIPS64 processors additional HIx/LOx 
> registers are 64-bit as the traditional HI/LO ones (which, if you notice 
> instruction encoding, could as well be called HI0/LO0 now) -- all the four 
> provide the same semantics.  The control register is 32-bit-wide in all 
> cases.

Then an N32 GDB is not going to be able to read these registers unless
we create a regset for them, FYI.  ptrace takes and returns longs on
n32, not long longs.  I experimented with using long long, but it was
a terrible mess.

>  It just looked wrong to me to depend on a preprocessor macro where we 
> strive to make GDB multi-platform.  Your point is of course valid, but 
> after a little thought I believe my change is right anyway.  Given a 
> 64-bit kernel and an (n)64 or n32 GDB binary you may want to debug an o32 
> executable; I have not investigated how ptrace() is meant to work in such 
> a scenario and I do not insist on getting rid of the macro dependency with 
> this patch, but this is something to be kept in mind in my opinion.

That exact requirement is why it's written the way it is.  If GDB is
64-bit, then we can always read 64-bit registers from the target; the
pseudo ABI registers will be the right size for o32.

>  These are the "ACcumulator eXtension" registers as defined by the 
> SmartMIPS ASE.  One is added per each HI/LO pair; though to the best of my 
> knowledge nobody has manufactured a MIPS core with the DSP and SmartMIPS 
> ASEs both included at the same time, hence only a single ACX register (for 
> the traditional HI/LO pair) has ever been in implemented in existing 
> hardware.

I see, thanks.

>  I have noticed I missed register format descriptions (what are they for 
> anyway? -- that don't seem to be documented in the obvious places) and 

They're for gdbserver; they define its register cache.  If I wrote the
missing XML files for all existing gdbserver targets, I could replace
them with pregenerated C files using xsltproc (just like I did for the
ones currently in features/*.c); I haven't gotten round to it.

> fixed a couple of issues that I discovered in testing too.  Here is a new 
> version.  As native regression testing takes quite a while, I will do this 
> once we agree on a reasonable candidate for commission.

Sounds fine.  If you'll forgive me, I'll wait to look at the patch
until we resolve the issues above.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-26 17:59         ` Daniel Jacobowitz
@ 2008-03-27 17:13           ` Maciej W. Rozycki
  2008-03-27 17:46             ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Maciej W. Rozycki @ 2008-03-27 17:13 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Wed, 26 Mar 2008, Daniel Jacobowitz wrote:

> You've got this backwards.  The numbers _taken_ by
> tdesc_remote_register_number are internal.  The numbers returned by it
> are the external interface with a remote stub.

 Ah, I see, indeed -- I got confused at one point.  So the numbers in XML 
files are externally visible and these from the enum containing 
MIPS_ZERO_REGNUM, etc. are internal.  Which means you are right they can 
be assigned randomly (so your choice is certainly not worse than mine but 
it's densier, which is an advantage here); though some other bits which 
predate target descriptions in my patch set depend on these numbers for 
remote targets, so again -- I will put that dependency to where the 
dependee is (1).

> Ptrace isn't affected by these numbers at all; translation is done
> by mips_linux_register_addr for instance.

 Indeed -- I was too fast writing this.

> If there are no existing remote stubs (ignoring gdbserver, here, newer
> versions of gdbserver will use XML) that transmit the new
> registers, then there's no need to give them any particular numbers.
> If there are existing stubs you want to preserve, then we can add
> a translation method if you can tell us what the actual register
> layout you want is.

 As far as I know it both YAMON and the SDE library debugging stub both 
provide access to cp0 registers.  I may not have time to check whether 
they use the problematic packets, but with the code shuffle above (1) this 
becomes a non-issue for this lone change.

> Does the MDI patch rely on passing "1" to the new function?  If not,
> please just use regcache_invalidate.  Speaking about good engineering

 Well, it passes "-1", so it is reasonable and not exactly the same as 
regcache_invalidate().

> design, a function which marks cached data as valid without putting
> in any data is pretty suspicious.

 Indeed -- another patch in the set adds:

  regcache_set_valid_p (regcache, cookednum,
			regcache_valid_p (regcache, rawnum));

at the botton of mips_pseudo_register_read() too, which is a place, I 
believe, the scenario you are referring to may actually happen; it used to 
for sure.  Similarly there used to be another possibility for this to 
trigger in code we have to access registers through a frame.

> Then an N32 GDB is not going to be able to read these registers unless
> we create a regset for them, FYI.  ptrace takes and returns longs on
> n32, not long longs.  I experimented with using long long, but it was
> a terrible mess.

 Hmm, I have had a peek at the kernel and it looks like PTRACE_POKEUSR and 
PTRACE_PEEKUSR requests are completely broken for n32; it's just that we 
have a way around it for GP/FP registers...

> >  It just looked wrong to me to depend on a preprocessor macro where we 
> > strive to make GDB multi-platform.  Your point is of course valid, but 
> > after a little thought I believe my change is right anyway.  Given a 
> > 64-bit kernel and an (n)64 or n32 GDB binary you may want to debug an o32 
> > executable; I have not investigated how ptrace() is meant to work in such 
> > a scenario and I do not insist on getting rid of the macro dependency with 
> > this patch, but this is something to be kept in mind in my opinion.
> 
> That exact requirement is why it's written the way it is.  If GDB is
> 64-bit, then we can always read 64-bit registers from the target; the
> pseudo ABI registers will be the right size for o32.

 Fair enough, though still hackish in my opinion. ;-)

> > fixed a couple of issues that I discovered in testing too.  Here is a new 
> > version.  As native regression testing takes quite a while, I will do this 
> > once we agree on a reasonable candidate for commission.
> 
> Sounds fine.  If you'll forgive me, I'll wait to look at the patch
> until we resolve the issues above.

 Well, certainly fixing ptrace() to work with DSP registers one way or 
another for n32 can wait until we have a relevant piece of silicon and 
I'll sort out the numbering issue as referred to above (1).  Please let me 
know whether there is anything else you have had in mind and I'll send a 
new version of the patch shortly.

  Maciej


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-27 17:13           ` Maciej W. Rozycki
@ 2008-03-27 17:46             ` Daniel Jacobowitz
  2008-03-28 17:16               ` Maciej W. Rozycki
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2008-03-27 17:46 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Thu, Mar 27, 2008 at 05:13:03PM +0000, Maciej W. Rozycki wrote:
>  As far as I know it both YAMON and the SDE library debugging stub both 
> provide access to cp0 registers.  I may not have time to check whether 
> they use the problematic packets, but with the code shuffle above (1) this 
> becomes a non-issue for this lone change.

Great.  So we can figure out what register layout they need and
provide it explicitly.

> > Does the MDI patch rely on passing "1" to the new function?  If not,
> > please just use regcache_invalidate.  Speaking about good engineering
> 
>  Well, it passes "-1", so it is reasonable and not exactly the same as 
> regcache_invalidate().

Hmm, that is more reasonable.  That meaning is documented in a
comment, but not used anywhere else in present GDB, though, and none
of the callers of regcache_valid_p expect it - so I'd be dubious of it
actually working!  If we want it to work there's going to be an
ugly audit involved.

May I ask you to save this function for later, and return to it along
with the MDI patch?  I will look at that as soon as I can find a
moment, it's next after this one.

> > Then an N32 GDB is not going to be able to read these registers unless
> > we create a regset for them, FYI.  ptrace takes and returns longs on
> > n32, not long longs.  I experimented with using long long, but it was
> > a terrible mess.
> 
>  Hmm, I have had a peek at the kernel and it looks like PTRACE_POKEUSR and 
> PTRACE_PEEKUSR requests are completely broken for n32; it's just that we 
> have a way around it for GP/FP registers...

Yes, pretty much.  Other platforms know how to fetch larger than
word-sized registers using these functions but they do it by using
register offsets in a hypothetical "struct user" as arguments, instead
of indexes.  The fact that we pass 30 and 31 to get $30 and $31 really
messes things up when you want the other half of $30.

>  Well, certainly fixing ptrace() to work with DSP registers one way or 
> another for n32 can wait until we have a relevant piece of silicon and 
> I'll sort out the numbering issue as referred to above (1).  Please let me 
> know whether there is anything else you have had in mind and I'll send a 
> new version of the patch shortly.

Nope, I'm otherwise happy.  Thanks for your patience.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-27 17:46             ` Daniel Jacobowitz
@ 2008-03-28 17:16               ` Maciej W. Rozycki
  2008-03-31 10:50                 ` Maciej W. Rozycki
  0 siblings, 1 reply; 13+ messages in thread
From: Maciej W. Rozycki @ 2008-03-28 17:16 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Thu, 27 Mar 2008, Daniel Jacobowitz wrote:

> >  Well, it passes "-1", so it is reasonable and not exactly the same as 
> > regcache_invalidate().
> 
> Hmm, that is more reasonable.  That meaning is documented in a
> comment, but not used anywhere else in present GDB, though, and none
> of the callers of regcache_valid_p expect it - so I'd be dubious of it
> actually working!  If we want it to work there's going to be an
> ugly audit involved.
> 
> May I ask you to save this function for later, and return to it along
> with the MDI patch?  I will look at that as soon as I can find a
> moment, it's next after this one.

 Well, I did this with the previous version of the patch already.

 WRT the MDI patch -- changes to this one imply a couple of updates to 
there for it to build at the very least.  I will post the current version 
separately, but I will not be able to do any further updates.

> >  Hmm, I have had a peek at the kernel and it looks like PTRACE_POKEUSR and 
> > PTRACE_PEEKUSR requests are completely broken for n32; it's just that we 
> > have a way around it for GP/FP registers...
> 
> Yes, pretty much.  Other platforms know how to fetch larger than
> word-sized registers using these functions but they do it by using
> register offsets in a hypothetical "struct user" as arguments, instead
> of indexes.  The fact that we pass 30 and 31 to get $30 and $31 really
> messes things up when you want the other half of $30.

 I suppose n32 support in the kernel and then GDB could be updated to use 
such an approach too -- it looks like inf-ptrace.c supports it already as 
is and given n32 is broken in this respect, nobody could have relied on 
the current ABI.

> >  Well, certainly fixing ptrace() to work with DSP registers one way or 
> > another for n32 can wait until we have a relevant piece of silicon and 
> > I'll sort out the numbering issue as referred to above (1).  Please let me 
> > know whether there is anything else you have had in mind and I'll send a 
> > new version of the patch shortly.
> 
> Nope, I'm otherwise happy.  Thanks for your patience.

 Well, it's my time, not patience that's limited I am afraid...

 Here's an updated version hopefully taking all the issues covered into 
account.  I have tested it with the mipsisa32-sde-elf target using the 
mips-sim-sde32/-EB/-march=mips32r2 and mips-sim-sde32/-EL/-march=mips32r2 
boards with no regressions.  I have tested it natively with the 
mips-linux-gnu host using a MIPS64 processor (no DSP support) with no 
regressions.  I did some basic testing the mips-linux-gnu host using a 
DSP-enabled MIPS32r2 processor (a 24KEf) to see whether the DSP registers 
are accessible and verified with a probe attached to same that values read 
and written under Linux actually correspond to the right hardware 
registers.  I'll see if I manage to find enough time to run the test suite 
on the 24KEf, but it is slow enough I may not.

2008-03-28  Maciej W. Rozycki  <macro@mips.com>
            Daniel Jacobowitz  <drow@false.org>
            Chris Dearman  <chris@mips.com>

	[mti-dsp-dbg]
	* features/mips-dsp.xml: New file for DSP ASE registers.
	* features/mips64-dsp.xml: Likewise.
	* features/mips-dsp-linux.xml: New file for a DSP-enabled
	target.
	* features/mips64-dsp-linux.xml: Likewise.
	* features/mips-dsp-linux.c: New generated file.
	* features/mips64-dsp-linux.c: Likewise.
	* regformats/mips-dsp-linux.dat: Likewise.
	* regformats/mips64-dsp-linux.dat: Likewise.
	* mips-linux-nat.c: Include the new DSP target descriptions.
	(super_fetch_registers): Mark static.
	(super_store_registers): Likewise.
	(mips_linux_register_addr): Handle DSP registers.
	(mips64_linux_register_addr): Likewise.
	(mips64_linux_regsets_fetch_registers): Likewise.
	(mips64_linux_regsets_store_registers): Likewise.
	(mips_linux_read_description): Check for the presence of the
	DSP ASE and select the target description accordingly.
	(_initialize_mips_linux_nat): Initialize the new DSP target
	descriptions.
	* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
	Remove padding as the register array does not use the layout
	defined for embedded targets anymore.
	* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
	(MIPS_RESTART_REGNUM): Set from MIPS_NUM_REGS.
	* mips-tdep.c (NUM_MIPS_PROCESSOR_REGS): Set from
	MIPS_LAST_CP0SEL0_REGNUM.
	(mips_generic_reg_names): Remove trailing null strings.
	(mips_tx39_reg_names): Likewise.
	(mips_r3041_reg_names): Add missing size specifier.
	(mips_register_name): Check for a null pointer in
	mips_processor_reg_names and return an empty string.  Handle
	missing XML-described registers.
	(mips_register_type): Handle the DSP control register.
	(mips_pseudo_register_type): Likewise.
	(mips_stab_reg_to_regnum): Handle the DSP accumulators.
	(mips_dwarf_dwarf2_ecoff_reg_to_regnum): Likewise.
	(mips_gdbarch_init): Likewise.  Handle the DSP ASE control
	register.  Use MIPS_NUM_REGS and NUM_MIPS_PROCESSOR_REGS as
	appropriate.
	* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.
	(MIPS_DSPACC_REGNUM): Offset to DSP accumulator registers.
	(MIPS_DSPCTL_REGNUM): Offset to the DSP control register.
	(MIPS_NUM_REGS): New value for total register count.
	* Makefile.in (mips_dsp_linux_c): New variable.
	(mips64_dsp_linux_c): Likewise.
	(mips-linux-nat.o): Depend on $(mips_dsp_linux_c) and
	$(mips64_dsp_linux_c).
	* features/Makefile (WHICH): Add "mips-dsp-linux" and
	"mips64-dsp-linux".
	(mips-dsp-linux-expedite): New variable.
	(mips64-dsp-linux-expedite): Likewise.

	* gdb.texinfo (MIPS Features): Document org.gnu.gdb.mips.dsp.

 OK to apply?

  Maciej

14607.diff
Index: binutils-quilt/src/gdb/mips-linux-nat.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-nat.c	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-nat.c	2008-03-28 12:53:25.000000000 +0000
@@ -19,6 +19,8 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "defs.h"
+#include "gdb_assert.h"
+#include "gdb_stdint.h"
 #include "inferior.h"
 #include "mips-tdep.h"
 #include "target.h"
@@ -34,7 +36,9 @@
 #include <sys/ptrace.h>
 
 #include "features/mips-linux.c"
+#include "features/mips-dsp-linux.c"
 #include "features/mips64-linux.c"
+#include "features/mips64-dsp-linux.c"
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
@@ -47,8 +51,8 @@
 /* Saved function pointers to fetch and store a single register using
    PTRACE_PEEKUSER and PTRACE_POKEUSER.  */
 
-void (*super_fetch_registers) (struct regcache *, int);
-void (*super_store_registers) (struct regcache *, int);
+static void (*super_fetch_registers) (struct regcache *, int);
+static void (*super_store_registers) (struct regcache *, int);
 
 /* Map gdb internal register number to ptrace ``address''.
    These ``addresses'' are normally defined in <asm/ptrace.h>. 
@@ -84,6 +88,21 @@
     regaddr = FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 10)
+    {
+      if ((regno - mips_regnum (gdbarch)->dspacc) % 3 == 0)
+	regaddr = (CORE_ADDR) -1;		/* ACX registers unhandled.  */
+      else
+	regaddr = DSP_BASE
+		  + (regno - mips_regnum (gdbarch)->dspacc)
+		  - (regno - mips_regnum (gdbarch)->dspacc) / 3
+		  - 1;
+    }
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -119,6 +138,21 @@
     regaddr = MIPS64_FPC_CSR;
   else if (regno == mips_regnum (gdbarch)->fp_implementation_revision)
     regaddr = store? (CORE_ADDR) -1 : MIPS64_FPC_EIR;
+  else if (mips_regnum (gdbarch)->dspacc != 0
+	   && regno >= mips_regnum (gdbarch)->dspacc
+	   && regno < mips_regnum (gdbarch)->dspacc + 10)
+    {
+      if ((regno - mips_regnum (gdbarch)->dspacc) % 3 == 0)
+	regaddr = (CORE_ADDR) -1;		/* ACX registers unhandled.  */
+      else
+	regaddr = DSP_BASE
+		  + (regno - mips_regnum (gdbarch)->dspacc)
+		  - (regno - mips_regnum (gdbarch)->dspacc) / 3
+		  - 1;
+    }
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    regaddr = DSP_CONTROL;
   else if (mips_linux_restart_reg_p (gdbarch) && regno == MIPS_RESTART_REGNUM)
     regaddr = 0;
   else
@@ -192,7 +226,8 @@
 mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -205,11 +240,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 10)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -245,16 +291,30 @@
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 10;
+	     regi++)
+	  super_fetch_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_fetch_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Store REGNO (or all registers if REGNO == -1) to the target
    using PTRACE_SETREGS et al.  */
 
 static void
-mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
+mips64_linux_regsets_store_registers (struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -267,11 +327,22 @@
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  if (mips_regnum (gdbarch)->dspacc != 0
+      && regno >= mips_regnum (gdbarch)->dspacc
+      && regno < mips_regnum (gdbarch)->dspacc + 10)
+    is_dsp = 1;
+  else if (mips_regnum (gdbarch)->dspctl != 0
+	   && regno == mips_regnum (gdbarch)->dspctl)
+    is_dsp = 1;
+  else
+    is_dsp = 0;
+
   tid = ptid_get_lwp (inferior_ptid);
   if (tid == 0)
     tid = ptid_get_pid (inferior_ptid);
 
-  if (regno == -1 || !is_fp)
+  if (regno == -1 || (!is_fp && !is_dsp))
     {
       mips64_elf_gregset_t regs;
 
@@ -298,6 +369,19 @@
 		  (PTRACE_TYPE_ARG3) &fp_regs) == -1)
 	perror_with_name (_("Couldn't set FP registers"));
     }
+
+  if (is_dsp)
+    super_store_registers (regcache, regno);
+  else if (regno == -1)
+    {
+      if (mips_regnum (gdbarch)->dspacc != 0)
+	for (regi = mips_regnum (gdbarch)->dspacc;
+	     regi < mips_regnum (gdbarch)->dspacc + 10;
+	     regi++)
+	  super_store_registers (regcache, regi);
+      if (mips_regnum (gdbarch)->dspctl != 0)
+	super_store_registers (regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
@@ -347,12 +431,23 @@
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  int has_dsp;
+  int tid;
+
+  tid = ptid_get_lwp (inferior_ptid);
+  if (tid == 0)
+    tid = ptid_get_pid (inferior_ptid);
+
+  errno = 0;
+  ptrace (PT_READ_U, tid, (PTRACE_TYPE_ARG3) (uintptr_t) DSP_CONTROL, 0);
+  has_dsp = (errno == 0);
+
   /* Report that target registers are a size we know for sure
      that we can get from ptrace.  */
   if (_MIPS_SIM == _ABIO32)
-    return tdesc_mips_linux;
+    return has_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
   else
-    return tdesc_mips64_linux;
+    return has_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
 }
 
 void _initialize_mips_linux_nat (void);
@@ -374,5 +469,7 @@
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
+  initialize_tdesc_mips_dsp_linux ();
   initialize_tdesc_mips64_linux ();
+  initialize_tdesc_mips64_dsp_linux ();
 }
Index: binutils-quilt/src/gdb/mips-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.c	2008-03-28 12:53:25.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c	2008-03-28 12:53:25.000000000 +0000
@@ -436,7 +436,7 @@
    are listed in the following tables.  */
 
 enum
-{ NUM_MIPS_PROCESSOR_REGS = (90 - 32) };
+{ NUM_MIPS_PROCESSOR_REGS = (MIPS_LAST_EMBED_REGNUM + 1 - 32) };
 
 /* Generic MIPS.  */
 
@@ -446,14 +446,12 @@
   "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" */ , "",
-  "", "", "", "", "", "", "", "",
-  "", "", "", "", "", "", "", "",
+  "fsr", "fir",
 };
 
 /* Names of IDT R3041 registers.  */
 
-static const char *mips_r3041_reg_names[] = {
+static const char *mips_r3041_reg_names[NUM_MIPS_PROCESSOR_REGS] = {
   "sr", "lo", "hi", "bad", "cause", "pc",
   "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
   "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
@@ -474,7 +472,7 @@
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -528,11 +526,15 @@
     }
   else if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
     return tdesc_register_name (gdbarch, rawnum);
-  else if (32 <= rawnum && rawnum < gdbarch_num_regs (gdbarch))
+  else if (32 <= rawnum && rawnum - 32 < NUM_MIPS_PROCESSOR_REGS)
     {
-      gdb_assert (rawnum - 32 < NUM_MIPS_PROCESSOR_REGS);
-      return tdep->mips_processor_reg_names[rawnum - 32];
+      if (tdep->mips_processor_reg_names[rawnum - 32])
+	return tdep->mips_processor_reg_names[rawnum - 32];
+      return "";
     }
+  else if (rawnum < gdbarch_num_regs (gdbarch))
+    /* Other known registers are always handled by an XML description.  */
+    return "";
   else
     internal_error (__FILE__, __LINE__,
 		    _("mips_register_name: bad register number %d"), rawnum);
@@ -741,9 +743,12 @@
     {
       /* The cooked or ABI registers.  These are sized according to
 	 the ABI (with a few complications).  */
-      if (regnum >= (gdbarch_num_regs (gdbarch)
-		     + mips_regnum (gdbarch)->fp_control_status)
-	  && regnum <= gdbarch_num_regs (gdbarch) + MIPS_LAST_EMBED_REGNUM)
+      if ((regnum >= (gdbarch_num_regs (gdbarch)
+		      + mips_regnum (gdbarch)->fp_control_status)
+	   && regnum <= gdbarch_num_regs (gdbarch) + MIPS_LAST_EMBED_REGNUM)
+	  || (mips_regnum (gdbarch)->dspctl != 0
+	      && regnum == (gdbarch_num_regs (gdbarch)
+			    + mips_regnum (gdbarch)->dspctl)))
 	/* The pseudo/cooked view of the embedded registers is always
 	   32-bit.  The raw view is handled below.  */
 	return builtin_type_int32;
@@ -787,7 +792,10 @@
        do not try to convert between FPU layouts.  */
     return rawtype;
 
-  if (rawnum >= MIPS_EMBED_FP0_REGNUM + 32 && rawnum <= MIPS_LAST_EMBED_REGNUM)
+  if ((rawnum >= MIPS_EMBED_FP0_REGNUM + 32
+       && rawnum <= MIPS_LAST_EMBED_REGNUM)
+      || (mips_regnum (gdbarch)->dspctl != 0
+	  && rawnum == mips_regnum (gdbarch)->dspctl))
     {
       /* The pseudo/cooked view of embedded registers is always
 	 32-bit, even if the target transfers 64-bit values for them.
@@ -5089,6 +5097,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 72 && num < 78)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 72;
   else
     /* This will hopefully (eventually) provoke a warning.  Should
        we be calling complaint() here?  */
@@ -5112,6 +5122,8 @@
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 65)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (num >= 66 && num < 72)
+    regnum = num + mips_regnum (gdbarch)->dspacc - 66;
   else
     /* This will hopefully (eventually) provoke a warning.  Should we
        be calling complaint() here?  */
@@ -5249,6 +5261,7 @@
   enum mips_fpu_type fpu_type;
   struct tdesc_arch_data *tdesc_data = NULL;
   int elf_fpu_type = 0;
+  int have_dsp = 0;
 
   /* Check any target description for validity.  */
   if (tdesc_has_registers (info.target_desc))
@@ -5345,6 +5358,37 @@
 	  return NULL;
 	}
 
+      /* The DSP registers are optional.  Handle the lack of them
+         gracefully.  */
+      feature = tdesc_find_feature (info.target_desc,
+				    "org.gnu.gdb.mips.dsp");
+      if (feature != NULL)
+	{
+	  valid_p = 1;
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 1, "hi1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 2, "lo1");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 4, "hi2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 5, "lo2");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 7, "hi3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPACC_REGNUM + 8, "lo3");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      MIPS_DSPCTL_REGNUM, "dspctl");
+
+	  if (!valid_p)
+	    {
+	      tdesc_data_cleanup (tdesc_data);
+	      return NULL;
+	    }
+
+	  have_dsp = 1;
+	}
+
       /* It would be nice to detect an attempt to use a 64-bit ABI
 	 when only 32-bit registers are provided.  */
     }
@@ -5600,7 +5644,9 @@
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
-	num_regs = MIPS_LAST_EMBED_REGNUM + 1;
+	regnum->dspacc = have_dsp ? MIPS_DSPACC_REGNUM : 0;
+	regnum->dspctl = have_dsp ? MIPS_DSPCTL_REGNUM : 0;
+	num_regs = MIPS_NUM_REGS;
 	reg_names = NULL;
       }
     else if (info.osabi == GDB_OSABI_IRIX)
@@ -5613,6 +5659,8 @@
 	regnum->lo = 68;
 	regnum->fp_control_status = 69;
 	regnum->fp_implementation_revision = 70;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
 	num_regs = 71;
 	reg_names = mips_irix_reg_names;
       }
@@ -5626,7 +5674,9 @@
 	regnum->fp0 = MIPS_EMBED_FP0_REGNUM;
 	regnum->fp_control_status = 70;
 	regnum->fp_implementation_revision = 71;
-	num_regs = 90;
+	regnum->dspacc = 0;
+	regnum->dspctl = 0;
+	num_regs = NUM_MIPS_PROCESSOR_REGS + 32;
 	if (info.bfd_arch_info != NULL
 	    && info.bfd_arch_info->mach == bfd_mach_mips3900)
 	  reg_names = mips_tx39_reg_names;
Index: binutils-quilt/src/gdb/mips-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.h	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.h	2008-03-28 12:53:25.000000000 +0000
@@ -53,6 +53,8 @@
   int cause;		/* Describes last exception.  */
   int hi;		/* Multiply/divide temp.  */
   int lo;		/* ...  */
+  int dspacc;		/* SmartMIPS/DSP accumulators.  */
+  int dspctl;		/* DSP control.  */
 };
 extern const struct mips_regnum *mips_regnum (struct gdbarch *gdbarch);
 
@@ -77,7 +79,12 @@
   MIPS_UNUSED_REGNUM = 73,	/* Never used, FIXME */
   MIPS_FIRST_EMBED_REGNUM = 74,	/* First CP0 register for embedded use.  */
   MIPS_PRID_REGNUM = 89,	/* Processor ID.  */
-  MIPS_LAST_EMBED_REGNUM = 89	/* Last one.  */
+  MIPS_LAST_EMBED_REGNUM = 89,	/* Last one.  */
+  MIPS_DSPACC_REGNUM = 90,	/* DSP/SmartMIPS registers:
+				   ACX, Hi1, Lo1, ACX1,
+				   Hi2, Lo2, ACX2, Hi3, Lo3, ACX3.  */
+  MIPS_DSPCTL_REGNUM = 100,	/* DSP DSPCTL register.  */
+  MIPS_NUM_REGS
 };
 
 /* Defined in mips-tdep.c and used in remote-mips.c */
Index: binutils-quilt/src/gdb/mips-linux-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.c	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.c	2008-03-28 12:53:25.000000000 +0000
@@ -112,14 +112,6 @@
   supply_32bit_reg (regcache, MIPS_PS_REGNUM, regp + EF_CP0_STATUS);
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into an elf_gregset_t.  */
@@ -325,14 +317,6 @@
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_STATUS));
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
-
-  /* Fill inaccessible registers with zero.  */
-  regcache_raw_supply (regcache, MIPS_ZERO_REGNUM, zerobuf);
-  regcache_raw_supply (regcache, MIPS_UNUSED_REGNUM, zerobuf);
-  for (regi = MIPS_FIRST_EMBED_REGNUM;
-       regi <= MIPS_LAST_EMBED_REGNUM;
-       regi++)
-    regcache_raw_supply (regcache, regi, zerobuf);
 }
 
 /* Pack our registers (or one register) into a 64-bit elf_gregset_t.  */
Index: binutils-quilt/src/gdb/mips-linux-tdep.h
===================================================================
--- binutils-quilt.orig/src/gdb/mips-linux-tdep.h	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/mips-linux-tdep.h	2008-03-28 12:53:25.000000000 +0000
@@ -36,6 +36,8 @@
 #define MMLO		68
 #define FPC_CSR		69
 #define FPC_EIR		70
+#define DSP_BASE	71
+#define DSP_CONTROL	77
 
 #define EF_REG0			6
 #define EF_REG31		37
@@ -94,7 +96,7 @@
 enum {
   /* The Linux kernel stores an error code from any interrupted
      syscall in a "register" (in $0's save slot).  */
-  MIPS_RESTART_REGNUM = MIPS_LAST_EMBED_REGNUM + 1
+  MIPS_RESTART_REGNUM = MIPS_NUM_REGS
 };
 
 /* Return 1 if MIPS_RESTART_REGNUM is usable.  */
Index: binutils-quilt/src/gdb/features/mips64-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp.xml	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="64"/>
+  <reg name="lo1" bitsize="64"/>
+  <reg name="hi2" bitsize="64"/>
+  <reg name="lo2" bitsize="64"/>
+  <reg name="hi3" bitsize="64"/>
+  <reg name="lo3" bitsize="64"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
Index: binutils-quilt/src/gdb/features/mips-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp.xml	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.mips.dsp">
+  <reg name="hi1" bitsize="32"/>
+  <reg name="lo1" bitsize="32"/>
+  <reg name="hi2" bitsize="32"/>
+  <reg name="lo2" bitsize="32"/>
+  <reg name="hi3" bitsize="32"/>
+  <reg name="lo3" bitsize="32"/>
+
+  <reg name="dspctl" bitsize="32"/>
+</feature>
Index: binutils-quilt/src/gdb/Makefile.in
===================================================================
--- binutils-quilt.orig/src/gdb/Makefile.in	2008-03-28 12:53:25.000000000 +0000
+++ binutils-quilt/src/gdb/Makefile.in	2008-03-28 12:53:25.000000000 +0000
@@ -960,7 +960,9 @@
 features_headers = $(defs_h) $(gdbtypes_h) $(target_descriptions_h)
 arm_with_iwmmxt_c = $(srcdir)/features/arm-with-iwmmxt.c $(features_headers)
 mips_linux_c = $(srcdir)/features/mips-linux.c $(features_headers)
+mips_dsp_linux_c = $(srcdir)/features/mips-dsp-linux.c $(features_headers)
 mips64_linux_c = $(srcdir)/features/mips64-linux.c $(features_headers)
+mips64_dsp_linux_c = $(srcdir)/features/mips64-dsp-linux.c $(features_headers)
 powerpc_32_c = $(srcdir)/features/rs6000/powerpc-32.c $(features_headers)
 powerpc_403_c = $(srcdir)/features/rs6000/powerpc-403.c $(features_headers)
 powerpc_403gc_c = $(srcdir)/features/rs6000/powerpc-403gc.c $(features_headers)
@@ -2473,7 +2475,8 @@
 mips-linux-nat.o: mips-linux-nat.c $(defs_h) $(mips_tdep_h) $(target_h) \
 	$(regcache_h) $(linux_nat_h) $(gdb_proc_service_h) $(gregset_h) \
 	$(mips_linux_tdep_h) $(inferior_h) $(target_descriptions_h) \
-	$(mips_linux_c) $(mips64_linux_c)
+	$(mips_linux_c) $(mips_dsp_linux_c) \
+	$(mips64_dsp_linux_c) $(mips64_dsp_linux_c)
 mips-linux-tdep.o: mips-linux-tdep.c $(defs_h) $(gdbcore_h) $(target_h) \
 	$(solib_svr4_h) $(osabi_h) $(mips_tdep_h) $(gdb_string_h) \
 	$(gdb_assert_h) $(frame_h) $(regcache_h) $(trad_frame_h) \
Index: binutils-quilt/src/gdb/features/Makefile
===================================================================
--- binutils-quilt.orig/src/gdb/features/Makefile	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/features/Makefile	2008-03-28 12:53:25.000000000 +0000
@@ -31,13 +31,16 @@
 # in the GDB repository.  To generate C files:
 #   make GDB=/path/to/gdb XMLTOC="xml files" cfiles
 
-WHICH = arm-with-iwmmxt mips-linux mips64-linux \
+WHICH = arm-with-iwmmxt \
+	mips-linux mips-dsp-linux mips64-linux mips64-dsp-linux \
 	rs6000/powerpc-32 rs6000/powerpc-e500 rs6000/powerpc-64
 
 # Record which registers should be sent to GDB by default after stop.
 arm-with-iwmmxt-expedite = r11,sp,pc
 mips-linux-expedite = r29,pc
+mips-dsp-linux-expedite = r29,pc
 mips64-linux-expedite = r29,pc
+mips64-dsp-linux-expedite = r29,pc
 rs6000/powerpc-32-expedite = r1,pc
 rs6000/powerpc-e500-expedite = r1,pc
 rs6000/powerpc-64-expedite = r1,pc
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.c	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips_dsp_linux;
+static void
+initialize_tdesc_mips_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 32, "ieee_single");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 32, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips-dsp-linux.xml	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips-cpu.xml"/>
+  <xi:include href="mips-cp0.xml"/>
+  <xi:include href="mips-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="32" group="system"/>
+  </feature>
+
+  <xi:include href="mips-dsp.xml"/>
+</target>
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.c	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips64-dsp-linux.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_mips64_dsp_linux;
+static void
+initialize_tdesc_mips64_dsp_linux (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cpu");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo", 33, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi", 34, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "pc", 37, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.cp0");
+  tdesc_create_reg (feature, "status", 32, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "badvaddr", 35, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "cause", 36, 1, NULL, 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.fpu");
+  tdesc_create_reg (feature, "f0", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f1", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f2", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f3", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f4", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f5", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f6", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f7", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f8", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f9", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f10", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f11", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f12", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f13", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f14", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f15", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f16", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f17", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f18", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f19", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f20", 58, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f21", 59, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f22", 60, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f23", 61, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f24", 62, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f25", 63, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f26", 64, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f27", 65, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f28", 66, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f29", 67, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f30", 68, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "f31", 69, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fcsr", 70, 1, "float", 64, "int");
+  tdesc_create_reg (feature, "fir", 71, 1, "float", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.linux");
+  tdesc_create_reg (feature, "restart", 72, 1, "system", 64, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.mips.dsp");
+  tdesc_create_reg (feature, "hi1", 73, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo1", 74, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi2", 75, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo2", 76, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "hi3", 77, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "lo3", 78, 1, NULL, 64, "int");
+  tdesc_create_reg (feature, "dspctl", 79, 1, NULL, 32, "int");
+
+  tdesc_mips64_dsp_linux = result;
+}
Index: binutils-quilt/src/gdb/features/mips64-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/features/mips64-dsp-linux.xml	2008-03-28 12:53:25.000000000 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <architecture>mips</architecture>
+  <xi:include href="mips64-cpu.xml"/>
+  <xi:include href="mips64-cp0.xml"/>
+  <xi:include href="mips64-fpu.xml"/>
+
+  <feature name="org.gnu.gdb.mips.linux">
+    <reg name="restart" bitsize="64" group="system"/>
+  </feature>
+
+  <xi:include href="mips64-dsp.xml"/>
+</target>
Index: binutils-quilt/src/gdb/doc/gdb.texinfo
===================================================================
--- binutils-quilt.orig/src/gdb/doc/gdb.texinfo	2008-03-28 12:53:04.000000000 +0000
+++ binutils-quilt/src/gdb/doc/gdb.texinfo	2008-03-28 12:53:26.000000000 +0000
@@ -26881,6 +26881,10 @@
 contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and
 @samp{fir}.  They may be 32-bit or 64-bit depending on the target.
 
+The @samp{org.gnu.gdb.mips.dsp} feature is optional.  If present, it
+should contain registers @samp{lo1} through @samp{lo3}, @samp{hi1}
+through @samp{hi3}, and @samp{dspctl}.
+
 The @samp{org.gnu.gdb.mips.linux} feature is optional.  It should
 contain a single register, @samp{restart}, which is used by the
 Linux kernel to control restartable syscalls.
Index: binutils-quilt/src/gdb/regformats/mips-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/regformats/mips-dsp-linux.dat	2008-03-28 12:53:26.000000000 +0000
@@ -0,0 +1,84 @@
+# DO NOT EDIT: generated from mips-dsp-linux.xml
+name:mips_dsp_linux
+xmltarget:mips-dsp-linux.xml
+expedite:r29,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:r13
+32:r14
+32:r15
+32:r16
+32:r17
+32:r18
+32:r19
+32:r20
+32:r21
+32:r22
+32:r23
+32:r24
+32:r25
+32:r26
+32:r27
+32:r28
+32:r29
+32:r30
+32:r31
+32:status
+32:lo
+32:hi
+32:badvaddr
+32:cause
+32:pc
+32:f0
+32:f1
+32:f2
+32:f3
+32:f4
+32:f5
+32:f6
+32:f7
+32:f8
+32:f9
+32:f10
+32:f11
+32:f12
+32:f13
+32:f14
+32:f15
+32:f16
+32:f17
+32:f18
+32:f19
+32:f20
+32:f21
+32:f22
+32:f23
+32:f24
+32:f25
+32:f26
+32:f27
+32:f28
+32:f29
+32:f30
+32:f31
+32:fcsr
+32:fir
+32:restart
+32:hi1
+32:lo1
+32:hi2
+32:lo2
+32:hi3
+32:lo3
+32:dspctl
Index: binutils-quilt/src/gdb/regformats/mips64-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ binutils-quilt/src/gdb/regformats/mips64-dsp-linux.dat	2008-03-28 12:53:26.000000000 +0000
@@ -0,0 +1,84 @@
+# DO NOT EDIT: generated from mips64-dsp-linux.xml
+name:mips64_dsp_linux
+xmltarget:mips64-dsp-linux.xml
+expedite:r29,pc
+64:r0
+64:r1
+64:r2
+64:r3
+64:r4
+64:r5
+64:r6
+64:r7
+64:r8
+64:r9
+64:r10
+64:r11
+64:r12
+64:r13
+64:r14
+64:r15
+64:r16
+64:r17
+64:r18
+64:r19
+64:r20
+64:r21
+64:r22
+64:r23
+64:r24
+64:r25
+64:r26
+64:r27
+64:r28
+64:r29
+64:r30
+64:r31
+64:status
+64:lo
+64:hi
+64:badvaddr
+64:cause
+64:pc
+64:f0
+64:f1
+64:f2
+64:f3
+64:f4
+64:f5
+64:f6
+64:f7
+64:f8
+64:f9
+64:f10
+64:f11
+64:f12
+64:f13
+64:f14
+64:f15
+64:f16
+64:f17
+64:f18
+64:f19
+64:f20
+64:f21
+64:f22
+64:f23
+64:f24
+64:f25
+64:f26
+64:f27
+64:f28
+64:f29
+64:f30
+64:f31
+64:fcsr
+64:fir
+64:restart
+64:hi1
+64:lo1
+64:hi2
+64:lo2
+64:hi3
+64:lo3
+32:dspctl


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: MIPS: Handle the DSP registers
  2008-03-28 17:16               ` Maciej W. Rozycki
@ 2008-03-31 10:50                 ` Maciej W. Rozycki
  0 siblings, 0 replies; 13+ messages in thread
From: Maciej W. Rozycki @ 2008-03-31 10:50 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Chris Dearman, Maciej W. Rozycki

On Fri, 28 Mar 2008, Maciej W. Rozycki wrote:

> registers.  I'll see if I manage to find enough time to run the test suite 
> on the 24KEf, but it is slow enough I may not.

 Well, it has finished now and except from a few additional timeouts on 
some particularly slow cases, no problems.

  Maciej


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-03-31 10:50 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-12-10 16:33 MIPS: Handle the DSP registers Maciej W. Rozycki
2007-12-18 13:42 ` Daniel Jacobowitz
2007-12-18 13:56   ` Nigel Stephens
2007-12-18 15:15     ` Daniel Jacobowitz
2007-12-18 16:06       ` Nigel Stephens
2008-03-19 17:07   ` Maciej W. Rozycki
2008-03-21 18:44     ` Daniel Jacobowitz
2008-03-26 16:59       ` Maciej W. Rozycki
2008-03-26 17:59         ` Daniel Jacobowitz
2008-03-27 17:13           ` Maciej W. Rozycki
2008-03-27 17:46             ` Daniel Jacobowitz
2008-03-28 17:16               ` Maciej W. Rozycki
2008-03-31 10:50                 ` Maciej W. Rozycki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox