This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


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

[PATCH] MIPS/Linux: DSP ASE support


Hi,

 The DSP ASE has added numerous instructions to the MIPS instruction set 
that we already support through (lib)opcodes, but there are also seven new 
registers that we have not supported, namely three additional HI/LO 
accumulator pairs, that correspond to the original MIPS ISA's 
multiply/divide HI/LO accumulator, as well as DSPCTL, the DSP control 
register.  The three new accumulators were given 1-3 indices with the 
original accumulator referred to by an optional 0 index.  These numbers 
correspond to actual operand encodings in processor instructions 
targetting these accumulators, and many of the original MIPS ISA 
instructions that operated on HI/LO have been extended so that any of the 
four accumulators can be used.

 The access to these new registers has been long possible on Linux through 
the ptrace PTRACE_PEEKUSER and PTRACE_POKEUSER requests.  These registers 
are not accessible as a a part of any register set and must always be 
transferred individually.  They are not written to core dumps either 
(arguably their values are hardly useful for post-mortem analysis as to 
cause a core dump in the first place any of these would have to be 
transferred to a general register first anyway; DSPCTL might be marginally 
useful in the context of the BPOSGE32 and BPOSGE64 branches).

 As this mixed regset/individual access requirement seems unique to the 
MIPS/Linux DSP target, I made some adjustments to the native accessors as 
well as some more extensive changes to gdbserver that did not seem to 
support such an arrangement.  The new regset_bitmap backend vector's 
member is used to report the bitmap of registers that need not be 
transferred individually unless regset access has failed to gdbserver's 
generic Linux core.

 Some changes were needed to the way the generic MIPS backend handles 
register numbers too.  There has never really been any need for the Linux 
ABI to use the embedded register numbers, but it was done so regardless, 
presumably hoping for some simplification of code.  With the DSP registers 
in place this is actually troublesome as they'd have to either overlap 
with some numbers allocated for the embedded registers or they'd have to 
be added at the end making the allocated register array unnecessary large.  
That would conflict with some embedded register changes I plan later on 
too.

 Therefore I decided to take the clean approach and disentangle the Linux 
register numbers from the embedded register numbers altogether -- the 
Linux ABI now uses a separate matrix as the IRIX ABI does.  This required 
obvious changes throughout to use register numbers recorded in the gdbarch 
rather than hardcoded constants.  It may make sense to define another set 
of macros to replace the immediates used in mips_gdbarch_init for IRIX and 
Linux, but that's logically a separate change, so I refrained from making 
it on this occasion.

 Other than that the change is hopefully obvious, but please do not 
hesitate to send me any questions or comments that you may have.

 No regressions on i686-linux-gnu (remotely, via gdbserver), mips-sde-elf 
(remotely, using a simulator), mips-linux-gnu (remotely, via gdbserver) or 
mips64el-linux-gnu (natively).  Remote mips-linux-gnu testing was done 
with both a DSP and a non-DSP ASE processor.  Native mips64el-linux-gnu 
testing was done with a non-DSP ASE processor as we have no DSP ASE 
processor equipped enough for local DejaGNU testing available.

 However I did some manual tests with native GDB and via gdbserver on a 
DSP ASE processor to make sure it does the right thing, including 
verifying the register dump (`info registers'), internal register data 
(`maint print registers'), the ability to write new values to DSP 
registers and correct register values reported after instructions 
targetting these registers have executed.

 OK to apply?

2011-11-22  Maciej W. Rozycki  <macro@mips.com>
            Chris Dearman  <chris@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>
            Joseph Myers  <joseph@codesourcery.com>

	gdb/
	* features/mips-dsp.xml: New file.
	* features/mips64-dsp.xml: New file.
	* features/mips-dsp-linux.xml: New file.
	* features/mips64-dsp-linux.xml: New file.
	* features/Makefile (WHICH): Add mips-dsp-linux and
	mips64-dsp-linux.
	(mips-dsp-expedite, mips64-dsp-expedite): New variables.
	* features/mips-dsp-linux.c: New file.
	* features/mips64-dsp-linux.c: New file.
	* regformats/mips-dsp-linux.dat: New file.
	* regformats/mips64-dsp-linux.dat: New file.
	* mips-linux-nat.c (mips_linux_register_addr): Handle DSP
	registers.
	(mips64_linux_register_addr): Likewise.
	(mips64_linux_regsets_fetch_registers): Likewise.
	(mips64_linux_regsets_store_registers): Likewise.
        (mips64_linux_fetch_registers): Update call to
        mips64_linux_regsets_fetch_registers.
        (mips64_linux_store_registers): Update call to
        mips64_linux_regsets_store_registers.
	(mips_linux_read_description): Probe for DSP registers.
	(_initialize_mips_linux_nat): Call initialize_tdesc_mips_dsp_linux
	and initialize_tdesc_mips64_dsp_linux.
	* mips-linux-tdep.c (supply_gregset, mips64_supply_gregset):
	Remove padding of no longer used embedded register slots.
	* mips-linux-tdep.h (DSP_BASE, DSP_CONTROL): New macros.
	(MIPS_RESTART_REGNUM): Redefine enum value.
	* mips-tdep.c (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_register_type): Exclude embedded registers for the IRIX
	and Linux ABIs.
	(mips_pseudo_register_type): Likewise.  Use dynamic numbers to
	refer to FP registers, LO, HI, BadVAddr, Cause and PC.  Handle
	DSP registers.
	(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 the Linux ABI.  Use dynamic numbers to refer to
	registers, as applicable, while parsing the target description.
	* mips-tdep.h (struct mips_regnum): Add dspacc/dspctl offsets.

2011-11-22  Maciej W. Rozycki  <macro@codesourcery.com>

	gdb/gdbserver/
	* linux-low.h (linux_target_ops): Add regset_bitmap member.
	* linux-low.c (use_linux_regsets): New macro.
	(regsets_fetch_inferior_registers): Likewise.
	(regsets_store_inferior_registers): Likewise.
	(linux_register_in_regsets): New function.
	(usr_fetch_inferior_registers): Skip registers covered by
	regsets.
	(usr_store_inferior_registers): Likewise.
	(usr_fetch_inferior_registers): New macro.
	(usr_store_inferior_registers): Likewise.
	(linux_fetch_registers): Handle mixed regset/non-regset targets.
	(linux_store_registers): Likewise.
	* linux-mips-low.c (init_registers_mips_dsp_linux): New
	prototype.
	(init_registers_mips64_dsp_linux): Likewise.
	(init_registers_mips_linux): New macro.
	(init_registers_mips_dsp_linux): Likewise.
	(mips_dsp_num_regs): Likewise.
	(DSP_BASE, DSP_CONTROL): New fallback macros.
	(mips_base_regs): New macro.
	(mips_regmap): Use it.  Fix the size.
	(mips_dsp_regmap): New variable.
	(mips_dsp_regset_bitmap): Likewise.
	(mips_arch_setup): New function.
	(mips_cannot_fetch_register): Use the_low_target.regmap rather
	than mips_regmap.
	(mips_cannot_store_register): Likewise.
	(the_low_target): Update .arch_setup, .num_regs and .regmap
	initializers.  Add .regset_bitmap initializer.
	* linux-arm-low.c (the_low_target): Add .regset_bitmap
	initializer.
	* linux-bfin-low.c (the_low_target): Likewise.
	* linux-cris-low.c (the_low_target): Likewise.
	* linux-crisv32-low.c (the_low_target): Likewise.
	* linux-ia64-low.c (the_low_target): Likewise.
	* linux-m32r-low.c (the_low_target): Likewise.
	* linux-m68k-low.c (the_low_target): Likewise.
	* linux-ppc-low.c (the_low_target): Likewise.
	* linux-s390-low.c (the_low_target): Likewise.
	* linux-sh-low.c (the_low_target): Likewise.
	* linux-sparc-low.c (the_low_target): Likewise.
	* linux-tic6x-low.c (the_low_target): Likewise.
	* linux-x86-low.c (the_low_target): Likewise.
	* linux-xtensa-low.c (the_low_target): Likewise.
	* configure.srv <mips*-*-linux*>: Add mips-dsp-linux.o and
	mips64-dsp-linux.o to srv_regobj.  Add mips-dsp-linux.xml,
	mips64-dsp-linux.xml, mips-dsp.xml and mips64-dsp.xml to
	srv_xmlfiles.
	* Makefile.in (mips-dsp-linux.o, mips-dsp-linux.c): New targets.
	(mips64-dsp-linux.o, mips64-dsp-linux.c): Likewise.

2011-11-22  Maciej W. Rozycki  <macro@mips.com>

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

  Maciej

Index: gdb-fsf-trunk-quilt/gdb/features/Makefile
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/features/Makefile	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/Makefile	2011-11-21 20:02:55.395618342 +0000
@@ -36,7 +36,8 @@ WHICH = arm-with-iwmmxt arm-with-vfpv2 a
 	i386/amd64 i386/amd64-linux \
 	i386/i386-avx i386/i386-avx-linux \
 	i386/amd64-avx i386/amd64-avx-linux \
-	mips-linux mips64-linux \
+	mips-linux mips-dsp-linux \
+	mips64-linux mips64-dsp-linux \
 	rs6000/powerpc-32 \
 	rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
 	rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \
@@ -58,7 +59,9 @@ i386/i386-mmx-linux-expedite = ebp,esp,e
 i386/amd64-avx-expedite = rbp,rsp,rip
 i386/amd64-avx-linux-expedite = rbp,rsp,rip
 mips-expedite = r29,pc
+mips-dsp-expedite = r29,pc
 mips64-expedite = r29,pc
+mips64-dsp-expedite = r29,pc
 powerpc-expedite = r1,pc
 rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
 rs6000/powerpc-cell64l-expedite = r1,pc,r0,orig_r3,r4
Index: gdb-fsf-trunk-quilt/gdb/features/mips-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips-dsp-linux.c	2011-11-21 20:02:55.395618342 +0000
@@ -0,0 +1,110 @@
+/* THIS FILE IS GENERATED.  Original: mips-dsp-linux.xml */
+
+#include "defs.h"
+#include "osabi.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 tdesc_type *field_type, *type;
+
+  set_tdesc_architecture (result, bfd_scan_arch ("mips"));
+
+  set_tdesc_osabi (result, osabi_from_tdesc_string ("GNU/Linux"));
+
+  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: gdb-fsf-trunk-quilt/gdb/features/mips-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips-dsp-linux.xml	2011-11-21 20:02:55.395618342 +0000
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010, 2011 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>
+  <osabi>GNU/Linux</osabi>
+  <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"/>
+  </feature>
+</target>
Index: gdb-fsf-trunk-quilt/gdb/features/mips-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips-dsp.xml	2011-11-21 20:02:55.395618342 +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: gdb-fsf-trunk-quilt/gdb/features/mips64-dsp-linux.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips64-dsp-linux.c	2011-11-21 20:02:55.395618342 +0000
@@ -0,0 +1,108 @@
+/* THIS FILE IS GENERATED.  Original: mips64-dsp-linux.xml */
+
+#include "defs.h"
+#include "osabi.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 tdesc_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: gdb-fsf-trunk-quilt/gdb/features/mips64-dsp-linux.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips64-dsp-linux.xml	2011-11-21 20:02:55.395618342 +0000
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008, 2009, 2010, 2011 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"/>
+  </feature>
+</target>
Index: gdb-fsf-trunk-quilt/gdb/features/mips64-dsp.xml
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/features/mips64-dsp.xml	2011-11-21 20:02:55.395618342 +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: gdb-fsf-trunk-quilt/gdb/gdbserver/Makefile.in
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/Makefile.in	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/Makefile.in	2011-11-21 20:02:55.395618342 +0000
@@ -540,9 +540,15 @@ reg-cf.c : $(srcdir)/../regformats/reg-c
 mips-linux.o : mips-linux.c $(regdef_h)
 mips-linux.c : $(srcdir)/../regformats/mips-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-linux.dat mips-linux.c
+mips-dsp-linux.o : mips-dsp-linux.c $(regdef_h)
+mips-dsp-linux.c : $(srcdir)/../regformats/mips-dsp-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips-dsp-linux.dat mips-dsp-linux.c
 mips64-linux.o : mips64-linux.c $(regdef_h)
 mips64-linux.c : $(srcdir)/../regformats/mips64-linux.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-linux.dat mips64-linux.c
+mips64-dsp-linux.o : mips64-dsp-linux.c $(regdef_h)
+mips64-dsp-linux.c : $(srcdir)/../regformats/mips64-dsp-linux.dat $(regdat_sh)
+	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/mips64-dsp-linux.dat mips64-dsp-linux.c
 powerpc-32.o : powerpc-32.c $(regdef_h)
 powerpc-32.c : $(srcdir)/../regformats/rs6000/powerpc-32.dat $(regdat_sh)
 	$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-32.dat powerpc-32.c
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/configure.srv
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/configure.srv	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/configure.srv	2011-11-21 20:02:55.395618342 +0000
@@ -151,16 +151,23 @@ case "${target}" in
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
-  mips*-*-linux*)	srv_regobj="mips-linux.o mips64-linux.o"
+  mips*-*-linux*)	srv_regobj="mips-linux.o"
+			srv_regobj="${srv_regobj} mips-dsp-linux.o"
+			srv_regobj="${srv_regobj} mips64-linux.o"
+			srv_regobj="${srv_regobj} mips64-dsp-linux.o"
 			srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o linux-procfs.o"
 			srv_xmlfiles="mips-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips-fpu.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips-dsp.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-linux.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips64-dsp-linux.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-cpu.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-cp0.xml"
 			srv_xmlfiles="${srv_xmlfiles} mips64-fpu.xml"
+			srv_xmlfiles="${srv_xmlfiles} mips64-dsp.xml"
 			srv_linux_regsets=yes
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-arm-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-arm-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-arm-low.c	2011-11-21 20:02:55.395618342 +0000
@@ -835,6 +835,7 @@ struct linux_target_ops the_low_target =
   arm_arch_setup,
   arm_num_regs,
   arm_regmap,
+  NULL,
   arm_cannot_fetch_register,
   arm_cannot_store_register,
   arm_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-bfin-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-bfin-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-bfin-low.c	2011-11-21 20:02:55.395618342 +0000
@@ -95,6 +95,7 @@ struct linux_target_ops the_low_target =
   init_registers_bfin,
   bfin_num_regs,
   bfin_regmap,
+  NULL,
   bfin_cannot_fetch_register,
   bfin_cannot_store_register,
   bfin_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-cris-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-cris-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-cris-low.c	2011-11-21 20:02:55.395618342 +0000
@@ -112,6 +112,7 @@ struct linux_target_ops the_low_target =
   init_registers_cris,
   cris_num_regs,
   cris_regmap,
+  NULL,
   cris_cannot_fetch_register,
   cris_cannot_store_register,
   cris_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-crisv32-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-crisv32-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-crisv32-low.c	2011-11-21 20:02:55.395618342 +0000
@@ -376,6 +376,7 @@ struct linux_target_ops the_low_target =
   NULL,
   NULL,
   NULL,
+  NULL,
   cris_get_pc,
   cris_set_pc,
   (const unsigned char *) &cris_breakpoint,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-ia64-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-ia64-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-ia64-low.c	2011-11-21 20:02:55.395618342 +0000
@@ -282,6 +282,7 @@ struct linux_target_ops the_low_target =
   init_registers_ia64,
   ia64_num_regs,
   ia64_regmap,
+  NULL,
   ia64_cannot_fetch_register,
   ia64_cannot_store_register,
 };
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -3712,145 +3712,11 @@ unstop_all_lwps (int unsuspend, struct l
     find_inferior (&all_lwps, proceed_one_lwp, except);
 }
 
-#ifdef HAVE_LINUX_USRREGS
-
-int
-register_addr (int regnum)
-{
-  int addr;
-
-  if (regnum < 0 || regnum >= the_low_target.num_regs)
-    error ("Invalid register number %d.", regnum);
-
-  addr = the_low_target.regmap[regnum];
-
-  return addr;
-}
-
-/* Fetch one register.  */
-static void
-fetch_register (struct regcache *regcache, int regno)
-{
-  CORE_ADDR regaddr;
-  int i, size;
-  char *buf;
-  int pid;
-
-  if (regno >= the_low_target.num_regs)
-    return;
-  if ((*the_low_target.cannot_fetch_register) (regno))
-    return;
-
-  regaddr = register_addr (regno);
-  if (regaddr == -1)
-    return;
-
-  size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
-	  & -sizeof (PTRACE_XFER_TYPE));
-  buf = alloca (size);
-
-  pid = lwpid_of (get_thread_lwp (current_inferior));
-  for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
-    {
-      errno = 0;
-      *(PTRACE_XFER_TYPE *) (buf + i) =
-	ptrace (PTRACE_PEEKUSER, pid,
-		/* Coerce to a uintptr_t first to avoid potential gcc warning
-		   of coercing an 8 byte integer to a 4 byte pointer.  */
-		(PTRACE_ARG3_TYPE) (uintptr_t) regaddr, 0);
-      regaddr += sizeof (PTRACE_XFER_TYPE);
-      if (errno != 0)
-	error ("reading register %d: %s", regno, strerror (errno));
-    }
-
-  if (the_low_target.supply_ptrace_register)
-    the_low_target.supply_ptrace_register (regcache, regno, buf);
-  else
-    supply_register (regcache, regno, buf);
-}
-
-/* Store one register.  */
-static void
-store_register (struct regcache *regcache, int regno)
-{
-  CORE_ADDR regaddr;
-  int i, size;
-  char *buf;
-  int pid;
-
-  if (regno >= the_low_target.num_regs)
-    return;
-  if ((*the_low_target.cannot_store_register) (regno))
-    return;
-
-  regaddr = register_addr (regno);
-  if (regaddr == -1)
-    return;
-
-  size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
-	  & -sizeof (PTRACE_XFER_TYPE));
-  buf = alloca (size);
-  memset (buf, 0, size);
-
-  if (the_low_target.collect_ptrace_register)
-    the_low_target.collect_ptrace_register (regcache, regno, buf);
-  else
-    collect_register (regcache, regno, buf);
-
-  pid = lwpid_of (get_thread_lwp (current_inferior));
-  for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
-    {
-      errno = 0;
-      ptrace (PTRACE_POKEUSER, pid,
-	    /* Coerce to a uintptr_t first to avoid potential gcc warning
-	       about coercing an 8 byte integer to a 4 byte pointer.  */
-	      (PTRACE_ARG3_TYPE) (uintptr_t) regaddr,
-	      (PTRACE_ARG4_TYPE) *(PTRACE_XFER_TYPE *) (buf + i));
-      if (errno != 0)
-	{
-	  /* At this point, ESRCH should mean the process is
-	     already gone, in which case we simply ignore attempts
-	     to change its registers.  See also the related
-	     comment in linux_resume_one_lwp.  */
-	  if (errno == ESRCH)
-	    return;
-
-	  if ((*the_low_target.cannot_store_register) (regno) == 0)
-	    error ("writing register %d: %s", regno, strerror (errno));
-	}
-      regaddr += sizeof (PTRACE_XFER_TYPE);
-    }
-}
-
-/* Fetch all registers, or just one, from the child process.  */
-static void
-usr_fetch_inferior_registers (struct regcache *regcache, int regno)
-{
-  if (regno == -1)
-    for (regno = 0; regno < the_low_target.num_regs; regno++)
-      fetch_register (regcache, regno);
-  else
-    fetch_register (regcache, regno);
-}
-
-/* Store our register values back into the inferior.
-   If REGNO is -1, do this for all registers.
-   Otherwise, REGNO specifies which register (so we can save time).  */
-static void
-usr_store_inferior_registers (struct regcache *regcache, int regno)
-{
-  if (regno == -1)
-    for (regno = 0; regno < the_low_target.num_regs; regno++)
-      store_register (regcache, regno);
-  else
-    store_register (regcache, regno);
-}
-#endif /* HAVE_LINUX_USRREGS */
-
-
 
 #ifdef HAVE_LINUX_REGSETS
 
+#define use_linux_regsets 1
+
 static int
 regsets_fetch_inferior_registers (struct regcache *regcache)
 {
@@ -4010,34 +3876,224 @@ regsets_store_inferior_registers (struct
     return 0;
   else
     return 1;
-  return 0;
 }
 
-#endif /* HAVE_LINUX_REGSETS */
+#else /* !HAVE_LINUX_REGSETS */
 
+#define use_linux_regsets 0
+#define regsets_fetch_inferior_registers(regcache) 1
+#define regsets_store_inferior_registers(regcache) 1
 
-void
-linux_fetch_registers (struct regcache *regcache, int regno)
-{
-#ifdef HAVE_LINUX_REGSETS
-  if (regsets_fetch_inferior_registers (regcache) == 0)
-    return;
 #endif
+
+/* Return 1 if register REGNO is supported by one of the regset ptrace
+   calls or 0 if it has to be transferred individually.  */
+
+static int
+linux_register_in_regsets (int regno)
+{
+  unsigned char mask = 1 << (regno % 8);
+  size_t index = regno / 8;
+
+  return (use_linux_regsets
+	  && (the_low_target.regset_bitmap == NULL
+	      || (the_low_target.regset_bitmap[index] & mask) != 0));
+}
+
 #ifdef HAVE_LINUX_USRREGS
-  usr_fetch_inferior_registers (regcache, regno);
+
+int
+register_addr (int regnum)
+{
+  int addr;
+
+  if (regnum < 0 || regnum >= the_low_target.num_regs)
+    error ("Invalid register number %d.", regnum);
+
+  addr = the_low_target.regmap[regnum];
+
+  return addr;
+}
+
+/* Fetch one register.  */
+static void
+fetch_register (struct regcache *regcache, int regno)
+{
+  CORE_ADDR regaddr;
+  int i, size;
+  char *buf;
+  int pid;
+
+  if (regno >= the_low_target.num_regs)
+    return;
+  if ((*the_low_target.cannot_fetch_register) (regno))
+    return;
+
+  regaddr = register_addr (regno);
+  if (regaddr == -1)
+    return;
+
+  size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
+	  & -sizeof (PTRACE_XFER_TYPE));
+  buf = alloca (size);
+
+  pid = lwpid_of (get_thread_lwp (current_inferior));
+  for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      *(PTRACE_XFER_TYPE *) (buf + i) =
+	ptrace (PTRACE_PEEKUSER, pid,
+		/* Coerce to a uintptr_t first to avoid potential gcc warning
+		   of coercing an 8 byte integer to a 4 byte pointer.  */
+		(PTRACE_ARG3_TYPE) (uintptr_t) regaddr, 0);
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+      if (errno != 0)
+	error ("reading register %d: %s", regno, strerror (errno));
+    }
+
+  if (the_low_target.supply_ptrace_register)
+    the_low_target.supply_ptrace_register (regcache, regno, buf);
+  else
+    supply_register (regcache, regno, buf);
+}
+
+/* Store one register.  */
+static void
+store_register (struct regcache *regcache, int regno)
+{
+  CORE_ADDR regaddr;
+  int i, size;
+  char *buf;
+  int pid;
+
+  if (regno >= the_low_target.num_regs)
+    return;
+  if ((*the_low_target.cannot_store_register) (regno))
+    return;
+
+  regaddr = register_addr (regno);
+  if (regaddr == -1)
+    return;
+
+  size = ((register_size (regno) + sizeof (PTRACE_XFER_TYPE) - 1)
+	  & -sizeof (PTRACE_XFER_TYPE));
+  buf = alloca (size);
+  memset (buf, 0, size);
+
+  if (the_low_target.collect_ptrace_register)
+    the_low_target.collect_ptrace_register (regcache, regno, buf);
+  else
+    collect_register (regcache, regno, buf);
+
+  pid = lwpid_of (get_thread_lwp (current_inferior));
+  for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
+    {
+      errno = 0;
+      ptrace (PTRACE_POKEUSER, pid,
+	    /* Coerce to a uintptr_t first to avoid potential gcc warning
+	       about coercing an 8 byte integer to a 4 byte pointer.  */
+	      (PTRACE_ARG3_TYPE) (uintptr_t) regaddr,
+	      (PTRACE_ARG4_TYPE) *(PTRACE_XFER_TYPE *) (buf + i));
+      if (errno != 0)
+	{
+	  /* At this point, ESRCH should mean the process is
+	     already gone, in which case we simply ignore attempts
+	     to change its registers.  See also the related
+	     comment in linux_resume_one_lwp.  */
+	  if (errno == ESRCH)
+	    return;
+
+	  if ((*the_low_target.cannot_store_register) (regno) == 0)
+	    error ("writing register %d: %s", regno, strerror (errno));
+	}
+      regaddr += sizeof (PTRACE_XFER_TYPE);
+    }
+}
+
+/* Fetch all registers, or just one, from the child process.
+   If REGNO is -1, do this for all registers, skipping any that are
+   assumed to have been retrieved by regsets_fetch_inferior_registers,
+   unless ALL is non-zero.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+static void
+usr_fetch_inferior_registers (struct regcache *regcache, int regno, int all)
+{
+  if (regno == -1)
+    {
+      for (regno = 0; regno < the_low_target.num_regs; regno++)
+	if (all || !linux_register_in_regsets (regno))
+	  fetch_register (regcache, regno);
+    }
+  else
+    fetch_register (regcache, regno);
+}
+
+/* Store our register values back into the inferior.
+   If REGNO is -1, do this for all registers, skipping any that are
+   assumed to have been saved by regsets_store_inferior_registers,
+   unless ALL is non-zero.
+   Otherwise, REGNO specifies which register (so we can save time).  */
+static void
+usr_store_inferior_registers (struct regcache *regcache, int regno, int all)
+{
+  if (regno == -1)
+    {
+      for (regno = 0; regno < the_low_target.num_regs; regno++)
+	if (all || !linux_register_in_regsets (regno))
+	  store_register (regcache, regno);
+    }
+  else
+    store_register (regcache, regno);
+}
+
+#else /* !HAVE_LINUX_USRREGS */
+
+#define usr_fetch_inferior_registers(regcache, regno, all) do {} while (0)
+#define usr_store_inferior_registers(regcache, regno, all) do {} while (0)
+
 #endif
+
+
+void
+linux_fetch_registers (struct regcache *regcache, int regno)
+{
+  int use_regsets;
+  int all = 0;
+
+  if (regno == -1)
+    {
+      all = regsets_fetch_inferior_registers (regcache);
+      usr_fetch_inferior_registers (regcache, regno, all);
+    }
+  else
+    {
+      use_regsets = linux_register_in_regsets (regno);
+      if (use_regsets)
+	all = regsets_fetch_inferior_registers (regcache);
+      if (!use_regsets || all)
+	usr_fetch_inferior_registers (regcache, regno, 1);
+    }
 }
 
 void
 linux_store_registers (struct regcache *regcache, int regno)
 {
-#ifdef HAVE_LINUX_REGSETS
-  if (regsets_store_inferior_registers (regcache) == 0)
-    return;
-#endif
-#ifdef HAVE_LINUX_USRREGS
-  usr_store_inferior_registers (regcache, regno);
-#endif
+  int use_regsets;
+  int all = 0;
+
+  if (regno == -1)
+    {
+      all = regsets_store_inferior_registers (regcache);
+      usr_store_inferior_registers (regcache, regno, all);
+    }
+  else
+    {
+      use_regsets = linux_register_in_regsets (regno);
+      if (use_regsets)
+	all = regsets_store_inferior_registers (regcache);
+      if (!use_regsets || all)
+	usr_store_inferior_registers (regcache, regno, 1);
+    }
 }
 
 
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-low.h	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-low.h	2011-11-21 20:02:55.405560276 +0000
@@ -67,6 +67,12 @@ struct linux_target_ops
 
   int num_regs;
   int *regmap;
+
+  /* Regset support bitmap: 1 for registers that are transferred as a part
+     of a regset, 0 for ones that need to be handled individually.  This
+     can be NULL if all registers are transferred with regsets or regsets
+     are not supported.  */
+  unsigned char *regset_bitmap;
   int (*cannot_fetch_register) (int);
 
   /* Returns 0 if we can store the register, 1 if we can not
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-m32r-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-m32r-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-m32r-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -92,6 +92,7 @@ struct linux_target_ops the_low_target =
   init_registers_m32r,
   m32r_num_regs,
   m32r_regmap,
+  NULL,
   m32r_cannot_fetch_register,
   m32r_cannot_store_register,
   m32r_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-m68k-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-m68k-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-m68k-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -179,6 +179,7 @@ struct linux_target_ops the_low_target =
   init_registers_m68k,
   m68k_num_regs,
   m68k_regmap,
+  NULL,
   m68k_cannot_fetch_register,
   m68k_cannot_store_register,
   m68k_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-mips-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-mips-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-mips-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -27,8 +27,17 @@
 
 /* Defined in auto-generated file mips-linux.c.  */
 void init_registers_mips_linux (void);
+/* Defined in auto-generated file mips-dsp-linux.c.  */
+void init_registers_mips_dsp_linux (void);
 /* Defined in auto-generated file mips64-linux.c.  */
 void init_registers_mips64_linux (void);
+/* Defined in auto-generated file mips64-dsp-linux.c.  */
+void init_registers_mips64_dsp_linux (void);
+
+#ifdef __mips64
+#define init_registers_mips_linux init_registers_mips64_linux
+#define init_registers_mips_dsp_linux init_registers_mips64_dsp_linux
+#endif
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 25
@@ -39,9 +48,15 @@ void init_registers_mips64_linux (void);
 #endif
 
 #define mips_num_regs 73
+#define mips_dsp_num_regs 80
 
 #include <asm/ptrace.h>
 
+#ifndef DSP_BASE
+#define DSP_BASE 71
+#define DSP_CONTROL 77
+#endif
+
 union mips_register
 {
   unsigned char buf[8];
@@ -53,27 +68,84 @@ union mips_register
 
 /* Return the ptrace ``address'' of register REGNO. */
 
-static int mips_regmap[] = {
-  -1,  1,  2,  3,  4,  5,  6,  7,
-  8,  9,  10, 11, 12, 13, 14, 15,
-  16, 17, 18, 19, 20, 21, 22, 23,
-  24, 25, 26, 27, 28, 29, 30, 31,
+#define mips_base_regs							\
+  -1,  1,  2,  3,  4,  5,  6,  7,					\
+  8,  9,  10, 11, 12, 13, 14, 15,					\
+  16, 17, 18, 19, 20, 21, 22, 23,					\
+  24, 25, 26, 27, 28, 29, 30, 31,					\
+									\
+  -1, MMLO, MMHI, BADVADDR, CAUSE, PC,					\
+									\
+  FPR_BASE,      FPR_BASE + 1,  FPR_BASE + 2,  FPR_BASE + 3,		\
+  FPR_BASE + 4,  FPR_BASE + 5,  FPR_BASE + 6,  FPR_BASE + 7,		\
+  FPR_BASE + 8,  FPR_BASE + 9,  FPR_BASE + 10, FPR_BASE + 11,		\
+  FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15,		\
+  FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19,		\
+  FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23,		\
+  FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27,		\
+  FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31,		\
+  FPC_CSR, FPC_EIR
 
-  -1, MMLO, MMHI, BADVADDR, CAUSE, PC,
+#define mips_dsp_regs							\
+  DSP_BASE,      DSP_BASE + 1,  DSP_BASE + 2,  DSP_BASE + 3,		\
+  DSP_BASE + 4,  DSP_BASE + 5,						\
+  DSP_CONTROL
 
-  FPR_BASE,      FPR_BASE + 1,  FPR_BASE + 2,  FPR_BASE + 3,
-  FPR_BASE + 4,  FPR_BASE + 5,  FPR_BASE + 6,  FPR_BASE + 7,
-  FPR_BASE + 8,  FPR_BASE + 9,  FPR_BASE + 10, FPR_BASE + 11,
-  FPR_BASE + 12, FPR_BASE + 13, FPR_BASE + 14, FPR_BASE + 15,
-  FPR_BASE + 16, FPR_BASE + 17, FPR_BASE + 18, FPR_BASE + 19,
-  FPR_BASE + 20, FPR_BASE + 21, FPR_BASE + 22, FPR_BASE + 23,
-  FPR_BASE + 24, FPR_BASE + 25, FPR_BASE + 26, FPR_BASE + 27,
-  FPR_BASE + 28, FPR_BASE + 29, FPR_BASE + 30, FPR_BASE + 31,
-  FPC_CSR, FPC_EIR,
+static int mips_regmap[mips_num_regs] = {
+  mips_base_regs,
+  0
+};
 
+static int mips_dsp_regmap[mips_dsp_num_regs] = {
+  mips_base_regs,
+  mips_dsp_regs,
   0
 };
 
+/* DSP registers are not in any regset and can only be accessed
+   individually.  */
+
+static unsigned char mips_dsp_regset_bitmap[(mips_dsp_num_regs + 7) / 8] = {
+  0xfe, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x80
+};
+
+/* Try peeking at an arbitrarily chosen DSP register and pick the available
+   user register set accordingly.  */
+
+static void
+mips_arch_setup (void)
+{
+  static void (*init_registers) (void);
+
+  gdb_assert (current_inferior);
+
+  if (init_registers == NULL)
+    {
+      int pid = lwpid_of (get_thread_lwp (current_inferior));
+
+      ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0);
+      switch (errno)
+	{
+	case 0:
+	  the_low_target.num_regs = mips_dsp_num_regs;
+	  the_low_target.regmap = mips_dsp_regmap;
+	  the_low_target.regset_bitmap = mips_dsp_regset_bitmap;
+	  init_registers = init_registers_mips_dsp_linux;
+	  break;
+	case EIO:
+	  the_low_target.num_regs = mips_num_regs;
+	  the_low_target.regmap = mips_regmap;
+	  the_low_target.regset_bitmap = NULL;
+	  init_registers = init_registers_mips_linux;
+	  break;
+	default:
+	  perror_with_name ("ptrace");
+	  break;
+	}
+    }
+  init_registers ();
+}
+
 /* From mips-linux-nat.c.  */
 
 /* Pseudo registers can not be read.  ptrace does not provide a way to
@@ -84,7 +156,7 @@ static int mips_regmap[] = {
 static int
 mips_cannot_fetch_register (int regno)
 {
-  if (mips_regmap[regno] == -1)
+  if (the_low_target.regmap[regno] == -1)
     return 1;
 
   if (find_regno ("r0") == regno)
@@ -96,7 +168,7 @@ mips_cannot_fetch_register (int regno)
 static int
 mips_cannot_store_register (int regno)
 {
-  if (mips_regmap[regno] == -1)
+  if (the_low_target.regmap[regno] == -1)
     return 1;
 
   if (find_regno ("r0") == regno)
@@ -352,13 +424,10 @@ struct regset_info target_regsets[] = {
 };
 
 struct linux_target_ops the_low_target = {
-#ifdef __mips64
-  init_registers_mips64_linux,
-#else
-  init_registers_mips_linux,
-#endif
-  mips_num_regs,
-  mips_regmap,
+  mips_arch_setup,
+  -1,
+  NULL,
+  NULL,
   mips_cannot_fetch_register,
   mips_cannot_store_register,
   mips_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-ppc-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-ppc-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-ppc-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -610,6 +610,7 @@ struct linux_target_ops the_low_target =
   ppc_arch_setup,
   ppc_num_regs,
   ppc_regmap,
+  NULL,
   ppc_cannot_fetch_register,
   ppc_cannot_store_register,
   ppc_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-s390-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-s390-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-s390-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -309,6 +309,7 @@ struct linux_target_ops the_low_target =
   s390_arch_setup,
   s390_num_regs,
   s390_regmap,
+  NULL,
   s390_cannot_fetch_register,
   s390_cannot_store_register,
   s390_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-sh-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-sh-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-sh-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -112,6 +112,7 @@ struct linux_target_ops the_low_target =
   init_registers_sh,
   sh_num_regs,
   sh_regmap,
+  NULL,
   sh_cannot_fetch_register,
   sh_cannot_store_register,
   sh_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-sparc-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-sparc-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-sparc-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -282,6 +282,7 @@ struct linux_target_ops the_low_target =
   sparc_num_regs,
   /* No regmap needs to be provided since this impl. doesn't use USRREGS.  */
   NULL,
+  NULL,
   sparc_cannot_fetch_register,
   sparc_cannot_store_register,
   sparc_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-tic6x-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-tic6x-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-tic6x-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -322,6 +322,7 @@ struct linux_target_ops the_low_target =
   tic6x_arch_setup,
   TIC6X_NUM_REGS,
   0,
+  NULL,
   tic6x_cannot_fetch_register,
   tic6x_cannot_store_register,
   tic6x_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-x86-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-x86-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-x86-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -2938,6 +2938,7 @@ struct linux_target_ops the_low_target =
   NULL,
   NULL,
   NULL,
+  NULL,
   x86_get_pc,
   x86_set_pc,
   x86_breakpoint,
Index: gdb-fsf-trunk-quilt/gdb/gdbserver/linux-xtensa-low.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/gdbserver/linux-xtensa-low.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/gdbserver/linux-xtensa-low.c	2011-11-21 20:02:55.405560276 +0000
@@ -180,6 +180,7 @@ struct linux_target_ops the_low_target =
   init_registers_xtensa,
   0,
   0,
+  NULL,
   0,
   0,
   xtensa_get_pc,
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-nat.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-nat.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-nat.c	2011-11-21 20:02:55.405560276 +0000
@@ -37,7 +37,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
@@ -95,6 +97,12 @@ 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 != -1
+	   && 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
@@ -130,6 +138,12 @@ 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 != -1
+	   && 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
@@ -202,10 +216,13 @@ fill_fpregset (const struct regcache *re
    using PTRACE_GETREGS et al.  */
 
 static void
-mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
+mips64_linux_regsets_fetch_registers (struct target_ops *ops,
+				      struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int have_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -218,11 +235,23 @@ mips64_linux_regsets_fetch_registers (st
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  have_dsp = mips_regnum (gdbarch)->dspctl != -1;
+  if (!have_dsp)
+    is_dsp = 0;
+  else 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;
 
@@ -258,17 +287,30 @@ mips64_linux_regsets_fetch_registers (st
       mips64_supply_fpregset (regcache,
 			      (const mips64_elf_fpregset_t *) &fp_regs);
     }
+
+  if (is_dsp)
+    super_fetch_registers (ops, regcache, regno);
+  else if (regno == -1 && have_dsp)
+    {
+      for (regi = mips_regnum (gdbarch)->dspacc;
+	   regi < mips_regnum (gdbarch)->dspacc + 6;
+	   regi++)
+	super_fetch_registers (ops, regcache, regi);
+      super_fetch_registers (ops, 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 target_ops *ops,
+				      struct regcache *regcache, int regno)
 {
   struct gdbarch *gdbarch = get_regcache_arch (regcache);
-  int is_fp;
+  int is_fp, is_dsp;
+  int have_dsp;
+  int regi;
   int tid;
 
   if (regno >= mips_regnum (gdbarch)->fp0
@@ -281,11 +323,23 @@ mips64_linux_regsets_store_registers (co
   else
     is_fp = 0;
 
+  /* DSP registers are optional and not a part of any set.  */
+  have_dsp = mips_regnum (gdbarch)->dspctl != -1;
+  if (!have_dsp)
+    is_dsp = 0;
+  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;
 
@@ -312,6 +366,17 @@ 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 (ops, regcache, regno);
+  else if (regno == -1 && have_dsp)
+    {
+      for (regi = mips_regnum (gdbarch)->dspacc;
+	   regi < mips_regnum (gdbarch)->dspacc + 6;
+	   regi++)
+	super_store_registers (ops, regcache, regi);
+      super_store_registers (ops, regcache, mips_regnum (gdbarch)->dspctl);
+    }
 }
 
 /* Fetch REGNO (or all registers if REGNO == -1) from the target
@@ -323,7 +388,7 @@ mips64_linux_fetch_registers (struct tar
 {
   /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
   if (have_ptrace_regsets)
-    mips64_linux_regsets_fetch_registers (regcache, regnum);
+    mips64_linux_regsets_fetch_registers (ops, regcache, regnum);
 
   /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
      back to PTRACE_PEEKUSER.  */
@@ -340,7 +405,7 @@ mips64_linux_store_registers (struct tar
 {
   /* Unless we already know that PTRACE_GETREGS does not work, try it.  */
   if (have_ptrace_regsets)
-    mips64_linux_regsets_store_registers (regcache, regnum);
+    mips64_linux_regsets_store_registers (ops, regcache, regnum);
 
   /* If we know, or just found out, that PTRACE_GETREGS does not work, fall
      back to PTRACE_PEEKUSER.  */
@@ -363,12 +428,37 @@ mips_linux_register_u_offset (struct gdb
 static const struct target_desc *
 mips_linux_read_description (struct target_ops *ops)
 {
+  static int have_dsp = -1;
+
+  if (have_dsp < 0)
+    {
+      int tid;
+
+      tid = ptid_get_lwp (inferior_ptid);
+      if (tid == 0)
+	tid = ptid_get_pid (inferior_ptid);
+
+      ptrace (PTRACE_PEEKUSER, tid, DSP_CONTROL, 0);
+      switch (errno)
+	{
+	case 0:
+	  have_dsp = 1;
+	  break;
+	case EIO:
+	  have_dsp = 0;
+	  break;
+	default:
+	  perror_with_name ("ptrace");
+	  break;
+	}
+    }
+
   /* 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 have_dsp ? tdesc_mips_dsp_linux : tdesc_mips_linux;
   else
-    return tdesc_mips64_linux;
+    return have_dsp ? tdesc_mips64_dsp_linux : tdesc_mips64_linux;
 }
 
 #ifndef PTRACE_GET_WATCH_REGS
@@ -1089,5 +1179,7 @@ triggers a breakpoint or watchpoint."),
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_mips_linux ();
+  initialize_tdesc_mips_dsp_linux ();
   initialize_tdesc_mips64_linux ();
+  initialize_tdesc_mips64_dsp_linux ();
 }
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c	2011-11-21 20:02:55.405560276 +0000
@@ -120,13 +120,8 @@ mips_supply_gregset (struct regcache *re
   supply_32bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    regp + EF_CP0_CAUSE);
 
-  /* Fill inaccessible registers with zero.  */
+  /* Fill the inaccessible zero register 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);
 }
 
 static void
@@ -375,13 +370,8 @@ mips64_supply_gregset (struct regcache *
   supply_64bit_reg (regcache, mips_regnum (gdbarch)->cause,
 		    (const gdb_byte *) (regp + MIPS64_EF_CP0_CAUSE));
 
-  /* Fill inaccessible registers with zero.  */
+  /* Fill the inaccessible zero register 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);
 }
 
 static void
Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.h	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.h	2011-11-21 20:02:55.405560276 +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
@@ -97,7 +99,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 = 79
 };
 
 /* Return 1 if MIPS_RESTART_REGNUM is usable.  */
Index: gdb-fsf-trunk-quilt/gdb/mips-tdep.c
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.c	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.c	2011-11-21 20:02:55.415560252 +0000
@@ -392,9 +392,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.  */
@@ -420,7 +418,7 @@ static const char *mips_tx39_reg_names[N
   "", "", "", "", "", "", "", "",
   "", "", "", "",
   "", "", "", "", "", "", "", "",
-  "", "", "config", "cache", "debug", "depc", "epc", ""
+  "", "", "config", "cache", "debug", "depc", "epc",
 };
 
 /* Names of IRIX registers.  */
@@ -432,6 +430,16 @@ static const char *mips_irix_reg_names[N
   "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"
+};
+
 
 /* Return the name of the register corresponding to REGNO.  */
 static const char *
@@ -486,7 +494,9 @@ mips_register_name (struct gdbarch *gdba
   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__,
@@ -856,11 +866,17 @@ mips_register_type (struct gdbarch *gdba
     }
   else
     {
+      int rawnum = regnum - gdbarch_num_regs (gdbarch);
+
       /* 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 (rawnum == mips_regnum (gdbarch)->fp_control_status
+	  || rawnum == mips_regnum (gdbarch)->fp_implementation_revision)
+	return builtin_type (gdbarch)->builtin_int32;
+      else if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
+	       && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
+	       && rawnum >= MIPS_FIRST_EMBED_REGNUM
+	       && rawnum <= MIPS_LAST_EMBED_REGNUM)
 	/* The pseudo/cooked view of the embedded registers is always
 	   32-bit.  The raw view is handled below.  */
 	return builtin_type (gdbarch)->builtin_int32;
@@ -899,37 +915,50 @@ mips_pseudo_register_type (struct gdbarc
   if (TYPE_LENGTH (rawtype) == 0)
     return rawtype;
 
-  if (rawnum >= MIPS_EMBED_FP0_REGNUM && rawnum < MIPS_EMBED_FP0_REGNUM + 32)
+  if (rawnum >= mips_regnum (gdbarch)->fp0
+      && rawnum < mips_regnum (gdbarch)->fp0 + 32)
     /* Present the floating point registers however the hardware did;
        do not try to convert between FPU layouts.  */
     return rawtype;
 
-  if (rawnum >= MIPS_EMBED_FP0_REGNUM + 32 && rawnum <= MIPS_LAST_EMBED_REGNUM)
-    {
-      /* The pseudo/cooked view of embedded registers is always
-	 32-bit, even if the target transfers 64-bit values for them.
-	 New targets relying on XML descriptions should only transfer
-	 the necessary 32 bits, but older versions of GDB expected 64,
-	 so allow the target to provide 64 bits without interfering
-	 with the displayed type.  */
-      return builtin_type (gdbarch)->builtin_int32;
-    }
-
   /* Use pointer types for registers if we can.  For n32 we can not,
      since we do not have a 64-bit pointer type.  */
   if (mips_abi_regsize (gdbarch)
       == TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr))
     {
-      if (rawnum == MIPS_SP_REGNUM || rawnum == MIPS_EMBED_BADVADDR_REGNUM)
+      if (rawnum == MIPS_SP_REGNUM
+	  || rawnum == mips_regnum (gdbarch)->badvaddr)
 	return builtin_type (gdbarch)->builtin_data_ptr;
-      else if (rawnum == MIPS_EMBED_PC_REGNUM)
+      else if (rawnum == mips_regnum (gdbarch)->pc)
 	return builtin_type (gdbarch)->builtin_func_ptr;
     }
 
   if (mips_abi_regsize (gdbarch) == 4 && TYPE_LENGTH (rawtype) == 8
-      && rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_EMBED_PC_REGNUM)
+      && ((rawnum >= MIPS_ZERO_REGNUM && rawnum <= MIPS_PS_REGNUM)
+	  || rawnum == mips_regnum (gdbarch)->lo
+	  || rawnum == mips_regnum (gdbarch)->hi
+	  || rawnum == mips_regnum (gdbarch)->badvaddr
+	  || rawnum == mips_regnum (gdbarch)->cause
+	  || rawnum == mips_regnum (gdbarch)->pc
+	  || (mips_regnum (gdbarch)->dspacc != -1
+	      && rawnum >= mips_regnum (gdbarch)->dspacc
+	      && rawnum < mips_regnum (gdbarch)->dspacc + 6)))
     return builtin_type (gdbarch)->builtin_int32;
 
+  if (gdbarch_osabi (gdbarch) != GDB_OSABI_IRIX
+      && gdbarch_osabi (gdbarch) != GDB_OSABI_LINUX
+      && rawnum >= MIPS_EMBED_FP0_REGNUM + 32
+      && rawnum <= MIPS_LAST_EMBED_REGNUM)
+    {
+      /* The pseudo/cooked view of embedded registers is always
+	 32-bit, even if the target transfers 64-bit values for them.
+	 New targets relying on XML descriptions should only transfer
+	 the necessary 32 bits, but older versions of GDB expected 64,
+	 so allow the target to provide 64 bits without interfering
+	 with the displayed type.  */
+      return builtin_type (gdbarch)->builtin_int32;
+    }
+
   /* For all other registers, pass through the hardware type.  */
   return rawtype;
 }
@@ -5514,6 +5543,8 @@ mips_stab_reg_to_regnum (struct gdbarch 
     regnum = mips_regnum (gdbarch)->hi;
   else if (num == 71)
     regnum = mips_regnum (gdbarch)->lo;
+  else if (mips_regnum (gdbarch)->dspacc != -1 && 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?  */
@@ -5537,6 +5568,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 (mips_regnum (gdbarch)->dspacc != -1 && 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?  */
@@ -5676,6 +5709,63 @@ 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;
+  const char **reg_names;
+  struct mips_regnum mips_regnum, *regnum;
+  int dspacc;
+  int dspctl;
+
+  /* Fill in the OS dependent 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 = dspacc = -1;
+      mips_regnum.dspctl = dspctl = -1;
+      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 = -1;
+      mips_regnum.dspctl = -1;
+      dspacc = 72;
+      dspctl = 78;
+      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 = dspacc = -1;
+      mips_regnum.dspctl = dspctl = -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))
@@ -5710,11 +5800,11 @@ mips_gdbarch_init (struct gdbarch_info i
 
 
       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)
 	{
@@ -5732,12 +5822,11 @@ mips_gdbarch_init (struct gdbarch_info i
 
       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)
 	{
@@ -5758,13 +5847,15 @@ mips_gdbarch_init (struct gdbarch_info i
       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)
 	{
@@ -5772,8 +5863,45 @@ mips_gdbarch_init (struct gdbarch_info i
 	  return NULL;
 	}
 
+      if (dspacc >= 0)
+	{
+	  feature = tdesc_find_feature (info.target_desc,
+					"org.gnu.gdb.mips.dsp");
+	  /* The DSP registers are optional; it's OK if they are absent.  */
+	  if (feature != NULL)
+	    {
+	      i = 0;
+	      valid_p = 1;
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "hi1");
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "lo1");
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "hi2");
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "lo2");
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "hi3");
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspacc + i++, "lo3");
+
+	      valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						  dspctl, "dspctl");
+
+	      if (!valid_p)
+		{
+		  tdesc_data_cleanup (tdesc_data);
+		  return NULL;
+		}
+
+	      mips_regnum.dspacc = dspacc;
+	      mips_regnum.dspctl = dspctl;
+	    }
+	}
+
       /* 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.  */
@@ -6022,66 +6150,19 @@ mips_gdbarch_init (struct gdbarch_info i
   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 gdbarch_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 gdbarch_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: gdb-fsf-trunk-quilt/gdb/mips-tdep.h
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/mips-tdep.h	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/mips-tdep.h	2011-11-21 20:02:55.415560252 +0000
@@ -54,6 +54,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);
 
Index: gdb-fsf-trunk-quilt/gdb/regformats/mips-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/regformats/mips-dsp-linux.dat	2011-11-21 20:02:55.415560252 +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:hi1
+32:lo1
+32:hi2
+32:lo2
+32:hi3
+32:lo3
+32:dspctl
+32:restart
Index: gdb-fsf-trunk-quilt/gdb/regformats/mips64-dsp-linux.dat
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb-fsf-trunk-quilt/gdb/regformats/mips64-dsp-linux.dat	2011-11-21 20:02:55.415560252 +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:hi1
+64:lo1
+64:hi2
+64:lo2
+64:hi3
+64:lo3
+32:dspctl
+64:restart
Index: gdb-fsf-trunk-quilt/gdb/testsuite/gdb.xml/tdesc-regs.exp
===================================================================
--- gdb-fsf-trunk-quilt.orig/gdb/testsuite/gdb.xml/tdesc-regs.exp	2011-11-21 20:02:53.085576708 +0000
+++ gdb-fsf-trunk-quilt/gdb/testsuite/gdb.xml/tdesc-regs.exp	2011-11-21 20:02:55.415560252 +0000
@@ -34,7 +34,7 @@ switch -glob -- [istarget] {
         set core-regs {m68k-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/"


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