This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Sparc/Linux patch 4



This moves all of the ptrace and core file handling into
sparc-linux-nat.c  It fully handles 64-bit and 32-bit
Sparc, in both the core files and ptrace'd inferiors.

It also makes is so that Linux LWP values are handled properly
although thread support on this platform still needs some help
yet... don't worry that will be resolved soon :-)

With all of today's Sparc/Linux patches applied we are now down to
about 91 testsuite failures (we started with ~148 using gcc-3.1).  I
should be able to kill another 5 or so with my next Sparc/Linux
patch (which adds signal frame and ld.so resolver skip support).

2002-04-19  David S. Miller  <davem@redhat.com>

	* sparc-linux-nat.c (gdbcore.h, gdb_string.h, target.h): Include.
	(elf64_greg_t, elf64_gregset_t, elf32_greg_t, elf32_gregset_t,
	elf64_fpregset_t, elf32_fpregset_t, pt64_regs, pt32_regs,
	pt64_fpregs, pt32_fpregs): New typedefs.
	(UREG_G[1-7], UREG_O[0-7]): Define.
	(tstate_to_ccr, ccr_to_tstate, tstate_to_psr, psr_to_tstate_icc):
	New inferior register helpers.
	(supply_gregset, fill_gregset, supply_fpregset, fill_fpregset):
	Make sparc64 aware.
	(fetch_core_registers, fetch_inferior_registers,
	store_all_registers, store_inferior_registers): New functions
	implementing ptrace and core file support on Linux/Sparc.
	(sparc_linux_core_fns): New core_fns vector.
	(_initialize_core_sparc_linux): New.
	* config/sparc/linux.mh (NATDEPFILES): Delete sparc-nat.o

--- ./config/sparc/linux.mh.~1~	Wed Feb 13 21:48:40 2002
+++ ./config/sparc/linux.mh	Fri Apr 19 22:17:05 2002
@@ -3,9 +3,9 @@
 XM_FILE= xm-linux.h
 
 NAT_FILE= nm-linux.h
-NATDEPFILES= fork-child.o infptrace.o inftarg.o corelow.o sparc-nat.o \
-	proc-service.o thread-db.o lin-lwp.o sparc-linux-nat.o \
-	linux-proc.o gcore.o 
+NATDEPFILES= infptrace.o inftarg.o fork-child.o corelow.o linux-proc.o \
+	sparc-linux-nat.o \
+	proc-service.o thread-db.o lin-lwp.o linux-proc.o gcore.o
 
 # The dynamically loaded libthread_db needs access to symbols in the
 # gdb executable.
--- ./sparc-linux-nat.c.~1~	Fri Apr 19 15:51:54 2002
+++ ./sparc-linux-nat.c	Fri Apr 19 22:18:41 2002
@@ -21,7 +21,10 @@
 
 #include "defs.h"
 #include "regcache.h"
+#include "gdbcore.h"
+#include "gdb_string.h"
 #include "inferior.h"
+#include "target.h"
    
 #include <sys/procfs.h>
 #include <sys/ptrace.h>
@@ -31,78 +34,868 @@
 /* Prototypes for supply_gregset etc.  */
 #include "gregset.h"
 
+typedef unsigned long long elf64_greg_t;
+typedef elf64_greg_t elf64_gregset_t[36];
+typedef unsigned int elf32_greg_t;
+typedef elf32_greg_t elf32_gregset_t[38];
+
+static elf64_greg_t
+tstate_to_ccr(elf64_greg_t tstate)
+{
+	return (tstate >> 32) & 0xff;
+}
+
+static elf64_greg_t
+ccr_to_tstate(elf64_greg_t ccr)
+{
+	return (ccr & 0xffULL) << 32;
+}
+
 void
-supply_gregset (elf_gregset_t *gregsetp)
+supply_gregset (gdb_gregset_t *__gregsetp)
 {
-  elf_greg_t *regp = (elf_greg_t *) gregsetp;
-  int i;
+  if (GDB_TARGET_IS_SPARC64)
+    {
+      elf64_greg_t *regp = (elf64_greg_t *) __gregsetp;
+      elf64_greg_t ccr;
+      int i;
+
+      for (i = G0_REGNUM; i <= I7_REGNUM; i++)
+	supply_register (i, (char *) (regp + (i - G0_REGNUM)));
+
+      ccr = tstate_to_ccr(regp[32]);
+      supply_register (CCR_REGNUM, (char *) &ccr);
+      supply_register (PC_REGNUM, (char *) (regp + 33));
+      supply_register (NPC_REGNUM, (char *) (regp + 34));
+      supply_register (Y_REGNUM, (char *) (regp + 35));
+
+      /* ??? We could be clever and derive these from other sources
+	 ??? such as tstate, but that causes testsuite failures
+	 ??? because things like sparc_pop_frame would need to do such
+	 ??? derivations too.  */
+      for (i = FPRS_REGNUM; i <= FCC3_REGNUM; i++)
+	supply_register (i, NULL);
+    }
+  else
+    {
+      elf32_greg_t *regp = (elf32_greg_t *) __gregsetp;
+      int i;
+
+      for (i = G0_REGNUM; i <= I7_REGNUM; i++)
+	supply_register (i, (char *) (regp + (i - G0_REGNUM)));
+
+      supply_register (PS_REGNUM, (char *) (regp + 32));
+
+      supply_register (PC_REGNUM, (char *) (regp + 33));
+      supply_register (NPC_REGNUM, (char *) (regp + 34));
+      supply_register (Y_REGNUM, (char *) (regp + 35));
+
+      /* Fill inaccessible registers with zero.  */
+      supply_register (WIM_REGNUM, NULL);
+      supply_register (TBR_REGNUM, NULL);
+      supply_register (CPS_REGNUM, NULL);
+    }
+}
 
-  for (i = G0_REGNUM; i <= I7_REGNUM; i++)
-    supply_register (i, (char *) (regp + (i - G0_REGNUM)));
+void
+fill_gregset (gdb_gregset_t *__gregsetp, int regno)
+{
+  int i;
 
-  supply_register (PS_REGNUM, (char *) (regp + 32));
+  if (GDB_TARGET_IS_SPARC64)
+    {
+      elf64_greg_t *regp = (elf64_greg_t *) __gregsetp;
+      elf64_greg_t ccr;
+
+      for (i = G0_REGNUM; i <= I7_REGNUM; i++)
+	if (regno == -1 || regno == i)
+	  regcache_collect (i, regp + (i - G0_REGNUM));
+
+      if (regno == -1 || regno == CCR_REGNUM)
+	{
+	  regcache_collect (CCR_REGNUM, &ccr);
+	  regp[32] = ccr_to_tstate(ccr);
+	}
+
+      if (regno == -1 || regno == PC_REGNUM)
+	regcache_collect (PC_REGNUM, regp + 33);
+      if (regno == -1 || regno == NPC_REGNUM)
+	regcache_collect (NPC_REGNUM, regp + 34);
+      if (regno == -1 || regno == Y_REGNUM)
+	regcache_collect (Y_REGNUM, regp + 35);
+    }
+  else
+    {
+      elf32_greg_t *regp = (elf32_greg_t *) __gregsetp;
+
+      for (i = G0_REGNUM; i <= I7_REGNUM; i++)
+	if (regno == -1 || regno == i)
+	  regcache_collect (i, regp + (i - G0_REGNUM));
+
+      if (regno == -1 || regno == PS_REGNUM)
+	regcache_collect (PS_REGNUM, regp + 32);
+
+      if (regno == -1 || regno == PC_REGNUM)
+	regcache_collect (PC_REGNUM, regp + 33);
+      if (regno == -1 || regno == NPC_REGNUM)
+	regcache_collect (NPC_REGNUM, regp + 34);
+      if (regno == -1 || regno == Y_REGNUM)
+	regcache_collect (Y_REGNUM, regp + 35);
+    }
+}
 
-  supply_register (PC_REGNUM, (char *) (regp + 33));
-  supply_register (NPC_REGNUM, (char *) (regp + 34));
-  supply_register (Y_REGNUM, (char *) (regp + 35));
+typedef struct {
+  unsigned long long pr_regs[32];
+  unsigned long long pr_fsr;
+  unsigned long long pr_gsr;
+  unsigned long long pr_fprs;
+} elf64_fpregset_t;
+
+typedef struct {
+  unsigned int pr_regs[32];
+  unsigned int __unused;
+  unsigned int pr_fsr;
+  unsigned int pr_qcnt;
+  unsigned int pr_q_entrysize;
+  unsigned int pr_en;
+  unsigned int pr_q[64];
+} elf32_fpregset_t;
 
-  supply_register (WIM_REGNUM, (char *) (regp + 36));
-  supply_register (TBR_REGNUM, (char *) (regp + 37));
+void
+supply_fpregset (gdb_fpregset_t *__fpregsetp)
+{
+  int i;
 
-  /* Fill inaccessible registers with zero.  */
-  supply_register (CPS_REGNUM, NULL);
+  if (GDB_TARGET_IS_SPARC64)
+    {
+      elf64_fpregset_t *regs = (elf64_fpregset_t *) __fpregsetp;
+      unsigned int *fp_single = (unsigned int *) &regs->pr_regs[0];
+      unsigned long long *fp_double = (unsigned long long *) &fp_single[32];
+
+      for (i = 0; i < 32; i++)
+	supply_register (i + FP0_REGNUM, (char *) &fp_single[i]);
+      for (i = 0; i < 16; i++)
+	supply_register (i + FP0_REGNUM + 32, (char *) &fp_double[i]);
+
+      /* XXX No GSR_REGNUM */
+      supply_register (FPRS_REGNUM, (char *) &regs->pr_fprs);
+      supply_register (FSR_REGNUM, (char *) &regs->pr_fsr);
+    }
+  else
+    {
+      elf32_fpregset_t *regs = (elf32_fpregset_t *) __fpregsetp;
+
+      for (i = FP0_REGNUM; i < FP0_REGNUM + 32; i++)
+	supply_register (i, (char *) &regs->pr_regs[i - FP0_REGNUM]);
+      supply_register (FPS_REGNUM, (char *) &regs->pr_fsr);
+    }
 }
 
 void
-fill_gregset (elf_gregset_t *gregsetp, int regno)
+fill_fpregset (gdb_fpregset_t *__fpregsetp, int regno)
 {
-  elf_greg_t *regp = (elf_greg_t *) gregsetp;
   int i;
 
-  for (i = G0_REGNUM; i <= I7_REGNUM; i++)
-    if (regno == -1 || regno == i)
-      regcache_collect (i, regp + (i - G0_REGNUM));
+  if (GDB_TARGET_IS_SPARC64)
+    {
+      elf64_fpregset_t *regs = (elf64_fpregset_t *) __fpregsetp;
+      unsigned int *fp_single = (unsigned int *) &regs->pr_regs[0];
+      unsigned long long *fp_double = (unsigned long long *) &fp_single[32];
+
+      for (i = FP0_REGNUM; i < FP0_REGNUM + 32; i++)
+	if (regno == -1 || regno == i)
+	  regcache_collect (i, (char *) &fp_single[i - FP0_REGNUM]);
+      for (i = FP0_REGNUM + 32; i < FP0_REGNUM + 32 + 16; i++)
+	if (regno == -1 || regno == i)
+	  regcache_collect (i, (char *) &fp_double[i - (FP0_REGNUM + 32)]);
+
+      /* XXX No GSR_REGNUM */
+
+      if (regno == -1 || regno == FPRS_REGNUM)
+	regcache_collect (FPRS_REGNUM, &regs->pr_fprs);
+      if (regno == -1 || regno == FSR_REGNUM)
+	regcache_collect (FSR_REGNUM, &regs->pr_fsr);
+    }
+  else
+    {
+      elf32_fpregset_t *regs = (elf32_fpregset_t *) __fpregsetp;
+
+      for (i = FP0_REGNUM; i < FP0_REGNUM + 32; i++)
+	if (regno == -1 || regno == i)
+	  regcache_collect (i, &regs->pr_regs[i - FP0_REGNUM]);
+
+      if (regno == -1 || regno == FPS_REGNUM)
+	regcache_collect (FPS_REGNUM, &regs->pr_fsr);
+    }
+}
 
-  if (regno == -1 || regno == PS_REGNUM)
-    regcache_collect (PS_REGNUM, regp + 32);
+/*  Use a local version of this function to get the correct types for
+    regsets, until multi-arch core support is ready.  */
 
-  if (regno == -1 || regno == PC_REGNUM)
-    regcache_collect (PC_REGNUM, regp + 33);
-  if (regno == -1 || regno == NPC_REGNUM)
-    regcache_collect (NPC_REGNUM, regp + 34);
-  if (regno == -1 || regno == Y_REGNUM)
-    regcache_collect (Y_REGNUM, regp + 35);
+static void
+fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
+		      int which, CORE_ADDR reg_addr)
+{
 
-  if (regno == -1 || regno == WIM_REGNUM)
-    regcache_collect (WIM_REGNUM, regp + 36);
-  if (regno == -1 || regno == TBR_REGNUM)
-    regcache_collect (TBR_REGNUM, regp + 37);
+  if (which == 0)
+    {
+      if (GDB_TARGET_IS_SPARC64)
+	{
+	  elf64_gregset_t gregset;
+
+	  memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+	  supply_gregset ((gdb_gregset_t *) &gregset);
+	}
+      else
+	{
+	  elf32_gregset_t gregset;
+
+	  memcpy ((char *) &gregset, core_reg_sect, sizeof (gregset));
+	  supply_gregset ((gdb_gregset_t *) &gregset);
+	}
+    }
+  else if (which == 2)
+    {
+      if (GDB_TARGET_IS_SPARC64)
+	{
+	  elf64_fpregset_t fpregset;
+
+	  memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+	  supply_fpregset ((gdb_fpregset_t *) &fpregset);
+	}
+      else
+	{
+	  elf32_fpregset_t fpregset;
+
+	  memcpy ((char *) &fpregset, core_reg_sect, sizeof (fpregset));
+	  supply_fpregset ((gdb_fpregset_t *) &fpregset);
+	}
+    }
 }
 
-void
-supply_fpregset (elf_fpregset_t *fpregsetp)
+/* Size of a general (integer) register: */
+extern int sparc_intreg_size (void);
+#define SPARC_INTREG_SIZE (sparc_intreg_size ())
+
+static elf32_greg_t
+tstate_to_psr(elf64_greg_t tstate)
 {
-  int i;
+  return ((tstate & 0x1f) |
+	  0x80 |
+	  ((tstate & (elf64_greg_t)0x0f00000000) >> 12) |
+	  ((tstate & (elf64_greg_t)0xf000000000) >> 20) |
+	  0xff000000);
+}
 
-  for (i = FP0_REGNUM; i < FP0_REGNUM + 32; i++)
-    supply_register (i, (char *) &fpregsetp->pr_fr.pr_regs[i - FP0_REGNUM]);
+static elf64_greg_t
+psr_to_tstate_icc(elf32_greg_t psr)
+{
+  elf64_greg_t tstate = ((elf64_greg_t)(psr & 0x00f00000)) << 12;
+
+  if ((psr & (0xffffffff)) == 0xff000000)
+    tstate |= ((elf64_greg_t)(psr & 0x000f0000)) << 20;
 
-  supply_register (FPS_REGNUM, (char *) &fpregsetp->pr_fsr);
+  return tstate;
 }
 
+struct pt64_regs
+{
+  elf64_greg_t	u_regs[16];
+  elf64_greg_t	tstate;
+  elf64_greg_t	tpc;
+  elf64_greg_t	tnpc;
+  elf32_greg_t	y;
+  elf32_greg_t	fprs;
+};
+
+struct pt32_regs
+{
+  elf32_greg_t	psr;
+  elf32_greg_t	pc;
+  elf32_greg_t	npc;
+  elf32_greg_t	y;
+  elf32_greg_t	u_regs[16];
+};
+
+#define UREG_G1        0
+#define UREG_G2        1
+#define UREG_G3        2
+#define UREG_G4        3
+#define UREG_G5        4
+#define UREG_G6        5
+#define UREG_G7        6
+#define UREG_O0        7
+#define UREG_O1        8
+#define UREG_O2        9
+#define UREG_O3        10
+#define UREG_O4        11
+#define UREG_O5        12
+#define UREG_O6        13
+#define UREG_O7        14
+
+struct pt64_fpregs
+{
+  elf32_greg_t	regs[64];
+  elf64_greg_t	fsr;
+};
+
+struct pt32_fpregs
+{
+  elf32_greg_t	regs[32];
+  elf32_greg_t	fsr;
+  elf32_greg_t	flags;
+  elf32_greg_t	extra;
+  elf32_greg_t	fpqd;
+  struct fpu_fq {
+    elf32_greg_t	insnaddr;
+    elf32_greg_t	insn;
+  } fpq[16];
+};
+
 void
-fill_fpregset (elf_fpregset_t *fpregsetp, int regno)
+fetch_inferior_registers (int regno)
+{
+  int intreg_size = SPARC_INTREG_SIZE;
+  int proc_id, i;
+  char *buf;
+
+  /* GNU/Linux LWP ID's are process ID's.  */
+  if ((proc_id = TIDGET (inferior_ptid)) == 0)
+    proc_id = PIDGET (inferior_ptid);		/* Not a threaded program.  */
+
+  if (sizeof (void *) == 8)
+    {
+      union {
+	struct pt64_regs regs;
+	struct pt64_fpregs fpregs;
+      } u;
+      int offset = (intreg_size == 4) ? 4 : 0;
+
+      if (regno <= O7_REGNUM
+	  || (regno >= Y_REGNUM && regno != FSR_REGNUM)
+	  || (!register_cached (SP_REGNUM) && regno <= I7_REGNUM))
+	{
+	  if (0 != ptrace (PTRACE_GETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_getregs");
+
+	  supply_register (G0_REGNUM, NULL);
+	  if (regno == -1)
+	    {
+	      for (i = G1_REGNUM; i < G1_REGNUM + 15; i++)
+		{
+		  char *regptr = (char *)&u.regs.u_regs[i - G1_REGNUM + UREG_G1];
+
+		  regptr += offset;
+		  supply_register (i, regptr);
+		}
+	    }
+	  else if (regno >= G1_REGNUM && regno < G1_REGNUM + 15)
+	    {
+	      char *regptr = (char *)&u.regs.u_regs[regno - G1_REGNUM + UREG_G1];
+
+	      regptr += offset;
+	      supply_register (regno, regptr);
+	    }
+	  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+	    {
+	      char *regptr = (char *)&u.regs.u_regs[SP_REGNUM - G1_REGNUM + UREG_G1];
+
+	      regptr += offset;
+	      supply_register (SP_REGNUM, regptr);
+	    }
+
+	  if (regno == -1 ||
+	      (! GDB_TARGET_IS_SPARC64 && regno == PS_REGNUM) ||
+	      (GDB_TARGET_IS_SPARC64 && regno == CCR_REGNUM))
+	    {
+	      if (! GDB_TARGET_IS_SPARC64)
+		{
+		  elf32_greg_t psr_convert = tstate_to_psr(u.regs.tstate);
+		  supply_register (PS_REGNUM, (char *) &psr_convert);
+		}
+	      else
+		{
+		  elf64_greg_t ccr_convert = tstate_to_ccr(u.regs.tstate);
+		  supply_register (CCR_REGNUM, (char *) &ccr_convert);
+		}
+	    }
+	  if (regno == -1 || regno == PC_REGNUM)
+	    supply_register (PC_REGNUM, ((char *) &u.regs.tpc) + offset);
+	  if (regno == -1 || regno == NPC_REGNUM)
+	    supply_register (NPC_REGNUM, ((char *) &u.regs.tnpc) + offset);
+	  if (regno == -1 || regno == Y_REGNUM)
+	    supply_register (Y_REGNUM, ((char *) &u.regs.y) + offset);
+
+	  if (regno == -1)
+	    {
+	      if (! GDB_TARGET_IS_SPARC64)
+		{
+		  supply_register (WIM_REGNUM, NULL);
+		  supply_register (TBR_REGNUM, NULL);
+		  supply_register (CPS_REGNUM, NULL);
+		}
+	      else
+		{
+		  for (i = FPRS_REGNUM; i <= FCC3_REGNUM; i++)
+		    supply_register (i, NULL);
+		}
+	    }
+	}
+
+      if (regno == -1 ||
+	  (! GDB_TARGET_IS_SPARC64 && regno == FPS_REGNUM) ||
+	  (GDB_TARGET_IS_SPARC64   && regno == FSR_REGNUM) ||
+	  (regno >= FP0_REGNUM
+	   && regno < FP0_REGNUM + ((GDB_TARGET_IS_SPARC64) ? 48 : 32)))
+	{
+	  elf64_greg_t *fp_double = (elf64_greg_t *)&u.fpregs.regs[32];
+
+	  if (0 != ptrace (PTRACE_GETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_getfpregs");
+
+	  if (regno == -1)
+	    {
+	      if (GDB_TARGET_IS_SPARC64)
+		{
+		  for (i = 0; i < 32; i++)
+		    supply_register (FP0_REGNUM + i, (char *) &u.fpregs.regs[i]);
+		  for (i = 0; i < 16; i++)
+		    supply_register (FP0_REGNUM + i + 32, (char *) &fp_double[i]);
+		  supply_register (FSR_REGNUM, (char *) &u.fpregs.fsr);
+		}
+	      else
+		{
+		  for (i = 0; i < 32; i++)
+		    supply_register (FP0_REGNUM + i, (char *)&u.fpregs.regs[i]);
+		  supply_register (FPS_REGNUM, ((char *) &u.fpregs.fsr) + offset);
+		}
+	    }
+	  else
+	    {
+	      if (regno >= FP0_REGNUM && regno < (FP0_REGNUM + 32))
+		supply_register (regno, (char *) &u.fpregs.regs[regno - FP0_REGNUM]);
+	      else if (regno >= FP0_REGNUM + 32
+		       && regno < FP0_REGNUM + 48)
+		supply_register (regno, (char *) &fp_double[regno - 32 - FP0_REGNUM]);
+	      else if (GDB_TARGET_IS_SPARC64)
+		supply_register (FSR_REGNUM, (char *) &u.fpregs.fsr);
+	      else
+		supply_register (FPS_REGNUM, ((char *) &u.fpregs.fsr) + offset);
+	    }
+	}
+    }
+  else
+    {
+      union {
+	struct pt32_regs regs;
+	struct pt32_fpregs fpregs;
+      } u;
+
+      if (regno <= O7_REGNUM
+	  || regno >= Y_REGNUM
+	  || (!register_cached (SP_REGNUM) && regno <= I7_REGNUM))
+	{
+	  if (0 != ptrace (PTRACE_GETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_getregs");
+
+	  supply_register (G0_REGNUM, NULL);
+	  if (regno == -1)
+	    {
+	      for (i = G1_REGNUM; i < G1_REGNUM + 15; i++)
+		{
+		  char *regptr = (char *)&u.regs,u_regs[i - G1_REGNUM + UREG_G1];
+
+		  supply_register (i, regptr);
+		}
+	    }
+	  else if (regno >= G1_REGNUM && regno < G1_REGNUM + 15)
+	    {
+	      char *regptr = (char *)&u.regs.u_regs[regno - G1_REGNUM + UREG_G1];
+
+	      supply_register (regno, regptr);
+	    }
+	  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+	    {
+	      char *regptr = (char *)&u.regs.u_regs[SP_REGNUM - G1_REGNUM + UREG_G1];
+
+	      supply_register (SP_REGNUM, regptr);
+	    }
+
+	  if (regno == -1 || regno == PS_REGNUM)
+	    supply_register (PS_REGNUM, (char *) &u.regs.psr);
+	  if (regno == -1 || regno == PC_REGNUM)
+	    supply_register (PC_REGNUM, (char *) &u.regs.pc);
+	  if (regno == -1 || regno == NPC_REGNUM)
+	    supply_register (NPC_REGNUM, (char *) &u.regs.npc);
+	  if (regno == -1 || regno == Y_REGNUM)
+	    supply_register (Y_REGNUM, (char *) &u.regs.y);
+
+	  if (regno == -1)
+	    {
+	      supply_register (WIM_REGNUM, NULL);
+	      supply_register (TBR_REGNUM, NULL);
+	      supply_register (CPS_REGNUM, NULL);
+	    }
+	}
+
+      if (regno == -1 ||
+	  regno == FPS_REGNUM ||
+	  (regno >= FP0_REGNUM
+	   && regno < FP0_REGNUM + 32))
+	{
+	  if (0 != ptrace (PTRACE_GETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_getfpregs");
+
+	  if (regno == -1)
+	    {
+	      for (i = 0; i < 32; i++)
+		supply_register (FP0_REGNUM + i, (char *)&u.fpregs.regs[i]);
+	      supply_register (FPS_REGNUM, (char *) &u.fpregs.fsr);
+	    }
+	  else if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+	    {
+	      supply_register (regno, (char *)&u.fpregs.regs[regno - FP0_REGNUM]);
+	    }
+	  else
+	    supply_register (FPS_REGNUM, (char *) &u.fpregs.fsr);
+	}
+    }
+
+  if (regno == -1)
+    {
+      buf = alloca (16 * intreg_size);
+      target_read_memory (read_sp (), buf, 16 * intreg_size);
+      for (i = 0; i <= (I7_REGNUM - L0_REGNUM); i++)
+	supply_register (i + L0_REGNUM,
+			 buf + (i * intreg_size));
+    }
+  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+    {
+      buf = alloca (intreg_size);
+      target_read_memory (read_sp () + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+			  buf, intreg_size);
+      supply_register (regno, buf);
+    }
+}
+
+static void
+store_all_registers (int proc_id)
 {
   int i;
 
-  for (i = FP0_REGNUM; i < FP0_REGNUM + 32; i++)
-    if (regno == -1 || regno == i)
-      regcache_collect (i, &fpregsetp->pr_fr.pr_regs[i - FP0_REGNUM]);
+  if (sizeof (void *) == 8)
+    {
+      union {
+	struct pt64_regs regs;
+	struct pt64_fpregs fpregs;
+      } u;
+      int offset = (SPARC_INTREG_SIZE == 4) ? 4 : 0;
+
+      for (i = G1_REGNUM; i < G0_REGNUM + 16; i++)
+	{
+	  char *regptr = ((char *)&u.regs.u_regs[i - G1_REGNUM + UREG_G1]);
+
+	  if (offset != 0)
+	    memset (regptr, 0, sizeof(elf64_greg_t));
+	  regptr += offset;
+	  read_register_gen (i, regptr);
+	}
+      if (! GDB_TARGET_IS_SPARC64)
+	{
+	  elf32_greg_t tmp32;
+
+	  read_register_gen (PS_REGNUM, (char *) &tmp32);
+	  u.regs.tstate = psr_to_tstate_icc(tmp32);
+
+	  read_register_gen (PC_REGNUM, (char *) &tmp32);
+	  u.regs.tpc = tmp32;
+
+	  read_register_gen (NPC_REGNUM, (char *) &tmp32);
+	  u.regs.tnpc = tmp32;
+
+	  read_register_gen (Y_REGNUM, (char *) &tmp32);
+	  u.regs.y = tmp32;
+	}
+      else
+	{
+	  elf64_greg_t ccr;
+
+	  read_register_gen(CCR_REGNUM, (char *) &ccr);
+	  u.regs.tstate = ccr_to_tstate(ccr);
+
+	  read_register_gen(PC_REGNUM, (char *) &u.regs.tpc);
+	  read_register_gen(NPC_REGNUM, (char *) &u.regs.tnpc);
+	  read_register_gen(Y_REGNUM, (char *) &u.regs.y);
+	}
+
+      if (0 != ptrace (PTRACE_SETREGS, proc_id,
+		       (PTRACE_ARG3_TYPE) &u.regs, 0))
+	perror ("ptrace_setregs");
+
+      for (i = 0; i < 32; i++)
+	read_register_gen (FP0_REGNUM + i, (char *) &u.fpregs.regs[i]);
+      if (GDB_TARGET_IS_SPARC64)
+	{
+	  elf64_greg_t *fp_double = (elf64_greg_t *) &u.fpregs.regs[32];
+	  for (i = 0; i < 16; i++)
+	    read_register_gen (FP0_REGNUM + 32 + i, (char *) &fp_double[i]);
+	  read_register_gen (FSR_REGNUM, (char *) &u.fpregs.fsr);
+	}
+      else
+	read_register_gen (FPS_REGNUM, ((char *) &u.fpregs.fsr) + offset);
+
+      if (0 != ptrace (PTRACE_SETFPREGS, proc_id,
+		       (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	perror ("ptrace_setfpregs");
+    }
+  else
+    {
+      union {
+	struct pt32_regs regs;
+	struct pt32_fpregs fpregs;
+      } u;
+
+      for (i = G1_REGNUM; i < G0_REGNUM + 16; i++)
+	{
+	  char *regptr = ((char *)&u.regs.u_regs[i - G1_REGNUM + UREG_G1]);
+
+	  read_register_gen (i, regptr);
+	}
+      read_register_gen(PS_REGNUM, (char *) &u.regs.psr);
+      read_register_gen(PC_REGNUM, (char *) &u.regs.pc);
+      read_register_gen(NPC_REGNUM, (char *) &u.regs.npc);
+      read_register_gen(Y_REGNUM, (char *) &u.regs.y);
+
+      if (0 != ptrace (PTRACE_SETREGS, proc_id,
+		       (PTRACE_ARG3_TYPE) &u.regs, 0))
+	perror ("ptrace_setregs");
+
+      for (i = 0; i < 32; i++)
+	read_register_gen (FP0_REGNUM + i, (char *) &u.fpregs.regs[i]);
+      read_register_gen (FPS_REGNUM, (char *) &u.fpregs.fsr);
+
+      if (0 != ptrace (PTRACE_SETFPREGS, proc_id,
+		       (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	perror ("ptrace_setfpregs");
+    }
+}
 
-  if (regno == -1 || regno == FPS_REGNUM)
-    regcache_collect (FPS_REGNUM, &fpregsetp->pr_fsr);
+void
+store_inferior_registers (int regno)
+{
+  int intreg_size = SPARC_INTREG_SIZE;
+  int proc_id, i, store_mask;
+  char *buf;
+
+  /* GNU/Linux LWP ID's are process ID's.  */
+  if ((proc_id = TIDGET (inferior_ptid)) == 0)
+    proc_id = PIDGET (inferior_ptid);		/* Not a threaded program.  */
+
+  if (regno == G1_REGNUM)
+    return;
+
+  if (regno < 0 || regno == SP_REGNUM)
+    {
+      CORE_ADDR sp = read_sp ();
+
+      if (!register_cached(L0_REGNUM + 5))
+	internal_error (__FILE__, __LINE__, "failed internal consistency check");
+      target_write_memory (sp,
+			   &registers[REGISTER_BYTE (L0_REGNUM)],
+			   16 * intreg_size);
+    }
+  else if (regno >= L0_REGNUM && regno <= I7_REGNUM)
+    {
+      CORE_ADDR sp = read_sp ();
+
+      if (!register_cached(regno))
+	internal_error (__FILE__, __LINE__, "failed internal consistency check");
+      target_write_memory (sp + REGISTER_BYTE (regno) - REGISTER_BYTE (L0_REGNUM),
+			   &registers[REGISTER_BYTE (regno)],
+			   intreg_size);
+      return;
+    }
+
+  if (regno < 0)
+    {
+      store_all_registers (proc_id);
+      return;
+    }
+
+  if (sizeof (void *) == 8)
+    {
+      union {
+	struct pt64_regs regs;
+	struct pt64_fpregs fpregs;
+      } u;
+      int offset = (intreg_size == 4) ? 4 : 0;
+
+      if (regno <= O7_REGNUM
+	  || (regno >= Y_REGNUM && regno != FSR_REGNUM))
+	{
+	  if (0 != ptrace (PTRACE_GETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_getregs");
+
+	  if (regno >= G1_REGNUM && regno <= O7_REGNUM)
+	    {
+	      char *regptr = (char *) &u.regs.u_regs[regno - G1_REGNUM + UREG_G1];
+
+	      if (offset != 0)
+		memset (regptr, 0, sizeof(elf64_greg_t));
+	      regptr += offset;
+	      read_register_gen(regno, regptr);
+	    }
+	  if (! GDB_TARGET_IS_SPARC64)
+	    {
+	      elf32_greg_t tmp32;
+
+	      if (regno == PS_REGNUM)
+		{
+		  read_register_gen (PS_REGNUM, (char *) &tmp32);
+		  u.regs.tstate = psr_to_tstate_icc(tmp32);
+		}
+	      if (regno == PC_REGNUM)
+		{
+		  read_register_gen (PC_REGNUM, (char *) &tmp32);
+		  u.regs.tpc = tmp32;
+		}
+	      if (regno == NPC_REGNUM)
+		{
+		  read_register_gen (NPC_REGNUM, (char *) &tmp32);
+		  u.regs.tnpc = tmp32;
+		}
+	      if (regno == Y_REGNUM)
+		{
+		  read_register_gen (Y_REGNUM, (char *) &tmp32);
+		  u.regs.y = tmp32;
+		}
+	    }
+	  else
+	    {
+	      if (regno == CCR_REGNUM)
+		{
+		  elf64_greg_t ccr;
+
+		  read_register_gen (CCR_REGNUM, (char *) &ccr);
+		  u.regs.tstate = ccr_to_tstate(ccr);
+		}
+	      if (regno == PC_REGNUM)
+		read_register_gen (PC_REGNUM, (char *) &u.regs.tpc);
+	      if (regno == NPC_REGNUM)
+		read_register_gen (NPC_REGNUM, (char *) &u.regs.tnpc);
+	      if (regno == Y_REGNUM)
+		read_register_gen (Y_REGNUM, (char *) &u.regs.y);
+	    }
+
+	  if (0 != ptrace (PTRACE_SETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_setregs");
+	}
+      else
+	{
+	  if (0 != ptrace (PTRACE_GETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_getfpregs");
+
+	  if (GDB_TARGET_IS_SPARC64)
+	    {
+	      if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+		read_register_gen (regno, (char *) &u.fpregs.regs[regno - FP0_REGNUM]);
+	      else if (regno >= FP0_REGNUM + 32 && regno < FP0_REGNUM + 48)
+		{
+		  elf64_greg_t *fp_double = (elf64_greg_t *) &u.fpregs.regs[32];
+		  read_register_gen (regno,
+				     (char *) &fp_double[regno - (FP0_REGNUM + 32)]);
+		}
+	      else if (regno == FSR_REGNUM)
+		read_register_gen (FSR_REGNUM, (char *) &u.fpregs.fsr);
+	    }
+	  else
+	    {
+	      if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+		read_register_gen (regno, (char *) &u.fpregs.regs[regno - FP0_REGNUM]);
+	      else if (regno == FPS_REGNUM)
+		read_register_gen (FPS_REGNUM, ((char *) &u.fpregs.fsr) + offset);
+	    }
+
+	  if (0 != ptrace (PTRACE_SETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_setfpregs");
+	}
+    }
+  else
+    {
+      union {
+	struct pt32_regs regs;
+	struct pt32_fpregs fpregs;
+      } u;
+
+      if (regno <= O7_REGNUM
+	  || (regno >= Y_REGNUM && regno != FPS_REGNUM))
+	{
+	  if (0 != ptrace (PTRACE_GETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_getregs");
+
+	  if (regno >= G1_REGNUM && regno <= O7_REGNUM)
+	    {
+	      char *regptr = (char *) &u.regs.u_regs[regno - G1_REGNUM + UREG_G1];
+
+	      read_register_gen(regno, regptr);
+	    }
+	  if (regno == PS_REGNUM)
+	    read_register_gen (PS_REGNUM, (char *) &u.regs.psr);
+	  if (regno == PC_REGNUM)
+	    read_register_gen (PC_REGNUM, (char *) &u.regs.pc);
+	  if (regno == NPC_REGNUM)
+	    read_register_gen (NPC_REGNUM, (char *) &u.regs.npc);
+	  if (regno == Y_REGNUM)
+	    read_register_gen (Y_REGNUM, (char *) &u.regs.y);
+
+	  if (0 != ptrace (PTRACE_SETREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.regs, 0))
+	    perror ("ptrace_setregs");
+	}
+      else
+	{
+	  if (0 != ptrace (PTRACE_GETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_getfpregs");
+
+	  if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32)
+	    read_register_gen (regno, (char *) &u.fpregs.regs[regno - FP0_REGNUM]);
+	  else if (regno == FPS_REGNUM)
+	    read_register_gen (FPS_REGNUM, (char *) &u.fpregs.fsr);
+
+	  if (0 != ptrace (PTRACE_SETFPREGS, proc_id,
+			   (PTRACE_ARG3_TYPE) &u.fpregs, 0))
+	    perror ("ptrace_setfpregs");
+	}
+    }
 }
 
+/* Register that we are able to handle ELF file formats using standard
+   procfs "regset" structures.  */
+
+static struct core_fns sparc_linux_core_fns =
+{
+  bfd_target_elf_flavour,		/* core_flavour */
+  default_check_format,			/* check_format */
+  default_core_sniffer,			/* core_sniffer */
+  fetch_core_registers,			/* core_read_registers */
+  NULL					/* next */
+};
+
+void
+_initialize_core_sparc_linux (void)
+{
+  add_core_fns (&sparc_linux_core_fns);
+}
 
 /* Oh well, glibc's Linux ptrace() implementation does not understand
    the 5-arg calls that we need here.  */
--- ./Makefile.in.~1~	Fri Apr 19 15:52:11 2002
+++ ./Makefile.in	Fri Apr 19 22:16:02 2002
@@ -2046,7 +2046,8 @@ source.o: source.c $(defs_h) $(expressio
 	$(symtab_h) $(gdb_string_h) $(source_h) $(completer_h) $(linespec_h) \
 	$(ui_out_h)
 
-sparc-linux-nat.o: sparc-linux-nat.c $(defs_h) $(regcache_h) $(inferior_h)
+sparc-linux-nat.o: sparc-linux-nat.c $(defs_h) $(regcache_h) $(gdbcore_h) \
+	$(gdb_string_h) $(inferior_h) $(target_h) gregset.h
 
 sparc-nat.o: sparc-nat.c $(bfd_h) $(defs_h) $(inferior_h) $(gdbcore_h) \
 	$(target_h) $(regcache_h)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]