[PATCH] MIPS/Linux: DSP ASE support

Joel Brobecker brobecker@adacore.com
Mon Feb 27 17:37:00 GMT 2012


Hi Maciej,

I was going to review this patch, but it touches two areas that I am
not very familiar with: gdbserver, and feature files. The changes in
the latter section seem OK to me, but there are still the gdbserver
bits (which also look logical to me, but I have been corrected on so
many of my own patches that I don't trust my judgement alone).

Just one tiny thing I noticed while scanning the changes.   Copyright:
2012 needs to be added for the new files.  If you are adding the year,
can you use the new format YYYY-2012 where YYYY is the smallest year
of the list?

Pedro,

Do you think you'd be able to review this patch for us?

Thanks!

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

-- 
Joel



More information about the Gdb-patches mailing list