diff options
Diffstat (limited to 'gdb/mips-linux-nat.c')
-rw-r--r-- | gdb/mips-linux-nat.c | 114 |
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 (); } |