* target.h (struct regcache): Add forward declaration.
[deliverable/binutils-gdb.git] / gdb / mips-linux-nat.c
index d5a12025690a1adc6d86debca8ee183fb6d8c0f3..a511689f1cea21cc24a2b804c333ddd528cdbb55 100644 (file)
 #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>
 
@@ -43,8 +44,8 @@ static int have_ptrace_regsets = 1;
 /* 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
@@ -87,6 +88,75 @@ mips_linux_cannot_store_register (int regno)
     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
@@ -104,11 +174,52 @@ ps_get_thread_area (const struct ps_prochandle *ph,
   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;
@@ -141,7 +252,8 @@ mips64_linux_regsets_fetch_registers (int regno)
          perror_with_name (_("Couldn't get registers"));
        }
 
-      mips64_supply_gregset (&regs);
+      mips64_supply_gregset (regcache,
+                            (const mips64_elf_gregset_t *) &regs);
     }
 
   if (regno == -1 || is_fp)
@@ -159,7 +271,8 @@ mips64_linux_regsets_fetch_registers (int regno)
          perror_with_name (_("Couldn't get FP registers"));
        }
 
-      mips64_supply_fpregset (&fp_regs);
+      mips64_supply_fpregset (regcache,
+                             (const mips64_elf_fpregset_t *) &fp_regs);
     }
 }
 
@@ -167,7 +280,7 @@ mips64_linux_regsets_fetch_registers (int regno)
    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;
@@ -193,7 +306,7 @@ mips64_linux_regsets_store_registers (int regno)
       if (ptrace (PTRACE_GETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
        perror_with_name (_("Couldn't get registers"));
 
-      mips64_fill_gregset (&regs, regno);
+      mips64_fill_gregset (regcache, &regs, regno);
 
       if (ptrace (PTRACE_SETREGS, tid, 0L, (PTRACE_TYPE_ARG3) &regs) == -1)
        perror_with_name (_("Couldn't set registers"));
@@ -207,7 +320,7 @@ mips64_linux_regsets_store_registers (int regno)
                  (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)
@@ -219,32 +332,32 @@ mips64_linux_regsets_store_registers (int regno)
    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
@@ -253,10 +366,10 @@ mips64_linux_store_registers (int regnum)
 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);
This page took 0.028348 seconds and 4 git commands to generate.