Index: gdb/mips-linux-nat.c |
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c |
index edacbb78a2860f1e4aa5ea58b06a909532d40bfe..b9f7f1dc638fb8c57329d21e7927053312cf660c 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 (_("Couldn't check DSP support")); |
+ 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 |
@@ -885,14 +975,14 @@ write_watchpoint_regs (void) |
register values for the new thread. */ |
static void |
-mips_linux_new_thread (ptid_t ptid) |
+mips_linux_new_thread (struct lwp_info *lp) |
{ |
int tid; |
if (!mips_linux_read_watch_registers (0)) |
return; |
- tid = ptid_get_lwp (ptid); |
+ tid = ptid_get_lwp (lp->ptid); |
if (ptrace (PTRACE_SET_WATCH_REGS, tid, &watch_mirror) == -1) |
perror_with_name (_("Couldn't write debug register")); |
} |
@@ -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 (); |
} |