Re: MIPS: Handle the DSP registers

Maciej W. Rozycki
2008-03-26T16:59:24Z

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. -->
+
+
+<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. -->
+
+
+<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. -->
+
+
+<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. -->
+
+
+<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