#include "inferior.h"
#include "mips-tdep.h"
#include "target.h"
+#include "regcache.h"
#include "linux-nat.h"
#include "mips-linux-tdep.h"
-#include "gdbcore.h"
#include "gdb_proc_service.h"
+#include "gregset.h"
#include <sys/ptrace.h>
/* Saved function pointers to fetch and store a single register using
PTRACE_PEEKUSER and PTRACE_POKEUSER. */
-void (*super_fetch_registers) (int);
-void (*super_store_registers) (int);
+void (*super_fetch_registers) (struct regcache *, int);
+void (*super_store_registers) (struct regcache *, int);
/* Pseudo registers can not be read. ptrace does not provide a way to
read (or set) MIPS_PS_REGNUM, and there's no point in reading or
return 1;
}
+/* Map gdb internal register number to ptrace ``address''.
+ These ``addresses'' are normally defined in <asm/ptrace.h>. */
+
+static CORE_ADDR
+mips_linux_register_addr (int regno)
+{
+ int regaddr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error (_("Bogon register number %d."), regno);
+
+ if (regno < 32)
+ regaddr = regno;
+ else if ((regno >= mips_regnum (current_gdbarch)->fp0)
+ && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
+ regaddr = FPR_BASE + (regno - mips_regnum (current_gdbarch)->fp0);
+ else if (regno == mips_regnum (current_gdbarch)->pc)
+ regaddr = PC;
+ else if (regno == mips_regnum (current_gdbarch)->cause)
+ regaddr = CAUSE;
+ else if (regno == mips_regnum (current_gdbarch)->badvaddr)
+ regaddr = BADVADDR;
+ else if (regno == mips_regnum (current_gdbarch)->lo)
+ regaddr = MMLO;
+ else if (regno == mips_regnum (current_gdbarch)->hi)
+ regaddr = MMHI;
+ else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+ regaddr = FPC_CSR;
+ else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
+ regaddr = FPC_EIR;
+ else
+ error (_("Unknowable register number %d."), regno);
+
+ return regaddr;
+}
+
+static CORE_ADDR
+mips64_linux_register_addr (int regno)
+{
+ int regaddr;
+
+ if (regno < 0 || regno >= NUM_REGS)
+ error (_("Bogon register number %d."), regno);
+
+ if (regno < 32)
+ regaddr = regno;
+ else if ((regno >= mips_regnum (current_gdbarch)->fp0)
+ && (regno < mips_regnum (current_gdbarch)->fp0 + 32))
+ regaddr = MIPS64_FPR_BASE + (regno - FP0_REGNUM);
+ else if (regno == mips_regnum (current_gdbarch)->pc)
+ regaddr = MIPS64_PC;
+ else if (regno == mips_regnum (current_gdbarch)->cause)
+ regaddr = MIPS64_CAUSE;
+ else if (regno == mips_regnum (current_gdbarch)->badvaddr)
+ regaddr = MIPS64_BADVADDR;
+ else if (regno == mips_regnum (current_gdbarch)->lo)
+ regaddr = MIPS64_MMLO;
+ else if (regno == mips_regnum (current_gdbarch)->hi)
+ regaddr = MIPS64_MMHI;
+ else if (regno == mips_regnum (current_gdbarch)->fp_control_status)
+ regaddr = MIPS64_FPC_CSR;
+ else if (regno == mips_regnum (current_gdbarch)->fp_implementation_revision)
+ regaddr = MIPS64_FPC_EIR;
+ else
+ error (_("Unknowable register number %d."), regno);
+
+ return regaddr;
+}
+
/* Fetch the thread-local storage pointer for libthread_db. */
ps_err_e
return PS_OK;
}
+/* Wrapper functions. These are only used by libthread_db. */
+
+void
+supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
+{
+ if (mips_isa_regsize (current_gdbarch) == 4)
+ mips_supply_gregset (regcache, (const mips_elf_gregset_t *) gregsetp);
+ else
+ mips64_supply_gregset (regcache, (const mips64_elf_gregset_t *) gregsetp);
+}
+
+void
+fill_gregset (const struct regcache *regcache,
+ gdb_gregset_t *gregsetp, int regno)
+{
+ if (mips_isa_regsize (current_gdbarch) == 4)
+ mips_fill_gregset (regcache, (mips_elf_gregset_t *) gregsetp, regno);
+ else
+ mips64_fill_gregset (regcache, (mips64_elf_gregset_t *) gregsetp, regno);
+}
+
+void
+supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
+{
+ if (mips_isa_regsize (current_gdbarch) == 4)
+ mips_supply_fpregset (regcache, (const mips_elf_fpregset_t *) fpregsetp);
+ else
+ mips64_supply_fpregset (regcache, (const mips64_elf_fpregset_t *) fpregsetp);
+}
+
+void
+fill_fpregset (const struct regcache *regcache,
+ gdb_fpregset_t *fpregsetp, int regno)
+{
+ if (mips_isa_regsize (current_gdbarch) == 4)
+ mips_fill_fpregset (regcache, (mips_elf_fpregset_t *) fpregsetp, regno);
+ else
+ mips64_fill_fpregset (regcache, (mips64_elf_fpregset_t *) fpregsetp, regno);
+}
+
+
/* Fetch REGNO (or all registers if REGNO == -1) from the target
using PTRACE_GETREGS et al. */
static void
-mips64_linux_regsets_fetch_registers (int regno)
+mips64_linux_regsets_fetch_registers (struct regcache *regcache, int regno)
{
int is_fp;
int tid;
perror_with_name (_("Couldn't get registers"));
}
- mips64_supply_gregset (®s);
+ mips64_supply_gregset (regcache,
+ (const mips64_elf_gregset_t *) ®s);
}
if (regno == -1 || is_fp)
perror_with_name (_("Couldn't get FP registers"));
}
- mips64_supply_fpregset (&fp_regs);
+ mips64_supply_fpregset (regcache,
+ (const mips64_elf_fpregset_t *) &fp_regs);
}
}
using PTRACE_SETREGS et al. */
static void
-mips64_linux_regsets_store_registers (int regno)
+mips64_linux_regsets_store_registers (const struct regcache *regcache, int regno)
{
int is_fp;
int tid;
if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1)
perror_with_name (_("Couldn't get registers"));
- mips64_fill_gregset (®s, regno);
+ mips64_fill_gregset (regcache, ®s, regno);
if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) ®s) == -1)
perror_with_name (_("Couldn't set registers"));
(PTRACE_TYPE_ARG3) &fp_regs) == -1)
perror_with_name (_("Couldn't get FP registers"));
- mips64_fill_fpregset (&fp_regs, regno);
+ mips64_fill_fpregset (regcache, &fp_regs, regno);
if (ptrace (PTRACE_SETFPREGS, tid, 0L,
(PTRACE_TYPE_ARG3) &fp_regs) == -1)
using any working method. */
static void
-mips64_linux_fetch_registers (int regnum)
+mips64_linux_fetch_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
- mips64_linux_regsets_fetch_registers (regnum);
+ mips64_linux_regsets_fetch_registers (regcache, regnum);
/* If we know, or just found out, that PTRACE_GETREGS does not work, fall
back to PTRACE_PEEKUSER. */
if (!have_ptrace_regsets)
- super_fetch_registers (regnum);
+ super_fetch_registers (regcache, regnum);
}
/* Store REGNO (or all registers if REGNO == -1) to the target
using any working method. */
static void
-mips64_linux_store_registers (int regnum)
+mips64_linux_store_registers (struct regcache *regcache, int regnum)
{
/* Unless we already know that PTRACE_GETREGS does not work, try it. */
if (have_ptrace_regsets)
- mips64_linux_regsets_store_registers (regnum);
+ mips64_linux_regsets_store_registers (regcache, regnum);
/* If we know, or just found out, that PTRACE_GETREGS does not work, fall
back to PTRACE_PEEKUSER. */
if (!have_ptrace_regsets)
- super_store_registers (regnum);
+ super_store_registers (regcache, regnum);
}
/* Return the address in the core dump or inferior of register
static CORE_ADDR
mips_linux_register_u_offset (int regno)
{
- /* FIXME drow/2005-09-04: The hardcoded use of register_addr should go
- away. This requires disentangling the various definitions of it
- (particularly alpha-nat.c's). */
- return register_addr (regno, 0);
+ if (mips_abi_regsize (current_gdbarch) == 8)
+ return mips64_linux_register_addr (regno);
+ else
+ return mips_linux_register_addr (regno);
}
void _initialize_mips_linux_nat (void);