(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.
+2006-07-12 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * 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.
+
2006-07-12 Jan Kratochvil <lace@jankratochvil.net>
* infrun.c (handle_inferior_event): Fixed typos in printf.
amd64_tdep_h = amd64-tdep.h $(i386_tdep_h)
annotate_h = annotate.h $(symtab_h) $(gdbtypes_h)
arch_utils_h = arch-utils.h
+arm_linux_tdep_h = arm-linux-tdep.h
arm_tdep_h = arm-tdep.h
auxv_h = auxv.h
ax_gdb_h = ax-gdb.h
$(floatformat_h)
arm-linux-nat.o: arm-linux-nat.c $(defs_h) $(inferior_h) $(gdbcore_h) \
$(gdb_string_h) $(regcache_h) $(arm_tdep_h) $(gregset_h) \
- $(target_h) $(linux_nat_h) $(gdb_proc_service_h)
+ $(target_h) $(linux_nat_h) $(gdb_proc_service_h) $(arm_linux_tdep_h)
arm-linux-tdep.o: arm-linux-tdep.c $(defs_h) $(target_h) $(value_h) \
$(gdbtypes_h) $(floatformat_h) $(gdbcore_h) $(frame_h) $(regcache_h) \
$(doublest_h) $(solib_svr4_h) $(osabi_h) $(arm_tdep_h) \
+ $(regset_h) $(arm_linux_tdep_h) \
$(glibc_tdep_h) $(trad_frame_h) $(tramp_frame_h) $(gdb_string_h)
armnbsd-nat.o: armnbsd-nat.c $(defs_h) $(gdbcore_h) $(inferior_h) \
$(regcache_h) $(target_h) $(gdb_string_h) $(arm_tdep_h) $(inf_ptrace_h)
#include "linux-nat.h"
#include "arm-tdep.h"
+#include "arm-linux-tdep.h"
#include <sys/user.h>
#include <sys/ptrace.h>
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:
}
#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. */
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."));
/* 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
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."));
}
/* 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
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."));
/* 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."));
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."));
/* 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."));
}
}
-/* 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 *) ®_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
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
#include "doublest.h"
#include "solib-svr4.h"
#include "osabi.h"
+#include "regset.h"
#include "trad-frame.h"
#include "tramp-frame.h"
#include "arm-tdep.h"
+#include "arm-linux-tdep.h"
#include "glibc-tdep.h"
#include "gdb_string.h"
+extern int arm_apcs_32;
+
/* Under ARM GNU/Linux the traditional way of performing a breakpoint
is to execute a particular software interrupt, rather than use a
particular undefined instruction to provoke a trap. Upon exection
arm_linux_rt_sigreturn_init
};
+/* Core file and register set support. */
+
+#define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
+
+void
+arm_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *gregs_buf, size_t len)
+{
+ const gdb_byte *gregs = gregs_buf;
+ int regno;
+ CORE_ADDR reg_pc;
+ gdb_byte pc_buf[INT_REGISTER_SIZE];
+
+ for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ regcache_raw_supply (regcache, regno,
+ gregs + INT_REGISTER_SIZE * regno);
+
+ if (regnum == ARM_PS_REGNUM || regnum == -1)
+ {
+ if (arm_apcs_32)
+ regcache_raw_supply (regcache, ARM_PS_REGNUM,
+ gregs + INT_REGISTER_SIZE * ARM_CPSR_REGNUM);
+ else
+ regcache_raw_supply (regcache, ARM_PS_REGNUM,
+ gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+ }
+
+ if (regnum == ARM_PC_REGNUM || regnum == -1)
+ {
+ reg_pc = extract_unsigned_integer (gregs
+ + INT_REGISTER_SIZE * ARM_PC_REGNUM,
+ INT_REGISTER_SIZE);
+ reg_pc = ADDR_BITS_REMOVE (reg_pc);
+ store_unsigned_integer (pc_buf, INT_REGISTER_SIZE, reg_pc);
+ regcache_raw_supply (regcache, ARM_PC_REGNUM, pc_buf);
+ }
+}
+
+void
+arm_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs_buf, size_t len)
+{
+ gdb_byte *gregs = gregs_buf;
+ int regno;
+
+ for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ regcache_raw_collect (regcache, regno,
+ gregs + INT_REGISTER_SIZE * regno);
+
+ if (regnum == ARM_PS_REGNUM || regnum == -1)
+ {
+ if (arm_apcs_32)
+ regcache_raw_collect (regcache, ARM_PS_REGNUM,
+ gregs + INT_REGISTER_SIZE * ARM_CPSR_REGNUM);
+ else
+ regcache_raw_collect (regcache, ARM_PS_REGNUM,
+ gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+ }
+
+ if (regnum == ARM_PC_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, ARM_PC_REGNUM,
+ gregs + INT_REGISTER_SIZE * ARM_PC_REGNUM);
+}
+
+/* Support for register format used by the NWFPE FPA emulator. */
+
+#define typeNone 0x00
+#define typeSingle 0x01
+#define typeDouble 0x02
+#define typeExtended 0x03
+
+void
+supply_nwfpe_register (struct regcache *regcache, int regno,
+ const gdb_byte *regs)
+{
+ const gdb_byte *reg_data;
+ gdb_byte reg_tag;
+ gdb_byte buf[FP_REGISTER_SIZE];
+
+ reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
+ reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
+ memset (buf, 0, FP_REGISTER_SIZE);
+
+ switch (reg_tag)
+ {
+ case typeSingle:
+ memcpy (buf, reg_data, 4);
+ break;
+ case typeDouble:
+ memcpy (buf, reg_data + 4, 4);
+ memcpy (buf + 4, reg_data, 4);
+ break;
+ case typeExtended:
+ /* We want sign and exponent, then least significant bits,
+ then most significant. NWFPE does sign, most, least. */
+ memcpy (buf, reg_data, 4);
+ memcpy (buf + 4, reg_data + 8, 4);
+ memcpy (buf + 8, reg_data + 4, 4);
+ break;
+ default:
+ break;
+ }
+
+ regcache_raw_supply (regcache, regno, buf);
+}
+
+void
+collect_nwfpe_register (const struct regcache *regcache, int regno,
+ gdb_byte *regs)
+{
+ gdb_byte *reg_data;
+ gdb_byte reg_tag;
+ gdb_byte buf[FP_REGISTER_SIZE];
+
+ regcache_raw_collect (regcache, regno, buf);
+
+ /* NOTE drow/2006-06-07: This code uses the tag already in the
+ register buffer. I've preserved that when moving the code
+ from the native file to the target file. But this doesn't
+ always make sense. */
+
+ reg_data = regs + (regno - ARM_F0_REGNUM) * FP_REGISTER_SIZE;
+ reg_tag = regs[(regno - ARM_F0_REGNUM) + NWFPE_TAGS_OFFSET];
+
+ switch (reg_tag)
+ {
+ case typeSingle:
+ memcpy (reg_data, buf, 4);
+ break;
+ case typeDouble:
+ memcpy (reg_data, buf + 4, 4);
+ memcpy (reg_data + 4, buf, 4);
+ break;
+ case typeExtended:
+ memcpy (reg_data, buf, 4);
+ memcpy (reg_data + 4, buf + 8, 4);
+ memcpy (reg_data + 8, buf + 4, 4);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+arm_linux_supply_nwfpe (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *regs_buf, size_t len)
+{
+ const gdb_byte *regs = regs_buf;
+ int regno;
+
+ if (regnum == ARM_FPS_REGNUM || regnum == -1)
+ regcache_raw_supply (regcache, ARM_FPS_REGNUM,
+ regs + NWFPE_FPSR_OFFSET);
+
+ for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ supply_nwfpe_register (regcache, regno, regs);
+}
+
+void
+arm_linux_collect_nwfpe (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *regs_buf, size_t len)
+{
+ gdb_byte *regs = regs_buf;
+ int regno;
+
+ for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
+ if (regnum == -1 || regnum == regno)
+ collect_nwfpe_register (regcache, regno, regs);
+
+ if (regnum == ARM_FPS_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, ARM_FPS_REGNUM,
+ regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM);
+}
+
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
+
+static const struct regset *
+arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name, size_t sect_size)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (strcmp (sect_name, ".reg") == 0
+ && sect_size == ARM_LINUX_SIZEOF_GREGSET)
+ {
+ if (tdep->gregset == NULL)
+ tdep->gregset = regset_alloc (gdbarch, arm_linux_supply_gregset,
+ arm_linux_collect_gregset);
+ return tdep->gregset;
+ }
+
+ if (strcmp (sect_name, ".reg2") == 0
+ && sect_size == ARM_LINUX_SIZEOF_NWFPE)
+ {
+ if (tdep->fpregset == NULL)
+ tdep->fpregset = regset_alloc (gdbarch, arm_linux_supply_nwfpe,
+ arm_linux_collect_nwfpe);
+ return tdep->fpregset;
+ }
+
+ return NULL;
+}
+
static void
arm_linux_init_abi (struct gdbarch_info info,
struct gdbarch *gdbarch)
&arm_eabi_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
&arm_eabi_linux_rt_sigreturn_tramp_frame);
+
+ /* Core file support. */
+ set_gdbarch_regset_from_core_section (gdbarch,
+ arm_linux_regset_from_core_section);
}
void
--- /dev/null
+/* GNU/Linux on ARM target support, prototypes.
+
+ Copyright (C) 2006
+ Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+struct regset;
+struct regcache;
+
+#define ARM_CPSR_REGNUM 16
+
+#define ARM_LINUX_SIZEOF_NWFPE (8 * FP_REGISTER_SIZE \
+ + 2 * INT_REGISTER_SIZE \
+ + 8 + INT_REGISTER_SIZE)
+
+/* Support for register format used by the NWFPE FPA emulator. Each
+ register takes three words, where either the first one, two, or
+ three hold a single, double, or extended precision value (depending
+ on the corresponding tag). The register set is eight registers,
+ followed by the fpsr and fpcr, followed by eight tag bytes, and a
+ final word flag which indicates whether NWFPE has been
+ initialized. */
+
+#define NWFPE_FPSR_OFFSET (8 * FP_REGISTER_SIZE)
+#define NWFPE_FPCR_OFFSET (NWFPE_FPSR_OFFSET + INT_REGISTER_SIZE)
+#define NWFPE_TAGS_OFFSET (NWFPE_FPCR_OFFSET + INT_REGISTER_SIZE)
+#define NWFPE_INITFLAG_OFFSET (NWFPE_TAGS_OFFSET + 8)
+
+void arm_linux_supply_gregset (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *gregs_buf, size_t len);
+void arm_linux_collect_gregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *gregs_buf, size_t len);
+
+void supply_nwfpe_register (struct regcache *regcache, int regno,
+ const gdb_byte *regs);
+void collect_nwfpe_register (const struct regcache *regcache, int regno,
+ gdb_byte *regs);
+
+void arm_linux_supply_nwfpe (const struct regset *regset,
+ struct regcache *regcache,
+ int regnum, const void *regs_buf, size_t len);
+void arm_linux_collect_nwfpe (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *regs_buf, size_t len);
Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
+/* Forward declarations. */
+struct regset;
+
/* Register numbers of various important registers. Note that some of
these values are "real" register numbers, and correspond to the
general registers of the machine, and some are "phony" register
If this is negative, longjmp support
will be disabled. */
size_t jb_elt_size; /* And the size of each entry in the buf. */
+
+ /* Cached core file helpers. */
+ struct regset *gregset, *fpregset;
};
#ifndef LOWEST_PC
# Host: ARM based machine running GNU/Linux
NAT_FILE= nm-linux.h
-NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \
- core-regset.o arm-linux-nat.o gcore.o \
+NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o gcore.o \
proc-service.o linux-thread-db.o linux-nat.o linux-fork.o
LOADLIBES= -ldl -rdynamic
# Target: ARM based machine running GNU/Linux
DEPRECATED_TM_FILE= tm-linux.h
-TDEPFILES= arm-tdep.o arm-linux-tdep.o glibc-tdep.o solib.o solib-svr4.o solib-legacy.o symfile-mem.o
+TDEPFILES= arm-tdep.o arm-linux-tdep.o glibc-tdep.o solib.o \
+ solib-svr4.o solib-legacy.o symfile-mem.o \
+ corelow.o
+