MIPS: Handle the DSP registers

Maciej W. Rozycki
2007-12-10T15:52:21Z

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