summaryrefslogtreecommitdiff
path: root/gdb/mips-linux-nat.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2012-03-01 22:19:40 +0000
committerMaciej W. Rozycki <macro@linux-mips.org>2012-03-01 22:19:40 +0000
commitdcf8a078f8979a32f4bd1366644508e5ce71e523 (patch)
treeaca4ee0c6f21844c56177dc4d726051d21a928c5 /gdb/mips-linux-nat.c
parent80ac8d5dbb66adfc9ef1cf33bc324c63b3cc03af (diff)
downloadgdb-dcf8a078f8979a32f4bd1366644508e5ce71e523.tar.gz
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 <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. gdb/testsuite/ * gdb.xml/tdesc-regs.exp: Add "mips-dsp.xml" to the list of MIPS core registers.
Diffstat (limited to 'gdb/mips-linux-nat.c')
-rw-r--r--gdb/mips-linux-nat.c114
1 files changed, 103 insertions, 11 deletions
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 <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
@@ -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 ();
}