diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2011-06-15 16:39:28 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2011-06-15 16:39:28 +0000 |
commit | ef7e8358eca92b73e6f8df63ea5320809328d470 (patch) | |
tree | 08295fc95354af12ce48c0fa6ed837ee81ccb40d /gdb/arm-linux-tdep.c | |
parent | faa9a424ea76bdfd223e89b87f479297564a4e05 (diff) | |
download | gdb-ef7e8358eca92b73e6f8df63ea5320809328d470.zip gdb-ef7e8358eca92b73e6f8df63ea5320809328d470.tar.gz gdb-ef7e8358eca92b73e6f8df63ea5320809328d470.tar.bz2 |
* arm-linux-tdep.c: Include "auxv.h".
(AT_HWCAP): Define.
(ARM_LINUX_SIZEOF_VFP): Define.
(arm_linux_supply_vfp): New function.
(arm_linux_collect_vfp): Likewise.
(arm_linux_regset_from_core_section): Handle .reg-arm-vfp sections.
(arm_linux_fpa_regset_sections): New variable.
(arm_linux_vfp_regset_sections): Likewise.
(arm_linux_core_read_description): New function.
(arm_linux_init_abi): Install arm_linux_core_read_description and
arm_linux_fpa_regset_sections or arm_linux_vfp_regset_sections as
appropriate for the architecture.
* arm-tdep.h (struct gdbarch_tdep): Add member "vfpregset".
(tdesc_arm_with_m): Declare.
(tdesc_arm_with_iwmmxt): Likewise.
(tdesc_arm_with_vfpv2): Likewise.
(tdesc_arm_with_vfpv3): Likewise.
(tdesc_arm_with_neon): Likewise.
* arm-linux-nat.c: Move features/*.c includes ...
* arm-tdep.c: ... here.
* arm-linux-nat.c (arm_linux_read_description): Move initializing
target description data structures ...
* arm-tdep.c (_initialize_arm_tdep): ... here.
* arm-linux-nat.c (HWCAP_VFP, HWCAP_IWMMXT, HWCAP_NEON, HWCAP_VFPv3,
HWCAP_VFPv3D16): Move definitions ...
* arm-linux-tdep.h: ... here.
Diffstat (limited to 'gdb/arm-linux-tdep.c')
-rw-r--r-- | gdb/arm-linux-tdep.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index b7ff5ec..b5b56de 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -33,6 +33,7 @@ #include "trad-frame.h" #include "tramp-frame.h" #include "breakpoint.h" +#include "auxv.h" #include "arm-tdep.h" #include "arm-linux-tdep.h" @@ -45,6 +46,9 @@ #include "gdb_string.h" +/* This is defined in <elf.h> on ARM GNU/Linux systems. */ +#define AT_HWCAP 16 + extern int arm_apcs_32; /* Under ARM GNU/Linux the traditional way of performing a breakpoint @@ -638,6 +642,44 @@ arm_linux_collect_nwfpe (const struct regset *regset, regs + INT_REGISTER_SIZE * ARM_FPS_REGNUM); } +/* Support VFP register format. */ + +#define ARM_LINUX_SIZEOF_VFP (32 * 8 + 4) + +static void +arm_linux_supply_vfp (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_FPSCR_REGNUM || regnum == -1) + regcache_raw_supply (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache_raw_supply (regcache, regno, + regs + (regno - ARM_D0_REGNUM) * 8); +} + +static void +arm_linux_collect_vfp (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *regs_buf, size_t len) +{ + gdb_byte *regs = regs_buf; + int regno; + + if (regnum == ARM_FPSCR_REGNUM || regnum == -1) + regcache_raw_collect (regcache, ARM_FPSCR_REGNUM, regs + 32 * 8); + + for (regno = ARM_D0_REGNUM; regno <= ARM_D31_REGNUM; regno++) + if (regnum == -1 || regnum == regno) + regcache_raw_collect (regcache, regno, + regs + (regno - ARM_D0_REGNUM) * 8); +} + /* Return the appropriate register set for the core section identified by SECT_NAME and SECT_SIZE. */ @@ -665,9 +707,62 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch, return tdep->fpregset; } + if (strcmp (sect_name, ".reg-arm-vfp") == 0 + && sect_size == ARM_LINUX_SIZEOF_VFP) + { + if (tdep->vfpregset == NULL) + tdep->vfpregset = regset_alloc (gdbarch, arm_linux_supply_vfp, + arm_linux_collect_vfp); + return tdep->vfpregset; + } + + return NULL; +} + +/* Core file register set sections. */ + +static struct core_regset_section arm_linux_fpa_regset_sections[] = +{ + { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, + { ".reg2", ARM_LINUX_SIZEOF_NWFPE, "FPA floating-point" }, + { NULL, 0} +}; + +static struct core_regset_section arm_linux_vfp_regset_sections[] = +{ + { ".reg", ARM_LINUX_SIZEOF_GREGSET, "general-purpose" }, + { ".reg-arm-vfp", ARM_LINUX_SIZEOF_VFP, "VFP floating-point" }, + { NULL, 0} +}; + +/* Determine target description from core file. */ + +static const struct target_desc * +arm_linux_core_read_description (struct gdbarch *gdbarch, + struct target_ops *target, + bfd *abfd) +{ + CORE_ADDR arm_hwcap = 0; + + if (target_auxv_search (target, AT_HWCAP, &arm_hwcap) != 1) + return NULL; + + if (arm_hwcap & HWCAP_VFP) + { + /* NEON implies VFPv3-D32 or no-VFP unit. Say that we only support + Neon with VFPv3-D32. */ + if (arm_hwcap & HWCAP_NEON) + return tdesc_arm_with_neon; + else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3) + return tdesc_arm_with_vfpv3; + else + return tdesc_arm_with_vfpv2; + } + return NULL; } + /* Copy the value of next pc of sigreturn and rt_sigrturn into PC, return 1. In addition, set IS_THUMB depending on whether we will return to ARM or Thumb code. Return 0 if it is not a @@ -1036,6 +1131,12 @@ arm_linux_init_abi (struct gdbarch_info info, /* Core file support. */ set_gdbarch_regset_from_core_section (gdbarch, arm_linux_regset_from_core_section); + set_gdbarch_core_read_description (gdbarch, arm_linux_core_read_description); + + if (tdep->have_vfp_registers) + set_gdbarch_core_regset_sections (gdbarch, arm_linux_vfp_regset_sections); + else if (tdep->have_fpa_registers) + set_gdbarch_core_regset_sections (gdbarch, arm_linux_fpa_regset_sections); set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type); |