From 1faeff088bbbd037d7769d214378b4faf805fa2e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Thu, 1 Mar 2012 22:19:48 +0000 Subject: [PATCH] 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. gdb/doc/ * gdb.texinfo (MIPS Features): Add org.gnu.gdb.mips.dsp. gdb/gdbserver/ * linux-low.h (linux_target_ops): Add regset_bitmap member. * linux-low.c (use_linux_regsets): New macro. [!HAVE_LINUX_REGSETS] (regsets_fetch_inferior_registers): Likewise. [!HAVE_LINUX_REGSETS] (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 : 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. gdb/testsuite/ * gdb.xml/tdesc-regs.exp: Add "mips-dsp.xml" to the list of MIPS core registers. --- gdb/ChangeLog | 51 ++++ gdb/doc/ChangeLog | 4 + gdb/doc/gdb.texinfo | 5 + gdb/features/Makefile | 5 +- gdb/features/mips-dsp-linux.c | 110 ++++++++ gdb/features/mips-dsp-linux.xml | 20 ++ gdb/features/mips-dsp.xml | 18 ++ gdb/features/mips64-dsp-linux.c | 108 ++++++++ gdb/features/mips64-dsp-linux.xml | 19 ++ gdb/features/mips64-dsp.xml | 18 ++ gdb/gdbserver/ChangeLog | 53 ++++ gdb/gdbserver/Makefile.in | 6 + gdb/gdbserver/configure.srv | 9 +- gdb/gdbserver/linux-arm-low.c | 1 + gdb/gdbserver/linux-bfin-low.c | 1 + gdb/gdbserver/linux-cris-low.c | 1 + gdb/gdbserver/linux-crisv32-low.c | 1 + gdb/gdbserver/linux-ia64-low.c | 1 + gdb/gdbserver/linux-low.c | 360 ++++++++++++++++----------- gdb/gdbserver/linux-low.h | 6 + gdb/gdbserver/linux-m32r-low.c | 1 + gdb/gdbserver/linux-m68k-low.c | 1 + gdb/gdbserver/linux-mips-low.c | 119 +++++++-- gdb/gdbserver/linux-ppc-low.c | 1 + gdb/gdbserver/linux-s390-low.c | 1 + gdb/gdbserver/linux-sh-low.c | 1 + gdb/gdbserver/linux-sparc-low.c | 1 + gdb/gdbserver/linux-tic6x-low.c | 1 + gdb/gdbserver/linux-x86-low.c | 1 + gdb/gdbserver/linux-xtensa-low.c | 1 + gdb/mips-linux-nat.c | 114 ++++++++- gdb/mips-linux-tdep.c | 14 +- gdb/mips-linux-tdep.h | 4 +- gdb/mips-tdep.c | 269 +++++++++++++------- gdb/mips-tdep.h | 2 + gdb/regformats/mips-dsp-linux.dat | 84 +++++++ gdb/regformats/mips64-dsp-linux.dat | 84 +++++++ gdb/testsuite/ChangeLog | 5 + gdb/testsuite/gdb.xml/tdesc-regs.exp | 2 +- 39 files changed, 1205 insertions(+), 298 deletions(-) create mode 100644 gdb/features/mips-dsp-linux.c create mode 100644 gdb/features/mips-dsp-linux.xml create mode 100644 gdb/features/mips-dsp.xml create mode 100644 gdb/features/mips64-dsp-linux.c create mode 100644 gdb/features/mips64-dsp-linux.xml create mode 100644 gdb/features/mips64-dsp.xml create mode 100644 gdb/regformats/mips-dsp-linux.dat create mode 100644 gdb/regformats/mips64-dsp-linux.dat diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ce3d48e7a12..927c2d708da 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,54 @@ +2012-03-01 Maciej W. Rozycki + Chris Dearman + Maciej W. Rozycki + Joseph Myers + + * 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. + 2012-03-01 Pedro Alves * jit-reader.in [!__cplusplus] diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 18f47bd7871..89ded138f42 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,7 @@ +2012-03-01 Maciej W. Rozycki + + * gdb.texinfo (MIPS Features): Add org.gnu.gdb.mips.dsp. + 2012-03-01 Scott J. Goldman * gdb.texinfo (Commands In Python): Put example python macro in diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6fd615868b7..e187b035cba 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -38636,6 +38636,11 @@ it may be optional in a future version of @value{GDBN}. It should contain registers @samp{f0} through @samp{f31}, @samp{fcsr}, and @samp{fir}. They may be 32-bit or 64-bit depending on the target. +The @samp{org.gnu.gdb.mips.dsp} feature is optional. It should +contain registers @samp{hi1} through @samp{hi3}, @samp{lo1} through +@samp{lo3}, and @samp{dspctl}. The @samp{dspctl} register should +be 32-bit and the rest may be 32-bit or 64-bit depending on the target. + The @samp{org.gnu.gdb.mips.linux} feature is optional. It should contain a single register, @samp{restart}, which is used by the Linux kernel to control restartable syscalls. diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 8eaa03fbecd..eedc33e2776 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -36,7 +36,8 @@ WHICH = arm-with-iwmmxt arm-with-vfpv2 arm-with-vfpv3 arm-with-neon \ 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 \ @@ -60,7 +61,9 @@ i386/i386-mmx-linux-expedite = ebp,esp,eip 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 diff --git a/gdb/features/mips-dsp-linux.c b/gdb/features/mips-dsp-linux.c new file mode 100644 index 00000000000..0644cd6dcef --- /dev/null +++ b/gdb/features/mips-dsp-linux.c @@ -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; +} diff --git a/gdb/features/mips-dsp-linux.xml b/gdb/features/mips-dsp-linux.xml new file mode 100644 index 00000000000..63e3efdb638 --- /dev/null +++ b/gdb/features/mips-dsp-linux.xml @@ -0,0 +1,20 @@ + + + + + + mips + GNU/Linux + + + + + + + + + diff --git a/gdb/features/mips-dsp.xml b/gdb/features/mips-dsp.xml new file mode 100644 index 00000000000..0a421cfc0ae --- /dev/null +++ b/gdb/features/mips-dsp.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/gdb/features/mips64-dsp-linux.c b/gdb/features/mips64-dsp-linux.c new file mode 100644 index 00000000000..e8db243d4ab --- /dev/null +++ b/gdb/features/mips64-dsp-linux.c @@ -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; +} diff --git a/gdb/features/mips64-dsp-linux.xml b/gdb/features/mips64-dsp-linux.xml new file mode 100644 index 00000000000..bce88386a95 --- /dev/null +++ b/gdb/features/mips64-dsp-linux.xml @@ -0,0 +1,19 @@ + + + + + + mips + + + + + + + + + diff --git a/gdb/features/mips64-dsp.xml b/gdb/features/mips64-dsp.xml new file mode 100644 index 00000000000..413e4d334d1 --- /dev/null +++ b/gdb/features/mips64-dsp.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 454e64f05be..82971cd303c 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,56 @@ +2012-03-01 Maciej W. Rozycki + + * linux-low.h (linux_target_ops): Add regset_bitmap member. + * linux-low.c (use_linux_regsets): New macro. + [!HAVE_LINUX_REGSETS] (regsets_fetch_inferior_registers): Likewise. + [!HAVE_LINUX_REGSETS] (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 : 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. + 2012-02-29 Yao Qi Pedro Alves diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index b4d2006ee85..551a8f1cda6 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -544,9 +544,15 @@ reg-cf.c : $(srcdir)/../regformats/reg-cf.dat $(regdat_sh) 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 diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 7c47c863ed1..3358c3377d5 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -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 diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 309654644f9..ff2437d5bf8 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -834,6 +834,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, diff --git a/gdb/gdbserver/linux-bfin-low.c b/gdb/gdbserver/linux-bfin-low.c index 5e5aed28d6b..b6fe58a4c95 100644 --- a/gdb/gdbserver/linux-bfin-low.c +++ b/gdb/gdbserver/linux-bfin-low.c @@ -94,6 +94,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, diff --git a/gdb/gdbserver/linux-cris-low.c b/gdb/gdbserver/linux-cris-low.c index 60188b2ae54..a399789cb71 100644 --- a/gdb/gdbserver/linux-cris-low.c +++ b/gdb/gdbserver/linux-cris-low.c @@ -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, diff --git a/gdb/gdbserver/linux-crisv32-low.c b/gdb/gdbserver/linux-crisv32-low.c index e0e5504bcce..e33372de257 100644 --- a/gdb/gdbserver/linux-crisv32-low.c +++ b/gdb/gdbserver/linux-crisv32-low.c @@ -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, diff --git a/gdb/gdbserver/linux-ia64-low.c b/gdb/gdbserver/linux-ia64-low.c index 1b0ad81a6cf..875319051ad 100644 --- a/gdb/gdbserver/linux-ia64-low.c +++ b/gdb/gdbserver/linux-ia64-low.c @@ -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, }; diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 17d4694411e..bc14ec317f3 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -3781,145 +3781,11 @@ unstop_all_lwps (int unsuspend, struct lwp_info *except) 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) { @@ -4079,34 +3945,224 @@ regsets_store_inferior_registers (struct regcache *regcache) 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); + } } diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h index 3ba004c1ea9..677d2617df4 100644 --- a/gdb/gdbserver/linux-low.h +++ b/gdb/gdbserver/linux-low.h @@ -70,6 +70,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 diff --git a/gdb/gdbserver/linux-m32r-low.c b/gdb/gdbserver/linux-m32r-low.c index 6df1a0a3350..fd70cf2c499 100644 --- a/gdb/gdbserver/linux-m32r-low.c +++ b/gdb/gdbserver/linux-m32r-low.c @@ -91,6 +91,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, diff --git a/gdb/gdbserver/linux-m68k-low.c b/gdb/gdbserver/linux-m68k-low.c index 9843d177711..a640e4c42c2 100644 --- a/gdb/gdbserver/linux-m68k-low.c +++ b/gdb/gdbserver/linux-m68k-low.c @@ -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, diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c index 1fb62377a32..1f584425a14 100644 --- a/gdb/gdbserver/linux-mips-low.c +++ b/gdb/gdbserver/linux-mips-low.c @@ -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 +#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 + +#define mips_dsp_regs \ + DSP_BASE, DSP_BASE + 1, DSP_BASE + 2, DSP_BASE + 3, \ + DSP_BASE + 4, DSP_BASE + 5, \ + DSP_CONTROL + +static int mips_regmap[mips_num_regs] = { + mips_base_regs, + 0 +}; - -1, MMLO, MMHI, BADVADDR, CAUSE, PC, +static int mips_dsp_regmap[mips_dsp_num_regs] = { + mips_base_regs, + mips_dsp_regs, + 0 +}; - 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, +/* DSP registers are not in any regset and can only be accessed + individually. */ - 0 +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, diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index 36d3cb1c578..518a59e2720 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -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, diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c index be8d4419462..8a327952434 100644 --- a/gdb/gdbserver/linux-s390-low.c +++ b/gdb/gdbserver/linux-s390-low.c @@ -461,6 +461,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, diff --git a/gdb/gdbserver/linux-sh-low.c b/gdb/gdbserver/linux-sh-low.c index 4f2ba395a46..e2537d60796 100644 --- a/gdb/gdbserver/linux-sh-low.c +++ b/gdb/gdbserver/linux-sh-low.c @@ -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, diff --git a/gdb/gdbserver/linux-sparc-low.c b/gdb/gdbserver/linux-sparc-low.c index 834f63f4f78..dc9c0ccad88 100644 --- a/gdb/gdbserver/linux-sparc-low.c +++ b/gdb/gdbserver/linux-sparc-low.c @@ -281,6 +281,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, diff --git a/gdb/gdbserver/linux-tic6x-low.c b/gdb/gdbserver/linux-tic6x-low.c index 895d99d2dac..db7c5a4ed62 100644 --- a/gdb/gdbserver/linux-tic6x-low.c +++ b/gdb/gdbserver/linux-tic6x-low.c @@ -321,6 +321,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, diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 365cd52d90a..7fca416b6a2 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -2944,6 +2944,7 @@ struct linux_target_ops the_low_target = NULL, NULL, NULL, + NULL, x86_get_pc, x86_set_pc, x86_breakpoint, diff --git a/gdb/gdbserver/linux-xtensa-low.c b/gdb/gdbserver/linux-xtensa-low.c index 4158395f8bf..bf7f064eded 100644 --- a/gdb/gdbserver/linux-xtensa-low.c +++ b/gdb/gdbserver/linux-xtensa-low.c @@ -180,6 +180,7 @@ struct linux_target_ops the_low_target = { init_registers_xtensa, 0, 0, + NULL, 0, 0, xtensa_get_pc, diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c index dac5eca4263..af472df0441 100644 --- a/gdb/mips-linux-nat.c +++ b/gdb/mips-linux-nat.c @@ -36,7 +36,9 @@ #include #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 @@ -94,6 +96,12 @@ mips_linux_register_addr (struct gdbarch *gdbarch, int regno, int store) 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 @@ -129,6 +137,12 @@ mips64_linux_register_addr (struct gdbarch *gdbarch, int regno, int store) 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 @@ -201,10 +215,13 @@ fill_fpregset (const struct regcache *regcache, 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 @@ -217,11 +234,23 @@ mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno) 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; @@ -257,17 +286,30 @@ mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno) 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 @@ -280,11 +322,23 @@ mips64_linux_regsets_store_registers (const struct regcache *regcache, 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; @@ -311,6 +365,17 @@ mips64_linux_regsets_store_registers (const struct regcache *regcache, (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 @@ -322,7 +387,7 @@ mips64_linux_fetch_registers (struct target_ops *ops, { /* 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. */ @@ -339,7 +404,7 @@ mips64_linux_store_registers (struct target_ops *ops, { /* 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. */ @@ -362,12 +427,37 @@ mips_linux_register_u_offset (struct gdbarch *gdbarch, int regno, int store_p) 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 @@ -1088,5 +1178,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 (); } diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 6b16995ce30..dea0bf7b4c6 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -119,13 +119,8 @@ mips_supply_gregset (struct regcache *regcache, 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 @@ -374,13 +369,8 @@ mips64_supply_gregset (struct regcache *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 diff --git a/gdb/mips-linux-tdep.h b/gdb/mips-linux-tdep.h index fcf7983154a..d9ee88286f8 100644 --- a/gdb/mips-linux-tdep.h +++ b/gdb/mips-linux-tdep.h @@ -36,6 +36,8 @@ typedef mips_elf_fpreg_t mips_elf_fpregset_t[ELF_NFPREG]; #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 regcache *, 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. */ diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 67ead3c0d2d..3e09d5c152f 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -390,9 +390,7 @@ static const char *mips_generic_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "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. */ @@ -418,7 +416,7 @@ static const char *mips_tx39_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", - "", "", "config", "cache", "debug", "depc", "epc", "" + "", "", "config", "cache", "debug", "depc", "epc", }; /* Names of IRIX registers. */ @@ -430,6 +428,16 @@ static const char *mips_irix_reg_names[NUM_MIPS_PROCESSOR_REGS] = { "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 * @@ -484,7 +492,9 @@ mips_register_name (struct gdbarch *gdbarch, int regno) 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__, @@ -854,11 +864,17 @@ mips_register_type (struct gdbarch *gdbarch, int regnum) } 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; @@ -897,37 +913,50 @@ mips_pseudo_register_type (struct gdbarch *gdbarch, int regnum) 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; } @@ -5715,6 +5744,8 @@ mips_stab_reg_to_regnum (struct gdbarch *gdbarch, int num) 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? */ @@ -5738,6 +5769,8 @@ mips_dwarf_dwarf2_ecoff_reg_to_regnum (struct gdbarch *gdbarch, int num) 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? */ @@ -5877,6 +5910,63 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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)) @@ -5911,11 +6001,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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) { @@ -5933,12 +6023,11 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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) { @@ -5959,13 +6048,15 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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) { @@ -5973,8 +6064,45 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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. */ @@ -6223,66 +6351,19 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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) { diff --git a/gdb/mips-tdep.h b/gdb/mips-tdep.h index d91a1d2a21c..b264257a14b 100644 --- a/gdb/mips-tdep.h +++ b/gdb/mips-tdep.h @@ -53,6 +53,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); diff --git a/gdb/regformats/mips-dsp-linux.dat b/gdb/regformats/mips-dsp-linux.dat new file mode 100644 index 00000000000..34706e9af0b --- /dev/null +++ b/gdb/regformats/mips-dsp-linux.dat @@ -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 diff --git a/gdb/regformats/mips64-dsp-linux.dat b/gdb/regformats/mips64-dsp-linux.dat new file mode 100644 index 00000000000..ba93eb22829 --- /dev/null +++ b/gdb/regformats/mips64-dsp-linux.dat @@ -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 diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 98c76750087..8c0a991c49b 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-03-01 Maciej W. Rozycki + + * gdb.xml/tdesc-regs.exp: Add "mips-dsp.xml" to the list of MIPS + core registers. + 2012-03-01 Maciej W. Rozycki Maciej W. Rozycki Daniel Jacobowitz diff --git a/gdb/testsuite/gdb.xml/tdesc-regs.exp b/gdb/testsuite/gdb.xml/tdesc-regs.exp index 35d85417b4f..9a89d7ee77a 100644 --- a/gdb/testsuite/gdb.xml/tdesc-regs.exp +++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp @@ -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/" -- 2.30.2