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] |
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] |