* Makefile.in (arm_linux_tdep_h): New variable.

(arm-linux-nat.o, arm-linux-tdep.o): Update.
	* arm-linux-nat.c: Include "arm-linux-tdep.h".
	(typeNone, typeSingle, typeDouble, typeExtended)
	(FPWORDS, ARM_CPSR_REGNUM, FPREG, FPA11)
	(fetch_nwfpe_single, fetch_nwfpe_double, fetch_nwfpe_none)
	(fetch_nwfpe_extended, fetch_nwfpe_register, store_nwfpe_single)
	(store_nwfpe_double, store_nwfpe_extended, store_nwfpe_register):
	Delete.
	(fetch_fpregister, fetch_fpregs, store_fpregister, store_fpregs):
	Use gdb_byte buffers, NWFPE_FPSR_OFFSET, supply_nwfpe_register,
	and collect_nwfpe_register.
	(fill_gregset, supply_gregset, fill_fpregset, supply_fpregset): Use
	new regset functions.
	* arm-linux-tdep.c: Include "regset.h" and "arm-linux-tdep.h".
	(arm_apcs_32): New declaration.
	(ARM_LINUX_SIZEOF_GREGSET, arm_linux_supply_gregset)
	(arm_linux_collect_gregset, typeNone, typeSingle, typeDouble)
	(typeExtended, supply_nwfpe_register, collect_nwfpe_register)
	(arm_linux_supply_nwfpe, arm_linux_collect_nwfpe)
	(arm_linux_regset_from_core_section): New.
	(arm_linux_init_abi): Register arm_linux_regset_from_core_section.
	* arm-linux-tdep.h: New file.
	* arm-tdep.h (struct regset): Declare.
	(struct gdbarch_tdep): Add gregset, fpregset members.
	* config/arm/linux.mh (NATDEPFILES): Remove corelow.o and
	core-regset.o.
	* config/arm/linux.mt (TDEPFILES): Add corelow.o.
This commit is contained in:
Daniel Jacobowitz
2006-07-12 20:46:33 +00:00
parent 8802d8ed3a
commit cb587d836a
8 changed files with 356 additions and 292 deletions

View File

@@ -28,6 +28,7 @@
#include "linux-nat.h"
#include "arm-tdep.h"
#include "arm-linux-tdep.h"
#include <sys/user.h>
#include <sys/ptrace.h>
@@ -46,32 +47,6 @@
extern int arm_apcs_32;
#define typeNone 0x00
#define typeSingle 0x01
#define typeDouble 0x02
#define typeExtended 0x03
#define FPWORDS 28
#define ARM_CPSR_REGNUM 16
typedef union tagFPREG
{
unsigned int fSingle;
unsigned int fDouble[2];
unsigned int fExtended[3];
}
FPREG;
typedef struct tagFPA11
{
FPREG fpreg[8]; /* 8 floating point registers */
unsigned int fpsr; /* floating point status register */
unsigned int fpcr; /* floating point control register */
unsigned char fType[8]; /* type of floating point value held in
floating point registers. */
int initflag; /* NWFPE initialization flag. */
}
FPA11;
/* The following variables are used to determine the version of the
underlying GNU/Linux operating system. Examples:
@@ -104,132 +79,6 @@ get_thread_id (ptid_t ptid)
}
#define GET_THREAD_ID(PTID) get_thread_id ((PTID));
static void
fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fSingle;
mem[1] = 0;
mem[2] = 0;
regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fDouble[1];
mem[1] = fpa11->fpreg[fn].fDouble[0];
mem[2] = 0;
regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nwfpe_none (unsigned int fn)
{
unsigned int mem[3] =
{0, 0, 0};
regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
{
unsigned int mem[3];
mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
}
static void
fetch_nwfpe_register (int regno, FPA11 * fpa11)
{
int fn = regno - ARM_F0_REGNUM;
switch (fpa11->fType[fn])
{
case typeSingle:
fetch_nwfpe_single (fn, fpa11);
break;
case typeDouble:
fetch_nwfpe_double (fn, fpa11);
break;
case typeExtended:
fetch_nwfpe_extended (fn, fpa11);
break;
default:
fetch_nwfpe_none (fn);
}
}
static void
store_nwfpe_single (unsigned int fn, FPA11 *fpa11)
{
unsigned int mem[3];
regcache_raw_collect (current_regcache, ARM_F0_REGNUM + fn,
(char *) &mem[0]);
fpa11->fpreg[fn].fSingle = mem[0];
fpa11->fType[fn] = typeSingle;
}
static void
store_nwfpe_double (unsigned int fn, FPA11 *fpa11)
{
unsigned int mem[3];
regcache_raw_collect (current_regcache, ARM_F0_REGNUM + fn,
(char *) &mem[0]);
fpa11->fpreg[fn].fDouble[1] = mem[0];
fpa11->fpreg[fn].fDouble[0] = mem[1];
fpa11->fType[fn] = typeDouble;
}
void
store_nwfpe_extended (unsigned int fn, FPA11 *fpa11)
{
unsigned int mem[3];
regcache_raw_collect (current_regcache, ARM_F0_REGNUM + fn,
(char *) &mem[0]);
fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
fpa11->fType[fn] = typeDouble;
}
void
store_nwfpe_register (int regno, FPA11 * fpa11)
{
if (register_cached (regno))
{
unsigned int fn = regno - ARM_F0_REGNUM;
switch (fpa11->fType[fn])
{
case typeSingle:
store_nwfpe_single (fn, fpa11);
break;
case typeDouble:
store_nwfpe_double (fn, fpa11);
break;
case typeExtended:
store_nwfpe_extended (fn, fpa11);
break;
}
}
}
/* Get the value of a particular register from the floating point
state of the process and store it into regcache. */
@@ -237,13 +86,13 @@ static void
fetch_fpregister (int regno)
{
int ret, tid;
FPA11 fp;
gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
/* Get the thread id for the ptrace call. */
tid = GET_THREAD_ID (inferior_ptid);
/* Read the floating point state. */
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
ret = ptrace (PT_GETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to fetch floating point register."));
@@ -252,31 +101,12 @@ fetch_fpregister (int regno)
/* Fetch fpsr. */
if (ARM_FPS_REGNUM == regno)
regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
fp + NWFPE_FPSR_OFFSET);
/* Fetch the floating point register. */
if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
{
int fn = regno - ARM_F0_REGNUM;
switch (fp.fType[fn])
{
case typeSingle:
fetch_nwfpe_single (fn, &fp);
break;
case typeDouble:
fetch_nwfpe_double (fn, &fp);
break;
case typeExtended:
fetch_nwfpe_extended (fn, &fp);
break;
default:
fetch_nwfpe_none (fn);
}
}
supply_nwfpe_register (current_regcache, regno, fp);
}
/* Get the whole floating point state of the process and store it
@@ -286,13 +116,13 @@ static void
fetch_fpregs (void)
{
int ret, regno, tid;
FPA11 fp;
gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
/* Get the thread id for the ptrace call. */
tid = GET_THREAD_ID (inferior_ptid);
/* Read the floating point state. */
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
ret = ptrace (PT_GETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to fetch the floating point registers."));
@@ -300,31 +130,12 @@ fetch_fpregs (void)
}
/* Fetch fpsr. */
regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
regcache_raw_supply (current_regcache, ARM_FPS_REGNUM,
fp + NWFPE_FPSR_OFFSET);
/* Fetch the floating point registers. */
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
{
int fn = regno - ARM_F0_REGNUM;
switch (fp.fType[fn])
{
case typeSingle:
fetch_nwfpe_single (fn, &fp);
break;
case typeDouble:
fetch_nwfpe_double (fn, &fp);
break;
case typeExtended:
fetch_nwfpe_extended (fn, &fp);
break;
default:
fetch_nwfpe_none (fn);
}
}
supply_nwfpe_register (current_regcache, regno, fp);
}
/* Save a particular register into the floating point state of the
@@ -334,13 +145,13 @@ static void
store_fpregister (int regno)
{
int ret, tid;
FPA11 fp;
gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
/* Get the thread id for the ptrace call. */
tid = GET_THREAD_ID (inferior_ptid);
/* Read the floating point state. */
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
ret = ptrace (PT_GETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to fetch the floating point registers."));
@@ -349,15 +160,14 @@ store_fpregister (int regno)
/* Store fpsr. */
if (ARM_FPS_REGNUM == regno && register_cached (ARM_FPS_REGNUM))
regcache_raw_collect (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
fp + NWFPE_FPSR_OFFSET);
/* Store the floating point register. */
if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
{
store_nwfpe_register (regno, &fp);
}
collect_nwfpe_register (current_regcache, regno, fp);
ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to store floating point register."));
@@ -372,13 +182,13 @@ static void
store_fpregs (void)
{
int ret, regno, tid;
FPA11 fp;
gdb_byte fp[ARM_LINUX_SIZEOF_NWFPE];
/* Get the thread id for the ptrace call. */
tid = GET_THREAD_ID (inferior_ptid);
/* Read the floating point state. */
ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
ret = ptrace (PT_GETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to fetch the floating point registers."));
@@ -387,15 +197,15 @@ store_fpregs (void)
/* Store fpsr. */
if (register_cached (ARM_FPS_REGNUM))
regcache_raw_collect (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
fp + NWFPE_FPSR_OFFSET);
/* Store the floating point registers. */
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
{
fetch_nwfpe_register (regno, &fp);
}
if (register_cached (regno))
collect_nwfpe_register (current_regcache, regno, fp);
ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
ret = ptrace (PTRACE_SETFPREGS, tid, 0, fp);
if (ret < 0)
{
warning (_("Unable to store floating point registers."));
@@ -597,83 +407,25 @@ arm_linux_store_inferior_registers (int regno)
}
}
/* Fill register regno (if it is a general-purpose register) in
*gregsetp with the appropriate value from GDB's register array.
If regno is -1, do this for all registers. */
/* Wrapper functions for the standard regset handling, used by
thread debugging. */
void
fill_gregset (gdb_gregset_t *gregsetp, int regno)
{
if (-1 == regno)
{
int regnum;
for (regnum = ARM_A1_REGNUM; regnum <= ARM_PC_REGNUM; regnum++)
regcache_raw_collect (current_regcache, regnum,
(char *) &(*gregsetp)[regnum]);
}
else if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
regcache_raw_collect (current_regcache, regno,
(char *) &(*gregsetp)[regno]);
if (ARM_PS_REGNUM == regno || -1 == regno)
{
if (arm_apcs_32)
regcache_raw_collect (current_regcache, ARM_PS_REGNUM,
(char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
else
regcache_raw_collect (current_regcache, ARM_PC_REGNUM,
(char *) &(*gregsetp)[ARM_PC_REGNUM]);
}
arm_linux_collect_gregset (NULL, current_regcache, regno, gregsetp, 0);
}
/* Fill GDB's register array with the general-purpose register values
in *gregsetp. */
void
supply_gregset (gdb_gregset_t *gregsetp)
{
int regno, reg_pc;
for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
regcache_raw_supply (current_regcache, regno,
(char *) &(*gregsetp)[regno]);
if (arm_apcs_32)
regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
(char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
else
regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
(char *) &(*gregsetp)[ARM_PC_REGNUM]);
reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[ARM_PC_REGNUM]);
regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &reg_pc);
arm_linux_supply_gregset (NULL, current_regcache, -1, gregsetp, 0);
}
/* Fill register regno (if it is a floating-point register) in
*fpregsetp with the appropriate value from GDB's register array.
If regno is -1, do this for all registers. */
void
fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
{
FPA11 *fp = (FPA11 *) fpregsetp;
if (-1 == regno)
{
int regnum;
for (regnum = ARM_F0_REGNUM; regnum <= ARM_F7_REGNUM; regnum++)
store_nwfpe_register (regnum, fp);
}
else if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
{
store_nwfpe_register (regno, fp);
return;
}
/* Store fpsr. */
if (ARM_FPS_REGNUM == regno || -1 == regno)
regcache_raw_collect (current_regcache, ARM_FPS_REGNUM,
(char *) &fp->fpsr);
arm_linux_collect_nwfpe (NULL, current_regcache, regno, fpregsetp, 0);
}
/* Fill GDB's register array with the floating-point register values
@@ -682,17 +434,7 @@ fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
void
supply_fpregset (gdb_fpregset_t *fpregsetp)
{
int regno;
FPA11 *fp = (FPA11 *) fpregsetp;
/* Fetch fpsr. */
regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp->fpsr);
/* Fetch the floating point registers. */
for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
{
fetch_nwfpe_register (regno, fp);
}
arm_linux_supply_nwfpe (NULL, current_regcache, -1, fpregsetp, 0);
}
int