#include "defs.h"
#include "inferior.h"
#include "regcache.h"
#include "target.h"
#include "gdb_assert.h"
#include <signal.h>
#include "gdb_string.h"
#include <sys/ptrace.h>
#include "gdb_wait.h"
#ifdef HAVE_MACHINE_REG_H
#include <machine/reg.h>
#endif
#include "sparc-tdep.h"
#include "sparc-nat.h"
#ifdef HAVE_MACHINE_REG_H
#ifdef HAVE_STRUCT_REG
typedef struct reg gregset_t;
typedef struct fpreg fpregset_t;
#else
typedef struct regs gregset_t;
typedef struct fp_status fpregset_t;
#endif
#endif
#ifndef PTRACE_GETREGS
#define PTRACE_GETREGS PT_GETREGS
#endif
#ifndef PTRACE_SETREGS
#define PTRACE_SETREGS PT_SETREGS
#endif
#ifndef PTRACE_GETFPREGS
#define PTRACE_GETFPREGS PT_GETFPREGS
#endif
#ifndef PTRACE_SETFPREGS
#define PTRACE_SETFPREGS PT_SETFPREGS
#endif
const struct sparc_gregset *sparc_gregset;
void (*sparc_supply_gregset) (const struct sparc_gregset *,
struct regcache *, int , const void *);
void (*sparc_collect_gregset) (const struct sparc_gregset *,
const struct regcache *, int, void *);
void (*sparc_supply_fpregset) (struct regcache *, int , const void *);
void (*sparc_collect_fpregset) (const struct regcache *, int , void *);
int (*sparc_gregset_supplies_p) (int);
int (*sparc_fpregset_supplies_p) (int);
int
sparc32_gregset_supplies_p (int regnum)
{
if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
|| (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
|| (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
|| (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
return 1;
if (regnum == SPARC32_PC_REGNUM
|| regnum == SPARC32_NPC_REGNUM
|| regnum == SPARC32_PSR_REGNUM
|| regnum == SPARC32_Y_REGNUM)
return 1;
return 0;
}
int
sparc32_fpregset_supplies_p (int regnum)
{
if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
return 1;
if (regnum == SPARC32_FSR_REGNUM)
return 1;
return 0;
}
void
fetch_inferior_registers (int regnum)
{
struct regcache *regcache = current_regcache;
int pid;
pid = TIDGET (inferior_ptid);
if (pid == 0)
pid = PIDGET (inferior_ptid);
if (regnum == SPARC_G0_REGNUM)
{
regcache_raw_supply (regcache, SPARC_G0_REGNUM, NULL);
return;
}
if (regnum == -1 || sparc_gregset_supplies_p (regnum))
{
gregset_t regs;
if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_supply_gregset (sparc_gregset, regcache, -1, ®s);
if (regnum != -1)
return;
}
if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
{
fpregset_t fpregs;
if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating point status");
sparc_supply_fpregset (regcache, -1, &fpregs);
}
}
void
store_inferior_registers (int regnum)
{
struct regcache *regcache = current_regcache;
int pid;
pid = TIDGET (inferior_ptid);
if (pid == 0)
pid = PIDGET (inferior_ptid);
if (regnum == -1 || sparc_gregset_supplies_p (regnum))
{
gregset_t regs;
if (ptrace (PTRACE_GETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
perror_with_name ("Couldn't get registers");
sparc_collect_gregset (sparc_gregset, regcache, regnum, ®s);
if (ptrace (PTRACE_SETREGS, pid, (PTRACE_ARG3_TYPE) ®s, 0) == -1)
perror_with_name ("Couldn't write registers");
if (regnum == -1 || regnum == SPARC_SP_REGNUM
|| (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM))
{
ULONGEST sp;
regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
sparc_collect_rwindow (regcache, sp, regnum);
}
if (regnum != -1)
return;
}
if (regnum == -1 || sparc_fpregset_supplies_p (regnum))
{
fpregset_t fpregs, saved_fpregs;
if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
perror_with_name ("Couldn't get floating-point registers");
memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
sparc_collect_fpregset (regcache, regnum, &fpregs);
if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
{
if (ptrace (PTRACE_SETFPREGS, pid,
(PTRACE_ARG3_TYPE) &fpregs, 0) == -1)
perror_with_name ("Couldn't write floating-point registers");
}
if (regnum != -1)
return;
}
}
LONGEST
sparc_xfer_wcookie (struct target_ops *ops, enum target_object object,
const char *annex, void *readbuf, const void *writebuf,
ULONGEST offset, LONGEST len)
{
unsigned long wcookie = 0;
char *buf = (char *)&wcookie;
gdb_assert (object == TARGET_OBJECT_WCOOKIE);
gdb_assert (readbuf && writebuf == NULL);
if (offset >= sizeof (unsigned long))
return -1;
#ifdef PT_WCOOKIE
{
int pid;
pid = TIDGET (inferior_ptid);
if (pid == 0)
pid = PIDGET (inferior_ptid);
gdb_assert (sizeof (wcookie) == sizeof (register_t));
if (ptrace (PT_WCOOKIE, pid, (PTRACE_ARG3_TYPE) &wcookie, 0) == -1)
{
if (errno != EINVAL)
perror_with_name ("Couldn't get StackGhost cookie");
wcookie = 0x3;
}
}
#endif
if (len > sizeof (unsigned long) - offset)
len = sizeof (unsigned long) - offset;
memcpy (readbuf, buf + offset, len);
return len;
}
void _initialize_sparc_nat (void);
void
_initialize_sparc_nat (void)
{
if (sparc_gregset == NULL)
sparc_gregset = &sparc32_sunos4_gregset;
if (sparc_supply_gregset == NULL)
sparc_supply_gregset = sparc32_supply_gregset;
if (sparc_collect_gregset == NULL)
sparc_collect_gregset = sparc32_collect_gregset;
if (sparc_supply_fpregset == NULL)
sparc_supply_fpregset = sparc32_supply_fpregset;
if (sparc_collect_fpregset == NULL)
sparc_collect_fpregset = sparc32_collect_fpregset;
if (sparc_gregset_supplies_p == NULL)
sparc_gregset_supplies_p = sparc32_gregset_supplies_p;
if (sparc_fpregset_supplies_p == NULL)
sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p;
}