* arm-linux-tdep.c: Include "auxv.h".
authorUlrich Weigand <uweigand@de.ibm.com>
Wed, 15 Jun 2011 16:39:28 +0000 (16:39 +0000)
committerUlrich Weigand <uweigand@de.ibm.com>
Wed, 15 Jun 2011 16:39:28 +0000 (16:39 +0000)
(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.

gdb/ChangeLog
gdb/arm-linux-nat.c
gdb/arm-linux-tdep.c
gdb/arm-linux-tdep.h
gdb/arm-tdep.c
gdb/arm-tdep.h

index b40d0a6..ba1a501 100644 (file)
@@ -1,3 +1,32 @@
+2011-06-15  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+       * 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.
+
 2011-06-15  Hui Zhu  <teawater@gmail.com>
 
        * remote.c (remote_trace_set_readonly_regions): Add a check for
index 43f4fde..f64c37c 100644 (file)
 /* Defines ps_err_e, struct ps_prochandle.  */
 #include "gdb_proc_service.h"
 
-#include "features/arm-with-iwmmxt.c"
-#include "features/arm-with-vfpv2.c"
-#include "features/arm-with-vfpv3.c"
-#include "features/arm-with-neon.c"
-
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 22
 #endif
 #define PTRACE_SETHBPREGS 30
 #endif
 
-/* These are in <asm/elf.h> in current kernels.  */
-#define HWCAP_VFP       64
-#define HWCAP_IWMMXT    512
-#define HWCAP_NEON      4096
-#define HWCAP_VFPv3     8192
-#define HWCAP_VFPv3D16  16384
-
 /* A flag for whether the WMMX registers are available.  */
 static int arm_linux_has_wmmx_registers;
 
@@ -696,8 +684,6 @@ arm_linux_read_description (struct target_ops *ops)
   if (arm_hwcap & HWCAP_IWMMXT)
     {
       arm_linux_has_wmmx_registers = 1;
-      if (tdesc_arm_with_iwmmxt == NULL)
-       initialize_tdesc_arm_with_iwmmxt ();
       return tdesc_arm_with_iwmmxt;
     }
 
@@ -712,22 +698,16 @@ arm_linux_read_description (struct target_ops *ops)
       if (arm_hwcap & HWCAP_NEON)
        {
          arm_linux_vfp_register_count = 32;
-         if (tdesc_arm_with_neon == NULL)
-           initialize_tdesc_arm_with_neon ();
          result = tdesc_arm_with_neon;
        }
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
        {
          arm_linux_vfp_register_count = 32;
-         if (tdesc_arm_with_vfpv3 == NULL)
-           initialize_tdesc_arm_with_vfpv3 ();
          result = tdesc_arm_with_vfpv3;
        }
       else
        {
          arm_linux_vfp_register_count = 16;
-         if (tdesc_arm_with_vfpv2 == NULL)
-           initialize_tdesc_arm_with_vfpv2 ();
          result = tdesc_arm_with_vfpv2;
        }
 
index b7ff5ec..b5b56de 100644 (file)
@@ -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);
 
index 248994d..d967e43 100644 (file)
@@ -59,3 +59,12 @@ void arm_linux_supply_nwfpe (const struct regset *regset,
 void arm_linux_collect_nwfpe (const struct regset *regset,
                              const struct regcache *regcache,
                              int regnum, void *regs_buf, size_t len);
+
+/* ARM GNU/Linux HWCAP values.  These are in defined in
+   <asm/elf.h> in current kernels.  */
+#define HWCAP_VFP       64
+#define HWCAP_IWMMXT    512
+#define HWCAP_NEON      4096
+#define HWCAP_VFPv3     8192
+#define HWCAP_VFPv3D16  16384
+
index 2dd8c9e..433ce21 100644 (file)
 #include "vec.h"
 
 #include "features/arm-with-m.c"
+#include "features/arm-with-iwmmxt.c"
+#include "features/arm-with-vfpv2.c"
+#include "features/arm-with-vfpv3.c"
+#include "features/arm-with-neon.c"
 
 static int arm_debug;
 
@@ -8800,6 +8804,10 @@ _initialize_arm_tdep (void)
 
   /* Initialize the standard target descriptions.  */
   initialize_tdesc_arm_with_m ();
+  initialize_tdesc_arm_with_iwmmxt ();
+  initialize_tdesc_arm_with_vfpv2 ();
+  initialize_tdesc_arm_with_vfpv3 ();
+  initialize_tdesc_arm_with_neon ();
 
   /* Get the number of possible sets of register names defined in opcodes.  */
   num_disassembly_options = get_arm_regname_num_options ();
index fe27c7f..b6d44a2 100644 (file)
@@ -191,7 +191,7 @@ struct gdbarch_tdep
   enum struct_return struct_return;
 
   /* Cached core file helpers.  */
-  struct regset *gregset, *fpregset;
+  struct regset *gregset, *fpregset, *vfpregset;
 
   /* ISA-specific data types.  */
   struct type *arm_ext_type;
@@ -339,4 +339,11 @@ extern const struct regset *
   armbsd_regset_from_core_section (struct gdbarch *gdbarch,
                                   const char *sect_name, size_t sect_size);
 
+/* Target descriptions.  */
+extern struct target_desc *tdesc_arm_with_m;
+extern struct target_desc *tdesc_arm_with_iwmmxt;
+extern struct target_desc *tdesc_arm_with_vfpv2;
+extern struct target_desc *tdesc_arm_with_vfpv3;
+extern struct target_desc *tdesc_arm_with_neon;
+
 #endif /* arm-tdep.h */