aboutsummaryrefslogtreecommitdiff
path: root/gdb/mips-linux-nat.c
diff options
context:
space:
mode:
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 dac5eca..af472df 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 ();
}