* NEWS: Mention ARM VFP support.
authorDaniel Jacobowitz <drow@false.org>
Tue, 28 Jul 2009 18:26:51 +0000 (18:26 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 28 Jul 2009 18:26:51 +0000 (18:26 +0000)
* target-descriptions.c (tdesc_register_type): Make public.
(tdesc_unnumbered_register): New function.
(tdesc_register_reggroup_p): Allow missing
pseudo_register_reggroup_p.
* target-descriptions.h (tdesc_register_type): Declare.
(tdesc_unnumbered_register): Declare.
* arm-tdep.c (arm_neon_quad_read, arm_neon_quad_write): New functions.
(arm_push_dummy_call): Use arm_neon_quad_write.
(arm_neon_double_type, arm_neon_quad_type): New functions.
(arm_register_type): Handle VFP and NEON registers.  Override the
types of double-precision registers for NEON.  Disable FPA registers
if they are not present.
(arm_dwarf_reg_to_regnum): Add current VFP and NEON register numbers.
(arm_return_value): Use arm_neon_quad_write and arm_neon_quad_read.
(arm_register_name): Handle VFP single and NEON quad registers.
(arm_pseudo_read, arm_pseudo_write): New functions.
(arm_gdbarch_init): Check for VFP and NEON in the target description.
Assign numbers to double-precision registers.  Register VFP and NEON
pseudo registers.  Remove a shadowed "i" variable.
* arm-tdep.h (enum gdb_regnum): Add ARM_D0_REGNUM and
ARM_D31_REGNUM.
(struct gdbarch_tdep): Add have_neon_pseudos, have_neon,
have_vfp_registers, have_vfp_pseudos, neon_double_type,
and neon_quad_type.

* features/Makefile: Make expedite settings only architecture
specific.
(WHICH): Add new ARM descriptions.
* features/arm-with-neon.xml, features/arm-with-vfpv2.c,
features/arm-with-vfpv3.c, features/arm-vfpv2.xml,
features/arm-vfpv3.xml, features/arm-with-vfpv2.xml,
features/arm-with-vfpv3.xml, features/arm-with-neon.c: New files.
* regformats/arm-with-neon.dat, regformats/arm-with-vfpv2.dat,
regformats/arm-with-vfpv3.dat: Generate.

doc/
* gdb.texinfo (ARM Features): Document org.gnu.gdb.arm.vfp and
org.gnu.gdb.arm.neon.

gdbserver/
* linux-low.c (linux_write_memory): Update debugging output.
* Makefile.in (clean): Add new descriptions.
(arm-with-vfpv2.o, arm-with-vfpv2.c, arm-with-vfpv3.o)
(arm-with-vfpv3.c, arm-with-neon.o, arm-with-neon.c): New rules.
* configure.srv: Add new files for arm*-*-linux*.
* linux-arm-low.c: Add new declarations.
(PTRACE_GETVFPREGS, PTRACE_SETVFPREGS): Define if undefined.
(arm_hwcap, HWCAP_VFP, HWCAP_IWMMXT, HWCAP_NEON, HWCAP_VFPv3)
(HWCAP_VFPv3D16): New.
(arm_fill_wmmxregset, arm_store_wmmxregset): Check HWCAP_IWMMXT
instead of __IWMMXT__.
(arm_fill_vfpregset, arm_store_vfpregset, arm_get_hwcap)
(arm_arch_setup): New.
(target_regsets): Remove #ifdef.  Add VFP regset.
(the_low_target): Use arm_arch_setup.

testsuite/
* gdb.base/float.exp: Handle VFP registers.

27 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/arm-tdep.c
gdb/arm-tdep.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/features/Makefile
gdb/features/arm-vfpv2.xml [new file with mode: 0644]
gdb/features/arm-vfpv3.xml [new file with mode: 0644]
gdb/features/arm-with-neon.c [new file with mode: 0644]
gdb/features/arm-with-neon.xml [new file with mode: 0644]
gdb/features/arm-with-vfpv2.c [new file with mode: 0644]
gdb/features/arm-with-vfpv2.xml [new file with mode: 0644]
gdb/features/arm-with-vfpv3.c [new file with mode: 0644]
gdb/features/arm-with-vfpv3.xml [new file with mode: 0644]
gdb/gdbserver/ChangeLog
gdb/gdbserver/Makefile.in
gdb/gdbserver/configure.srv
gdb/gdbserver/linux-arm-low.c
gdb/gdbserver/linux-low.c
gdb/regformats/arm-with-neon.dat [new file with mode: 0644]
gdb/regformats/arm-with-vfpv2.dat [new file with mode: 0644]
gdb/regformats/arm-with-vfpv3.dat [new file with mode: 0644]
gdb/target-descriptions.c
gdb/target-descriptions.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/float.exp

index 019d4416dc5f40a03a174433655e372a73274870..1beccaab0b0f3b42026321960bf6704012d7d0ca 100644 (file)
@@ -1,3 +1,41 @@
+2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * NEWS: Mention ARM VFP support.
+       * target-descriptions.c (tdesc_register_type): Make public.
+       (tdesc_unnumbered_register): New function.
+       (tdesc_register_reggroup_p): Allow missing
+       pseudo_register_reggroup_p.
+       * target-descriptions.h (tdesc_register_type): Declare.
+       (tdesc_unnumbered_register): Declare.
+       * arm-tdep.c (arm_neon_quad_read, arm_neon_quad_write): New functions.
+       (arm_push_dummy_call): Use arm_neon_quad_write.
+       (arm_neon_double_type, arm_neon_quad_type): New functions.
+       (arm_register_type): Handle VFP and NEON registers.  Override the
+       types of double-precision registers for NEON.  Disable FPA registers
+       if they are not present.
+       (arm_dwarf_reg_to_regnum): Add current VFP and NEON register numbers.
+       (arm_return_value): Use arm_neon_quad_write and arm_neon_quad_read.
+       (arm_register_name): Handle VFP single and NEON quad registers.
+       (arm_pseudo_read, arm_pseudo_write): New functions.
+       (arm_gdbarch_init): Check for VFP and NEON in the target description.
+       Assign numbers to double-precision registers.  Register VFP and NEON
+       pseudo registers.  Remove a shadowed "i" variable.
+       * arm-tdep.h (enum gdb_regnum): Add ARM_D0_REGNUM and
+       ARM_D31_REGNUM.
+       (struct gdbarch_tdep): Add have_neon_pseudos, have_neon,
+       have_vfp_registers, have_vfp_pseudos, neon_double_type,
+       and neon_quad_type.
+
+       * features/Makefile: Make expedite settings only architecture
+       specific.
+       (WHICH): Add new ARM descriptions.
+       * features/arm-with-neon.xml, features/arm-with-vfpv2.c,
+       features/arm-with-vfpv3.c, features/arm-vfpv2.xml,
+       features/arm-vfpv3.xml, features/arm-with-vfpv2.xml,
+       features/arm-with-vfpv3.xml, features/arm-with-neon.c: New files.
+       * regformats/arm-with-neon.dat, regformats/arm-with-vfpv2.dat,
+       regformats/arm-with-vfpv3.dat: Generate.
+
 2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * infrun.c (handle_inferior_event): Clear trap_expected after
index 7dcc8fc7d3fffdd9e63cf8093c175b3b0ddd7c7b..1e359a0c05c5decfcd919f1079f522ae0a1b3df2 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -64,8 +64,13 @@ operators when expanding macros.  It also supports variable-arity
 macros.
 
 * GDB now supports inspecting extra signal information, exported by
-  the new $_siginfo convenience variable.  The feature is currently
-  implemented on linux ARM, i386 and amd64.
+the new $_siginfo convenience variable.  The feature is currently
+implemented on linux ARM, i386 and amd64.
+
+* GDB can now display the VFP floating point registers and NEON vector
+registers on ARM targets.  Both ARM GNU/Linux native GDB and gdbserver
+can provide these registers (requires Linux 2.6.30 or later).  Remote
+and simulator targets may also provide them.
 
 * New remote packets
 
index 733318d1d907b66759490a8d2202d677800b245e..3cc8d016a5fbb2c1f85c1740479c4e54b3b0cb90 100644 (file)
@@ -208,6 +208,13 @@ static void convert_from_extended (const struct floatformat *, const void *,
 static void convert_to_extended (const struct floatformat *, void *,
                                 const void *, int);
 
+static void arm_neon_quad_read (struct gdbarch *gdbarch,
+                               struct regcache *regcache,
+                               int regnum, gdb_byte *buf);
+static void arm_neon_quad_write (struct gdbarch *gdbarch,
+                                struct regcache *regcache,
+                                int regnum, const gdb_byte *buf);
+
 struct arm_prologue_cache
 {
   /* The stack pointer at the time this frame was created; i.e. the
@@ -1709,11 +1716,17 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                {
                  char name_buf[4];
                  int regnum;
-                 sprintf (name_buf, "%c%d", reg_char, reg_scaled + i);
-                 regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
-                                                       strlen (name_buf));
-                 regcache_cooked_write (regcache, regnum,
+                 if (reg_char == 'q')
+                   arm_neon_quad_write (gdbarch, regcache, reg_scaled + i,
                                         val + i * unit_length);
+                 else
+                   {
+                     sprintf (name_buf, "%c%d", reg_char, reg_scaled + i);
+                     regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                                           strlen (name_buf));
+                     regcache_cooked_write (regcache, regnum,
+                                            val + i * unit_length);
+                   }
                }
              continue;
            }
@@ -1874,14 +1887,115 @@ arm_ext_type (struct gdbarch *gdbarch)
   return tdep->arm_ext_type;
 }
 
+static struct type *
+arm_neon_double_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->neon_double_type == NULL)
+    {
+      struct type *t, *elem;
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_neon_d",
+                              TYPE_CODE_UNION);
+      elem = builtin_type (gdbarch)->builtin_uint8;
+      append_composite_type_field (t, "u8", init_vector_type (elem, 8));
+      elem = builtin_type (gdbarch)->builtin_uint16;
+      append_composite_type_field (t, "u16", init_vector_type (elem, 4));
+      elem = builtin_type (gdbarch)->builtin_uint32;
+      append_composite_type_field (t, "u32", init_vector_type (elem, 2));
+      elem = builtin_type (gdbarch)->builtin_uint64;
+      append_composite_type_field (t, "u64", elem);
+      elem = builtin_type (gdbarch)->builtin_float;
+      append_composite_type_field (t, "f32", init_vector_type (elem, 2));
+      elem = builtin_type (gdbarch)->builtin_double;
+      append_composite_type_field (t, "f64", elem);
+
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "neon_d";
+      tdep->neon_double_type = t;
+    }
+
+  return tdep->neon_double_type;
+}
+
+/* FIXME: The vector types are not correctly ordered on big-endian
+   targets.  Just as s0 is the low bits of d0, d0[0] is also the low
+   bits of d0 - regardless of what unit size is being held in d0.  So
+   the offset of the first uint8 in d0 is 7, but the offset of the
+   first float is 4.  This code works as-is for little-endian
+   targets.  */
+
+static struct type *
+arm_neon_quad_type (struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  if (tdep->neon_quad_type == NULL)
+    {
+      struct type *t, *elem;
+
+      t = arch_composite_type (gdbarch, "__gdb_builtin_type_neon_q",
+                              TYPE_CODE_UNION);
+      elem = builtin_type (gdbarch)->builtin_uint8;
+      append_composite_type_field (t, "u8", init_vector_type (elem, 16));
+      elem = builtin_type (gdbarch)->builtin_uint16;
+      append_composite_type_field (t, "u16", init_vector_type (elem, 8));
+      elem = builtin_type (gdbarch)->builtin_uint32;
+      append_composite_type_field (t, "u32", init_vector_type (elem, 4));
+      elem = builtin_type (gdbarch)->builtin_uint64;
+      append_composite_type_field (t, "u64", init_vector_type (elem, 2));
+      elem = builtin_type (gdbarch)->builtin_float;
+      append_composite_type_field (t, "f32", init_vector_type (elem, 4));
+      elem = builtin_type (gdbarch)->builtin_double;
+      append_composite_type_field (t, "f64", init_vector_type (elem, 2));
+
+      TYPE_VECTOR (t) = 1;
+      TYPE_NAME (t) = "neon_q";
+      tdep->neon_quad_type = t;
+    }
+
+  return tdep->neon_quad_type;
+}
+
 /* Return the GDB type object for the "standard" data type of data in
    register N.  */
 
 static struct type *
 arm_register_type (struct gdbarch *gdbarch, int regnum)
 {
+  int num_regs = gdbarch_num_regs (gdbarch);
+
+  if (gdbarch_tdep (gdbarch)->have_vfp_pseudos
+      && regnum >= num_regs && regnum < num_regs + 32)
+    return builtin_type (gdbarch)->builtin_float;
+
+  if (gdbarch_tdep (gdbarch)->have_neon_pseudos
+      && regnum >= num_regs + 32 && regnum < num_regs + 32 + 16)
+    return arm_neon_quad_type (gdbarch);
+
+  /* If the target description has register information, we are only
+     in this function so that we can override the types of
+     double-precision registers for NEON.  */
+  if (tdesc_has_registers (gdbarch_target_desc (gdbarch)))
+    {
+      struct type *t = tdesc_register_type (gdbarch, regnum);
+
+      if (regnum >= ARM_D0_REGNUM && regnum < ARM_D0_REGNUM + 32
+         && TYPE_CODE (t) == TYPE_CODE_FLT
+         && gdbarch_tdep (gdbarch)->have_neon)
+       return arm_neon_double_type (gdbarch);
+      else
+       return t;
+    }
+
   if (regnum >= ARM_F0_REGNUM && regnum < ARM_F0_REGNUM + NUM_FREGS)
-    return arm_ext_type (gdbarch);
+    {
+      if (!gdbarch_tdep (gdbarch)->have_fpa_registers)
+       return builtin_type (gdbarch)->builtin_void;
+
+      return arm_ext_type (gdbarch);
+    }
   else if (regnum == ARM_SP_REGNUM)
     return builtin_type (gdbarch)->builtin_data_ptr;
   else if (regnum == ARM_PC_REGNUM)
@@ -1925,6 +2039,34 @@ arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
   if (reg >= 192 && reg <= 199)
     return ARM_WC0_REGNUM + reg - 192;
 
+  /* VFP v2 registers.  A double precision value is actually
+     in d1 rather than s2, but the ABI only defines numbering
+     for the single precision registers.  This will "just work"
+     in GDB for little endian targets (we'll read eight bytes,
+     starting in s0 and then progressing to s1), but will be
+     reversed on big endian targets with VFP.  This won't
+     be a problem for the new Neon quad registers; you're supposed
+     to use DW_OP_piece for those.  */
+  if (reg >= 64 && reg <= 95)
+    {
+      char name_buf[4];
+
+      sprintf (name_buf, "s%d", reg - 64);
+      return user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                         strlen (name_buf));
+    }
+
+  /* VFP v3 / Neon registers.  This range is also used for VFP v2
+     registers, except that it now describes d0 instead of s0.  */
+  if (reg >= 256 && reg <= 287)
+    {
+      char name_buf[4];
+
+      sprintf (name_buf, "d%d", reg - 256);
+      return user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                         strlen (name_buf));
+    }
+
   return -1;
 }
 
@@ -2874,17 +3016,31 @@ arm_return_value (struct gdbarch *gdbarch, struct type *func_type,
       int i;
       for (i = 0; i < vfp_base_count; i++)
        {
-         char name_buf[4];
-         int regnum;
-         sprintf (name_buf, "%c%d", reg_char, i);
-         regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
-                                               strlen (name_buf));
-         if (writebuf)
-           regcache_cooked_write (regcache, regnum,
-                                  writebuf + i * unit_length);
-         if (readbuf)
-           regcache_cooked_read (regcache, regnum,
-                                 readbuf + i * unit_length);
+         if (reg_char == 'q')
+           {
+             if (writebuf)
+               arm_neon_quad_write (gdbarch, regcache, i,
+                                    writebuf + i * unit_length);
+
+             if (readbuf)
+               arm_neon_quad_read (gdbarch, regcache, i,
+                                   readbuf + i * unit_length);
+           }
+         else
+           {
+             char name_buf[4];
+             int regnum;
+
+             sprintf (name_buf, "%c%d", reg_char, i);
+             regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                                   strlen (name_buf));
+             if (writebuf)
+               regcache_cooked_write (regcache, regnum,
+                                      writebuf + i * unit_length);
+             if (readbuf)
+               regcache_cooked_read (regcache, regnum,
+                                     readbuf + i * unit_length);
+           }
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
@@ -3141,6 +3297,32 @@ set_disassembly_style_sfunc (char *args, int from_tty,
 static const char *
 arm_register_name (struct gdbarch *gdbarch, int i)
 {
+  const int num_regs = gdbarch_num_regs (gdbarch);
+
+  if (gdbarch_tdep (gdbarch)->have_vfp_pseudos
+      && i >= num_regs && i < num_regs + 32)
+    {
+      static const char *const vfp_pseudo_names[] = {
+       "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
+       "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15",
+       "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23",
+       "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
+      };
+
+      return vfp_pseudo_names[i - num_regs];
+    }
+
+  if (gdbarch_tdep (gdbarch)->have_neon_pseudos
+      && i >= num_regs + 32 && i < num_regs + 32 + 16)
+    {
+      static const char *const neon_pseudo_names[] = {
+       "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7",
+       "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15",
+      };
+
+      return neon_pseudo_names[i - num_regs - 32];
+    }
+
   if (i >= ARRAY_SIZE (arm_register_names))
     /* These registers are only supported on targets which supply
        an XML description.  */
@@ -3278,6 +3460,140 @@ arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
     }
 }
 
+/* Read the contents of a NEON quad register, by reading from two
+   double registers.  This is used to implement the quad pseudo
+   registers, and for argument passing in case the quad registers are
+   missing; vectors are passed in quad registers when using the VFP
+   ABI, even if a NEON unit is not present.  REGNUM is the index of
+   the quad register, in [0, 15].  */
+
+static void
+arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                   int regnum, gdb_byte *buf)
+{
+  char name_buf[4];
+  gdb_byte reg_buf[8];
+  int offset, double_regnum;
+
+  sprintf (name_buf, "d%d", regnum << 1);
+  double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                              strlen (name_buf));
+
+  /* d0 is always the least significant half of q0.  */
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    offset = 8;
+  else
+    offset = 0;
+
+  regcache_raw_read (regcache, double_regnum, reg_buf);
+  memcpy (buf + offset, reg_buf, 8);
+
+  offset = 8 - offset;
+  regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+  memcpy (buf + offset, reg_buf, 8);
+}
+
+static void
+arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
+                int regnum, gdb_byte *buf)
+{
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  char name_buf[4];
+  gdb_byte reg_buf[8];
+  int offset, double_regnum;
+
+  gdb_assert (regnum >= num_regs);
+  regnum -= num_regs;
+
+  if (gdbarch_tdep (gdbarch)->have_neon_pseudos && regnum >= 32 && regnum < 48)
+    /* Quad-precision register.  */
+    arm_neon_quad_read (gdbarch, regcache, regnum - 32, buf);
+  else
+    {
+      /* Single-precision register.  */
+      gdb_assert (regnum < 32);
+
+      /* s0 is always the least significant half of d0.  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       offset = (regnum & 1) ? 0 : 4;
+      else
+       offset = (regnum & 1) ? 4 : 0;
+
+      sprintf (name_buf, "d%d", regnum >> 1);
+      double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                                  strlen (name_buf));
+
+      regcache_raw_read (regcache, double_regnum, reg_buf);
+      memcpy (buf, reg_buf + offset, 4);
+    }
+}
+
+/* Store the contents of BUF to a NEON quad register, by writing to
+   two double registers.  This is used to implement the quad pseudo
+   registers, and for argument passing in case the quad registers are
+   missing; vectors are passed in quad registers when using the VFP
+   ABI, even if a NEON unit is not present.  REGNUM is the index
+   of the quad register, in [0, 15].  */
+
+static void
+arm_neon_quad_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                    int regnum, const gdb_byte *buf)
+{
+  char name_buf[4];
+  gdb_byte reg_buf[8];
+  int offset, double_regnum;
+
+  sprintf (name_buf, "d%d", regnum << 1);
+  double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                              strlen (name_buf));
+
+  /* d0 is always the least significant half of q0.  */
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    offset = 8;
+  else
+    offset = 0;
+
+  regcache_raw_write (regcache, double_regnum, buf + offset);
+  offset = 8 - offset;
+  regcache_raw_write (regcache, double_regnum + 1, buf + offset);
+}
+
+static void
+arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
+                 int regnum, const gdb_byte *buf)
+{
+  const int num_regs = gdbarch_num_regs (gdbarch);
+  char name_buf[4];
+  gdb_byte reg_buf[8];
+  int offset, double_regnum;
+
+  gdb_assert (regnum >= num_regs);
+  regnum -= num_regs;
+
+  if (gdbarch_tdep (gdbarch)->have_neon_pseudos && regnum >= 32 && regnum < 48)
+    /* Quad-precision register.  */
+    arm_neon_quad_write (gdbarch, regcache, regnum - 32, buf);
+  else
+    {
+      /* Single-precision register.  */
+      gdb_assert (regnum < 32);
+
+      /* s0 is always the least significant half of d0.  */
+      if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+       offset = (regnum & 1) ? 0 : 4;
+      else
+       offset = (regnum & 1) ? 4 : 0;
+
+      sprintf (name_buf, "d%d", regnum >> 1);
+      double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
+                                                  strlen (name_buf));
+
+      regcache_raw_read (regcache, double_regnum, reg_buf);
+      memcpy (reg_buf + offset, buf, 4);
+      regcache_raw_write (regcache, double_regnum, reg_buf);
+    }
+}
+
 static struct value *
 value_of_arm_user_reg (struct frame_info *frame, const void *baton)
 {
@@ -3322,6 +3638,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum arm_float_model fp_model = arm_fp_model;
   struct tdesc_arch_data *tdesc_data = NULL;
   int i;
+  int have_vfp_registers = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
+  int have_neon = 0;
   int have_fpa_registers = 1;
 
   /* Check any target description for validity.  */
@@ -3334,7 +3652,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       static const char *const arm_pc_names[] = { "r15", "pc", NULL };
 
       const struct tdesc_feature *feature;
-      int i, valid_p;
+      int valid_p;
 
       feature = tdesc_find_feature (info.target_desc,
                                    "org.gnu.gdb.arm.core");
@@ -3416,6 +3734,67 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
              return NULL;
            }
        }
+
+      /* If we have a VFP unit, check whether the single precision registers
+        are present.  If not, then we will synthesize them as pseudo
+        registers.  */
+      feature = tdesc_find_feature (info.target_desc,
+                                   "org.gnu.gdb.arm.vfp");
+      if (feature != NULL)
+       {
+         static const char *const vfp_double_names[] = {
+           "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+           "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15",
+           "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+           "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
+         };
+
+         /* Require the double precision registers.  There must be either
+            16 or 32.  */
+         valid_p = 1;
+         for (i = 0; i < 32; i++)
+           {
+             valid_p &= tdesc_numbered_register (feature, tdesc_data,
+                                                 ARM_D0_REGNUM + i,
+                                                 vfp_double_names[i]);
+             if (!valid_p)
+               break;
+           }
+
+         if (!valid_p && i != 16)
+           {
+             tdesc_data_cleanup (tdesc_data);
+             return NULL;
+           }
+
+         if (tdesc_unnumbered_register (feature, "s0") == 0)
+           have_vfp_pseudos = 1;
+
+         have_vfp_registers = 1;
+
+         /* If we have VFP, also check for NEON.  The architecture allows
+            NEON without VFP (integer vector operations only), but GDB
+            does not support that.  */
+         feature = tdesc_find_feature (info.target_desc,
+                                       "org.gnu.gdb.arm.neon");
+         if (feature != NULL)
+           {
+             /* NEON requires 32 double-precision registers.  */
+             if (i != 32)
+               {
+                 tdesc_data_cleanup (tdesc_data);
+                 return NULL;
+               }
+
+             /* If there are quad registers defined by the stub, use
+                their type; otherwise (normally) provide them with
+                the default type.  */
+             if (tdesc_unnumbered_register (feature, "q0") == 0)
+               have_neon_pseudos = 1;
+
+             have_neon = 1;
+           }
+       }
     }
 
   /* If we have an object to base this architecture on, try to determine
@@ -3559,6 +3938,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          && fp_model != gdbarch_tdep (best_arch->gdbarch)->fp_model)
        continue;
 
+      /* There are various other properties in tdep that we do not
+        need to check here: those derived from a target description,
+        since gdbarches with a different target description are
+        automatically disqualified.  */
+
       /* Found a match.  */
       break;
     }
@@ -3578,6 +3962,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->arm_abi = arm_abi;
   tdep->fp_model = fp_model;
   tdep->have_fpa_registers = have_fpa_registers;
+  tdep->have_vfp_registers = have_vfp_registers;
+  tdep->have_vfp_pseudos = have_vfp_pseudos;
+  tdep->have_neon_pseudos = have_neon_pseudos;
+  tdep->have_neon = have_neon;
 
   /* Breakpoints.  */
   switch (info.byte_order_for_code)
@@ -3717,8 +4105,30 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
     }
 
+  if (have_vfp_pseudos)
+    {
+      /* NOTE: These are the only pseudo registers used by
+        the ARM target at the moment.  If more are added, a
+        little more care in numbering will be needed.  */
+
+      int num_pseudos = 32;
+      if (have_neon_pseudos)
+       num_pseudos += 16;
+      set_gdbarch_num_pseudo_regs (gdbarch, num_pseudos);
+      set_gdbarch_pseudo_register_read (gdbarch, arm_pseudo_read);
+      set_gdbarch_pseudo_register_write (gdbarch, arm_pseudo_write);
+    }
+
   if (tdesc_data)
-    tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
+    {
+      set_tdesc_pseudo_register_name (gdbarch, arm_register_name);
+
+      tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
+
+      /* Override tdesc_register_type to adjust the types of VFP
+        registers for NEON.  */
+      set_gdbarch_register_type (gdbarch, arm_register_type);
+    }
 
   /* Add standard register aliases.  We add aliases even for those
      nanes which are used by the current architecture - it's simpler,
index 9af94ceb23a686a7ad997b07fd43cccb87e6d7d9..968c4f28df1ff495460c9fb283e4a123641789c9 100644 (file)
@@ -47,6 +47,8 @@ enum gdb_regnum {
   ARM_WCGR0_REGNUM,            /* WMMX general purpose registers.  */
   ARM_WCGR3_REGNUM = ARM_WCGR0_REGNUM + 3,
   ARM_WCGR7_REGNUM = ARM_WCGR0_REGNUM + 7,
+  ARM_D0_REGNUM,               /* VFP double-precision registers.  */
+  ARM_D31_REGNUM = ARM_D0_REGNUM + 31,
 
   ARM_NUM_REGS,
 
@@ -151,6 +153,13 @@ struct gdbarch_tdep
   enum arm_float_model fp_model; /* Floating point calling conventions.  */
 
   int have_fpa_registers;      /* Does the target report the FPA registers?  */
+  int have_vfp_registers;      /* Does the target report the VFP registers?  */
+  int have_vfp_pseudos;                /* Are we synthesizing the single precision
+                                  VFP registers?  */
+  int have_neon_pseudos;       /* Are we synthesizing the quad precision
+                                  NEON registers?  Requires
+                                  have_vfp_pseudos.  */
+  int have_neon;               /* Do we have a NEON unit?  */
 
   CORE_ADDR lowest_pc;         /* Lowest address at which instructions 
                                   will appear.  */
@@ -173,6 +182,8 @@ struct gdbarch_tdep
 
   /* ISA-specific data types.  */
   struct type *arm_ext_type;
+  struct type *neon_double_type;
+  struct type *neon_quad_type;
 };
 
 
index c0279a7c376c9e69af8f116a6747d883cc73abee..a544bc1f8fe8c277c3f1a3ad90e9e9855d1180f7 100644 (file)
@@ -1,3 +1,8 @@
+2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.texinfo (ARM Features): Document org.gnu.gdb.arm.vfp and
+       org.gnu.gdb.arm.neon.
+
 2009-07-20  Pedro Alves  <pedro@codesourcery.com>
 
        * gdb.texinfo (Target Description Format): Mention the new <osabi>
index c3693fae702632e5573ec385c068f09ce9f6446b..3bb35b60117fe8860ae2af49b992072191fefd1f 100644 (file)
@@ -31092,6 +31092,19 @@ it should contain at least registers @samp{wR0} through @samp{wR15} and
 @samp{wCGR0} through @samp{wCGR3}.  The @samp{wCID}, @samp{wCon},
 @samp{wCSSF}, and @samp{wCASF} registers are optional.
 
+The @samp{org.gnu.gdb.arm.vfp} feature is optional.  If present, it
+should contain at least registers @samp{d0} through @samp{d15}.  If
+they are present, @samp{d16} through @samp{d31} should also be included.
+@value{GDBN} will synthesize the single-precision registers from
+halves of the double-precision registers.
+
+The @samp{org.gnu.gdb.arm.neon} feature is optional.  It does not
+need to contain registers; it instructs @value{GDBN} to display the
+VFP double-precision registers as vectors and to synthesize the
+quad-precision registers from pairs of double-precision registers.
+If this feature is present, @samp{org.gnu.gdb.arm.vfp} must also
+be present and include 32 double-precision registers.
+
 @node MIPS Features
 @subsection MIPS Features
 @cindex target descriptions, MIPS features
index d70f15427db7935d7849a8bcd9f51df3d8f1485b..0a0a9b21b9006344f2657f27f1b39a561426bf1e 100644 (file)
 # in the GDB repository.  To generate C files:
 #   make GDB=/path/to/gdb XMLTOC="xml files" cfiles
 
-WHICH = arm-with-iwmmxt mips-linux mips64-linux \
+WHICH = arm-with-iwmmxt arm-with-vfpv2 arm-with-vfpv3 arm-with-neon \
+       mips-linux mips64-linux \
        rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
        rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \
        rs6000/powerpc-vsx64l
 
 # Record which registers should be sent to GDB by default after stop.
-arm-with-iwmmxt-expedite = r11,sp,pc
-mips-linux-expedite = r29,pc
-mips64-linux-expedite = r29,pc
-rs6000/powerpc-32l-expedite = r1,pc
-rs6000/powerpc-altivec32l-expedite = r1,pc
-rs6000/powerpc-vsx32l-expedite = r1,pc
-rs6000/powerpc-isa205-32l-expedite = r1,pc
-rs6000/powerpc-isa205-altivec32l-expedite = r1,pc
-rs6000/powerpc-isa205-vsx32l-expedite = r1,pc
-rs6000/powerpc-e500l-expedite = r1,pc
-rs6000/powerpc-64l-expedite = r1,pc
-rs6000/powerpc-altivec64l-expedite = r1,pc
-rs6000/powerpc-vsx64l-expedite = r1,pc
-rs6000/powerpc-isa205-64l-expedite = r1,pc
-rs6000/powerpc-isa205-altivec64l-expedite = r1,pc
-rs6000/powerpc-isa205-vsx64l-expedite = r1,pc
+arm-expedite = r11,sp,pc
+mips-expedite = r29,pc
+mips64-expedite = r29,pc
+powerpc-expedite = r1,pc
 
 
 XSLTPROC = xsltproc
@@ -69,7 +58,7 @@ $(outdir)/%.dat: %.xml number-regs.xsl sort-regs.xsl gdbserver-regs.xsl
        echo "# DO NOT EDIT: generated from $<" > $(outdir)/$*.tmp
        echo "name:`echo $(notdir $*) | sed 's/-/_/g'`" >> $(outdir)/$*.tmp
        echo "xmltarget:$(<F)" >> $(outdir)/$*.tmp
-       echo "expedite:$($*-expedite)" >> $(outdir)/$*.tmp
+       echo "expedite:$($(firstword $(subst -, ,$(notdir $*)))-expedite)" >> $(outdir)/$*.tmp
        $(XSLTPROC) --path "$(PWD)" --xinclude number-regs.xsl $< | \
          $(XSLTPROC) sort-regs.xsl - | \
          $(XSLTPROC) gdbserver-regs.xsl - >> $(outdir)/$*.tmp
diff --git a/gdb/features/arm-vfpv2.xml b/gdb/features/arm-vfpv2.xml
new file mode 100644 (file)
index 0000000..4c1d25d
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arm.vfp">
+  <reg name="d0" bitsize="64" type="ieee_double"/>
+  <reg name="d1" bitsize="64" type="ieee_double"/>
+  <reg name="d2" bitsize="64" type="ieee_double"/>
+  <reg name="d3" bitsize="64" type="ieee_double"/>
+  <reg name="d4" bitsize="64" type="ieee_double"/>
+  <reg name="d5" bitsize="64" type="ieee_double"/>
+  <reg name="d6" bitsize="64" type="ieee_double"/>
+  <reg name="d7" bitsize="64" type="ieee_double"/>
+  <reg name="d8" bitsize="64" type="ieee_double"/>
+  <reg name="d9" bitsize="64" type="ieee_double"/>
+  <reg name="d10" bitsize="64" type="ieee_double"/>
+  <reg name="d11" bitsize="64" type="ieee_double"/>
+  <reg name="d12" bitsize="64" type="ieee_double"/>
+  <reg name="d13" bitsize="64" type="ieee_double"/>
+  <reg name="d14" bitsize="64" type="ieee_double"/>
+  <reg name="d15" bitsize="64" type="ieee_double"/>
+
+  <reg name="fpscr" bitsize="32" type="int" group="float"/>
+</feature>
diff --git a/gdb/features/arm-vfpv3.xml b/gdb/features/arm-vfpv3.xml
new file mode 100644 (file)
index 0000000..80433d1
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.arm.vfp">
+  <reg name="d0" bitsize="64" type="ieee_double"/>
+  <reg name="d1" bitsize="64" type="ieee_double"/>
+  <reg name="d2" bitsize="64" type="ieee_double"/>
+  <reg name="d3" bitsize="64" type="ieee_double"/>
+  <reg name="d4" bitsize="64" type="ieee_double"/>
+  <reg name="d5" bitsize="64" type="ieee_double"/>
+  <reg name="d6" bitsize="64" type="ieee_double"/>
+  <reg name="d7" bitsize="64" type="ieee_double"/>
+  <reg name="d8" bitsize="64" type="ieee_double"/>
+  <reg name="d9" bitsize="64" type="ieee_double"/>
+  <reg name="d10" bitsize="64" type="ieee_double"/>
+  <reg name="d11" bitsize="64" type="ieee_double"/>
+  <reg name="d12" bitsize="64" type="ieee_double"/>
+  <reg name="d13" bitsize="64" type="ieee_double"/>
+  <reg name="d14" bitsize="64" type="ieee_double"/>
+  <reg name="d15" bitsize="64" type="ieee_double"/>
+  <reg name="d16" bitsize="64" type="ieee_double"/>
+  <reg name="d17" bitsize="64" type="ieee_double"/>
+  <reg name="d18" bitsize="64" type="ieee_double"/>
+  <reg name="d19" bitsize="64" type="ieee_double"/>
+  <reg name="d20" bitsize="64" type="ieee_double"/>
+  <reg name="d21" bitsize="64" type="ieee_double"/>
+  <reg name="d22" bitsize="64" type="ieee_double"/>
+  <reg name="d23" bitsize="64" type="ieee_double"/>
+  <reg name="d24" bitsize="64" type="ieee_double"/>
+  <reg name="d25" bitsize="64" type="ieee_double"/>
+  <reg name="d26" bitsize="64" type="ieee_double"/>
+  <reg name="d27" bitsize="64" type="ieee_double"/>
+  <reg name="d28" bitsize="64" type="ieee_double"/>
+  <reg name="d29" bitsize="64" type="ieee_double"/>
+  <reg name="d30" bitsize="64" type="ieee_double"/>
+  <reg name="d31" bitsize="64" type="ieee_double"/>
+
+  <reg name="fpscr" bitsize="32" type="int" group="float"/>
+</feature>
diff --git a/gdb/features/arm-with-neon.c b/gdb/features/arm-with-neon.c
new file mode 100644 (file)
index 0000000..d669d08
--- /dev/null
@@ -0,0 +1,72 @@
+/* THIS FILE IS GENERATED.  Original: arm-with-neon.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_arm_with_neon;
+static void
+initialize_tdesc_arm_with_neon (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "cpsr", 25, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.vfp");
+  tdesc_create_reg (feature, "d0", 26, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d1", 27, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d2", 28, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d3", 29, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d4", 30, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d5", 31, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d6", 32, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d7", 33, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d8", 34, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d9", 35, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d10", 36, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d11", 37, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d12", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d13", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d14", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d15", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d16", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d17", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d18", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d19", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d20", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d21", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d22", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d23", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d24", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d25", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d26", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d27", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d28", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d29", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d30", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d31", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fpscr", 58, 1, "float", 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.neon");
+
+  tdesc_arm_with_neon = result;
+}
diff --git a/gdb/features/arm-with-neon.xml b/gdb/features/arm-with-neon.xml
new file mode 100644 (file)
index 0000000..8b7e497
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <xi:include href="arm-core.xml"/>
+  <xi:include href="arm-vfpv3.xml"/>
+  <feature name="org.gnu.gdb.arm.neon"/>
+</target>
diff --git a/gdb/features/arm-with-vfpv2.c b/gdb/features/arm-with-vfpv2.c
new file mode 100644 (file)
index 0000000..687e140
--- /dev/null
@@ -0,0 +1,54 @@
+/* THIS FILE IS GENERATED.  Original: arm-with-vfpv2.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_arm_with_vfpv2;
+static void
+initialize_tdesc_arm_with_vfpv2 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "cpsr", 25, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.vfp");
+  tdesc_create_reg (feature, "d0", 26, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d1", 27, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d2", 28, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d3", 29, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d4", 30, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d5", 31, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d6", 32, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d7", 33, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d8", 34, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d9", 35, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d10", 36, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d11", 37, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d12", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d13", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d14", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d15", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fpscr", 42, 1, "float", 32, "int");
+
+  tdesc_arm_with_vfpv2 = result;
+}
diff --git a/gdb/features/arm-with-vfpv2.xml b/gdb/features/arm-with-vfpv2.xml
new file mode 100644 (file)
index 0000000..c64e4df
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <xi:include href="arm-core.xml"/>
+  <xi:include href="arm-vfpv2.xml"/>
+</target>
diff --git a/gdb/features/arm-with-vfpv3.c b/gdb/features/arm-with-vfpv3.c
new file mode 100644 (file)
index 0000000..efb851d
--- /dev/null
@@ -0,0 +1,70 @@
+/* THIS FILE IS GENERATED.  Original: arm-with-vfpv3.xml */
+
+#include "defs.h"
+#include "gdbtypes.h"
+#include "target-descriptions.h"
+
+struct target_desc *tdesc_arm_with_vfpv3;
+static void
+initialize_tdesc_arm_with_vfpv3 (void)
+{
+  struct target_desc *result = allocate_target_description ();
+  struct tdesc_feature *feature;
+  struct type *field_type, *type;
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
+  tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");
+  tdesc_create_reg (feature, "cpsr", 25, 1, NULL, 32, "int");
+
+  feature = tdesc_create_feature (result, "org.gnu.gdb.arm.vfp");
+  tdesc_create_reg (feature, "d0", 26, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d1", 27, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d2", 28, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d3", 29, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d4", 30, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d5", 31, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d6", 32, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d7", 33, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d8", 34, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d9", 35, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d10", 36, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d11", 37, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d12", 38, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d13", 39, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d14", 40, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d15", 41, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d16", 42, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d17", 43, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d18", 44, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d19", 45, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d20", 46, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d21", 47, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d22", 48, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d23", 49, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d24", 50, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d25", 51, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d26", 52, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d27", 53, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d28", 54, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d29", 55, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d30", 56, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "d31", 57, 1, NULL, 64, "ieee_double");
+  tdesc_create_reg (feature, "fpscr", 58, 1, "float", 32, "int");
+
+  tdesc_arm_with_vfpv3 = result;
+}
diff --git a/gdb/features/arm-with-vfpv3.xml b/gdb/features/arm-with-vfpv3.xml
new file mode 100644 (file)
index 0000000..9658b02
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2009 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target>
+  <xi:include href="arm-core.xml"/>
+  <xi:include href="arm-vfpv3.xml"/>
+</target>
index b878baf59f7c89816b68a0326016dc1ea23cd72d..27838a56daab96145cc93eafc00f67e14a78e324 100644 (file)
@@ -1,3 +1,21 @@
+2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * linux-low.c (linux_write_memory): Update debugging output.
+       * Makefile.in (clean): Add new descriptions.
+       (arm-with-vfpv2.o, arm-with-vfpv2.c, arm-with-vfpv3.o)
+       (arm-with-vfpv3.c, arm-with-neon.o, arm-with-neon.c): New rules.
+       * configure.srv: Add new files for arm*-*-linux*.
+       * linux-arm-low.c: Add new declarations.
+       (PTRACE_GETVFPREGS, PTRACE_SETVFPREGS): Define if undefined.
+       (arm_hwcap, HWCAP_VFP, HWCAP_IWMMXT, HWCAP_NEON, HWCAP_VFPv3)
+       (HWCAP_VFPv3D16): New.
+       (arm_fill_wmmxregset, arm_store_wmmxregset): Check HWCAP_IWMMXT
+       instead of __IWMMXT__.
+       (arm_fill_vfpregset, arm_store_vfpregset, arm_get_hwcap)
+       (arm_arch_setup): New.
+       (target_regsets): Remove #ifdef.  Add VFP regset.
+       (the_low_target): Use arm_arch_setup.
+
 2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * linux-low.c (linux_kill_one_lwp): Adjust kernel workaround to skip
index 37d6095922e96f71a71009a1238e8206d4a260c0..eea59a1a176b506323919c29da9a68a2deed8dbb 100644 (file)
@@ -205,7 +205,9 @@ clean:
        rm -f reg-arm.c reg-i386.c reg-ia64.c reg-m32r.c reg-m68k.c
        rm -f reg-sh.c reg-sparc.c reg-spu.c reg-x86-64.c reg-i386-linux.c
        rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c
-       rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c
+       rm -f arm-with-iwmmxt.c
+       rm -f arm-with-vfpv2.c arm-with-vfpv3.c arm-with-neon.c
+       rm -f mips-linux.c mips64-linux.c
        rm -f powerpc-32l.c powerpc-64l.c powerpc-e500l.c
        rm -f powerpc-altivec32l.c powerpc-vsx32l.c powerpc-altivec64l.c
        rm -f powerpc-vsx64l.c
@@ -326,6 +328,15 @@ reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh)
 arm-with-iwmmxt.o : arm-with-iwmmxt.c $(regdef_h)
 arm-with-iwmmxt.c : $(srcdir)/../regformats/arm-with-iwmmxt.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/arm-with-iwmmxt.dat arm-with-iwmmxt.c
+arm-with-vfpv2.o : arm-with-vfpv2.c $(regdef_h)
+arm-with-vfpv2.c : $(srcdir)/../regformats/arm-with-vfpv2.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/arm-with-vfpv2.dat arm-with-vfpv2.c
+arm-with-vfpv3.o : arm-with-vfpv3.c $(regdef_h)
+arm-with-vfpv3.c : $(srcdir)/../regformats/arm-with-vfpv3.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/arm-with-vfpv3.dat arm-with-vfpv3.c
+arm-with-neon.o : arm-with-neon.c $(regdef_h)
+arm-with-neon.c : $(srcdir)/../regformats/arm-with-neon.dat $(regdat_sh)
+       $(SHELL) $(regdat_sh) $(srcdir)/../regformats/arm-with-neon.dat arm-with-neon.c
 reg-cris.o : reg-cris.c $(regdef_h)
 reg-cris.c : $(srcdir)/../regformats/reg-cris.dat $(regdat_sh)
        $(SHELL) $(regdat_sh) $(srcdir)/../regformats/reg-cris.dat reg-cris.c
index b3ab6228e040c26583891bdf1abada15f0b3702b..900b5656b2f61f57366406170a6b90dc83d3704a 100644 (file)
@@ -26,10 +26,18 @@ srv_hostio_err_objs="hostio-errno.o"
 
 case "${target}" in
   arm*-*-linux*)       srv_regobj="reg-arm.o arm-with-iwmmxt.o"
+                       srv_regobj="${srv_regobj} arm-with-vfpv2.o"
+                       srv_regobj="${srv_regobj} arm-with-vfpv3.o"
+                       srv_regobj="${srv_regobj} arm-with-neon.o"
                        srv_tgtobj="linux-low.o linux-arm-low.o"
                        srv_xmlfiles="arm-with-iwmmxt.xml"
+                       srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml"
+                       srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv3.xml"
+                       srv_xmlfiles="${srv_xmlfiles} arm-with-neon.xml"
                        srv_xmlfiles="${srv_xmlfiles} arm-core.xml"
                        srv_xmlfiles="${srv_xmlfiles} xscale-iwmmxt.xml"
+                       srv_xmlfiles="${srv_xmlfiles} arm-vfpv2.xml"
+                       srv_xmlfiles="${srv_xmlfiles} arm-vfpv3.xml"
                        srv_linux_usrregs=yes
                        srv_linux_regsets=yes
                        srv_linux_thread_db=yes
index 70597fc2aab589ec35cab63abf344e22a55cbb2a..d47ee977311d1e70e081fe51c67d29853e435c84 100644 (file)
 #include "server.h"
 #include "linux-low.h"
 
+#include <elf.h>
 #include <sys/ptrace.h>
 
 #include "gdb_proc_service.h"
 
-/* Defined in auto-generated file reg-arm.c.  */
+/* Defined in auto-generated files.  */
 void init_registers_arm (void);
-/* Defined in auto-generated file arm-with-iwmmxt.c.  */
 void init_registers_arm_with_iwmmxt (void);
+void init_registers_arm_with_vfpv2 (void);
+void init_registers_arm_with_vfpv3 (void);
+void init_registers_arm_with_neon (void);
 
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 22
@@ -38,6 +41,20 @@ void init_registers_arm_with_iwmmxt (void);
 # define PTRACE_SETWMMXREGS 19
 #endif
 
+#ifndef PTRACE_GETVFPREGS
+# define PTRACE_GETVFPREGS 27
+# define PTRACE_SETVFPREGS 28
+#endif
+
+static unsigned long arm_hwcap;
+
+/* 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
+
 #ifdef HAVE_SYS_REG_H
 #include <sys/reg.h>
 #endif
@@ -87,13 +104,14 @@ arm_store_gregset (const void *buf)
       supply_register (i, zerobuf);
 }
 
-#ifdef __IWMMXT__
-
 static void
 arm_fill_wmmxregset (void *buf)
 {
   int i;
 
+  if (!(arm_hwcap & HWCAP_IWMMXT))
+    return;
+
   for (i = 0; i < 16; i++)
     collect_register (arm_num_regs + i, (char *) buf + i * 8);
 
@@ -107,6 +125,9 @@ arm_store_wmmxregset (const void *buf)
 {
   int i;
 
+  if (!(arm_hwcap & HWCAP_IWMMXT))
+    return;
+
   for (i = 0; i < 16; i++)
     supply_register (arm_num_regs + i, (char *) buf + i * 8);
 
@@ -115,7 +136,45 @@ arm_store_wmmxregset (const void *buf)
     supply_register (arm_num_regs + i + 16, (char *) buf + 16 * 8 + i * 4);
 }
 
-#endif /* __IWMMXT__ */
+static void
+arm_fill_vfpregset (void *buf)
+{
+  int i, num, base;
+
+  if (!(arm_hwcap & HWCAP_VFP))
+    return;
+
+  if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
+    num = 32;
+  else
+    num = 16;
+
+  base = find_regno ("d0");
+  for (i = 0; i < num; i++)
+    collect_register (base + i, (char *) buf + i * 8);
+
+  collect_register_by_name ("fpscr", (char *) buf + 32 * 8);
+}
+
+static void
+arm_store_vfpregset (const void *buf)
+{
+  int i, num, base;
+
+  if (!(arm_hwcap & HWCAP_VFP))
+    return;
+
+  if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
+    num = 32;
+  else
+    num = 16;
+
+  base = find_regno ("d0");
+  for (i = 0; i < num; i++)
+    supply_register (base + i, (char *) buf + i * 8);
+
+  supply_register_by_name ("fpscr", (char *) buf + 32 * 8);
+}
 
 extern int debug_threads;
 
@@ -208,24 +267,94 @@ ps_get_thread_area (const struct ps_prochandle *ph,
   return PS_OK;
 }
 
+static int
+arm_get_hwcap (unsigned long *valp)
+{
+  unsigned char *data = alloca (8);
+  int offset = 0;
+
+  while ((*the_target->read_auxv) (offset, data, 8) == 8)
+    {
+      unsigned int *data_p = (unsigned int *)data;
+      if (data_p[0] == AT_HWCAP)
+       {
+         *valp = data_p[1];
+         return 1;
+       }
+
+      offset += 8;
+    }
+
+  *valp = 0;
+  return 0;
+}
+
+static void
+arm_arch_setup (void)
+{
+  arm_hwcap = 0;
+  if (arm_get_hwcap (&arm_hwcap) == 0)
+    {
+      init_registers_arm ();
+      return;
+    }
+
+  if (arm_hwcap & HWCAP_IWMMXT)
+    {
+      init_registers_arm_with_iwmmxt ();
+      return;
+    }
+
+  if (arm_hwcap & HWCAP_VFP)
+    {
+      int pid;
+      char *buf;
+
+      /* NEON implies either no VFP, or VFPv3-D32.  We only support
+        it with VFP.  */
+      if (arm_hwcap & HWCAP_NEON)
+       init_registers_arm_with_neon ();
+      else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
+       init_registers_arm_with_vfpv3 ();
+      else
+       init_registers_arm_with_vfpv2 ();
+
+      /* Now make sure that the kernel supports reading these
+        registers.  Support was added in 2.6.30.  */
+      pid = lwpid_of (get_thread_lwp (current_inferior));
+      errno = 0;
+      buf = malloc (32 * 8 + 4);
+      if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0
+         && errno == EIO)
+       {
+         arm_hwcap = 0;
+         init_registers_arm ();
+       }
+      free (buf);
+
+      return;
+    }
+
+  /* The default configuration uses legacy FPA registers, probably
+     simulated.  */
+  init_registers_arm ();
+}
+
 struct regset_info target_regsets[] = {
   { PTRACE_GETREGS, PTRACE_SETREGS, 18 * 4,
     GENERAL_REGS,
     arm_fill_gregset, arm_store_gregset },
-#ifdef __IWMMXT__
   { PTRACE_GETWMMXREGS, PTRACE_SETWMMXREGS, 16 * 8 + 6 * 4,
     EXTENDED_REGS,
     arm_fill_wmmxregset, arm_store_wmmxregset },
-#endif
+  { PTRACE_GETVFPREGS, PTRACE_SETVFPREGS, 32 * 8 + 4,
+    EXTENDED_REGS,
+    arm_fill_vfpregset, arm_store_vfpregset },
   { 0, 0, -1, -1, NULL, NULL }
 };
 
 struct linux_target_ops the_low_target = {
-#ifdef __IWMMXT__
-  init_registers_arm_with_iwmmxt,
-#else
-  init_registers_arm,
-#endif
+  arm_arch_setup,
   arm_num_regs,
   arm_regmap,
   arm_cannot_fetch_register,
index 6d677f259e39a489cac8eb070aba3d2750276a31..5edc4730846160261d7e228c5592189935bac80e 100644 (file)
@@ -2394,7 +2394,16 @@ linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
 
   if (debug_threads)
     {
-      fprintf (stderr, "Writing %02x to %08lx\n", (unsigned)myaddr[0], (long)memaddr);
+      /* Dump up to four bytes.  */
+      unsigned int val = * (unsigned int *) myaddr;
+      if (len == 1)
+       val = val & 0xff;
+      else if (len == 2)
+       val = val & 0xffff;
+      else if (len == 3)
+       val = val & 0xffffff;
+      fprintf (stderr, "Writing %0*x to 0x%08lx\n", 2 * ((len < 4) ? len : 4),
+              val, (long)memaddr);
     }
 
   /* Fill start and end extra bytes of buffer with existing memory data.  */
diff --git a/gdb/regformats/arm-with-neon.dat b/gdb/regformats/arm-with-neon.dat
new file mode 100644 (file)
index 0000000..84694dc
--- /dev/null
@@ -0,0 +1,63 @@
+# DO NOT EDIT: generated from arm-with-neon.xml
+name:arm_with_neon
+xmltarget:arm-with-neon.xml
+expedite:r11,sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:sp
+32:lr
+32:pc
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+32:cpsr
+64:d0
+64:d1
+64:d2
+64:d3
+64:d4
+64:d5
+64:d6
+64:d7
+64:d8
+64:d9
+64:d10
+64:d11
+64:d12
+64:d13
+64:d14
+64:d15
+64:d16
+64:d17
+64:d18
+64:d19
+64:d20
+64:d21
+64:d22
+64:d23
+64:d24
+64:d25
+64:d26
+64:d27
+64:d28
+64:d29
+64:d30
+64:d31
+32:fpscr
diff --git a/gdb/regformats/arm-with-vfpv2.dat b/gdb/regformats/arm-with-vfpv2.dat
new file mode 100644 (file)
index 0000000..7c2780a
--- /dev/null
@@ -0,0 +1,47 @@
+# DO NOT EDIT: generated from arm-with-vfpv2.xml
+name:arm_with_vfpv2
+xmltarget:arm-with-vfpv2.xml
+expedite:r11,sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:sp
+32:lr
+32:pc
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+32:cpsr
+64:d0
+64:d1
+64:d2
+64:d3
+64:d4
+64:d5
+64:d6
+64:d7
+64:d8
+64:d9
+64:d10
+64:d11
+64:d12
+64:d13
+64:d14
+64:d15
+32:fpscr
diff --git a/gdb/regformats/arm-with-vfpv3.dat b/gdb/regformats/arm-with-vfpv3.dat
new file mode 100644 (file)
index 0000000..9bb1e90
--- /dev/null
@@ -0,0 +1,63 @@
+# DO NOT EDIT: generated from arm-with-vfpv3.xml
+name:arm_with_vfpv3
+xmltarget:arm-with-vfpv3.xml
+expedite:r11,sp,pc
+32:r0
+32:r1
+32:r2
+32:r3
+32:r4
+32:r5
+32:r6
+32:r7
+32:r8
+32:r9
+32:r10
+32:r11
+32:r12
+32:sp
+32:lr
+32:pc
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+0:
+32:cpsr
+64:d0
+64:d1
+64:d2
+64:d3
+64:d4
+64:d5
+64:d6
+64:d7
+64:d8
+64:d9
+64:d10
+64:d11
+64:d12
+64:d13
+64:d14
+64:d15
+64:d16
+64:d17
+64:d18
+64:d19
+64:d20
+64:d21
+64:d22
+64:d23
+64:d24
+64:d25
+64:d26
+64:d27
+64:d28
+64:d29
+64:d30
+64:d31
+32:fpscr
index 88cc7e0442d66fa7692ee2c94d5bca5c3b5a84f3..024257b73400aff3f602fb64bd9a85b27ec69b60 100644 (file)
@@ -633,6 +633,21 @@ tdesc_numbered_register (const struct tdesc_feature *feature,
   return 1;
 }
 
+/* Search FEATURE for a register named NAME, but do not assign a fixed
+   register number to it.  */
+
+int
+tdesc_unnumbered_register (const struct tdesc_feature *feature,
+                          const char *name)
+{
+  struct tdesc_reg *reg = tdesc_find_register_early (feature, name);
+
+  if (reg == NULL)
+    return 0;
+
+  return 1;
+}
+
 /* Search FEATURE for a register whose name is in NAMES and assign
    REGNO to it.  */
 
@@ -708,7 +723,7 @@ tdesc_register_name (struct gdbarch *gdbarch, int regno)
   return "";
 }
 
-static struct type *
+struct type *
 tdesc_register_type (struct gdbarch *gdbarch, int regno)
 {
   struct tdesc_arch_reg *arch_reg = tdesc_find_arch_register (gdbarch, regno);
@@ -856,8 +871,9 @@ tdesc_register_reggroup_p (struct gdbarch *gdbarch, int regno,
   if (regno >= num_regs && regno < num_regs + num_pseudo_regs)
     {
       struct tdesc_arch_data *data = gdbarch_data (gdbarch, tdesc_data);
-      gdb_assert (data->pseudo_register_reggroup_p != NULL);
-      return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup);
+      if (data->pseudo_register_reggroup_p != NULL)
+       return data->pseudo_register_reggroup_p (gdbarch, regno, reggroup);
+      /* Otherwise fall through to the default reggroup_p.  */
     }
 
   ret = tdesc_register_in_reggroup_p (gdbarch, regno, reggroup);
index 6553fc3440a077b41d25fa8eac1b37226847c1b7..899f1197e278c3ea1338857c3620966db19b4e19 100644 (file)
@@ -98,6 +98,12 @@ int tdesc_numbered_register (const struct tdesc_feature *feature,
                             struct tdesc_arch_data *data,
                             int regno, const char *name);
 
+/* Search FEATURE for a register named NAME, but do not assign a fixed
+   register number to it.  */
+
+int tdesc_unnumbered_register (const struct tdesc_feature *feature,
+                              const char *name);
+
 /* Search FEATURE for a register named NAME, and return its size in
    bits.  The register must exist.  */
 
@@ -159,6 +165,11 @@ struct tdesc_type *tdesc_named_type (const struct tdesc_feature *feature,
 
 const char *tdesc_register_name (struct gdbarch *gdbarch, int regno);
 
+/* Return the type of register REGNO, from the target description or
+   from an architecture-provided pseudo_register_type method.  */
+
+struct type *tdesc_register_type (struct gdbarch *gdbarch, int regno);
+
 /* Check whether REGNUM is a member of REGGROUP using the target
    description.  Return -1 if the target description does not
    specify a group.  */
index c2ae2f898cd6dc8a1b82b510c733db897574a6d8..aaaa84eeed1ad721ca7cead0bc8091a78cca6248 100644 (file)
@@ -1,3 +1,7 @@
+2009-07-28  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.base/float.exp: Handle VFP registers.
+
 2009-07-14  Michael Snyder  <msnyder@vmware.com>
 
        * gdb.reverse/finish-reverse.exp: Do not expect reverse-finish
index a14a91548eb30b9499d731c33f1b537397eb9f55..09a02cad731b123fa166f3bc5e8976f5b47d56ca 100644 (file)
@@ -51,6 +51,11 @@ if { [istarget "alpha*-*-*"] } then {
        -re "Software FPU type.*mask:.*flags:.*$gdb_prompt $" {
            pass "info float (FPA)"
        }
+       -re "fpscr.*s0.*s1.*s31.*$gdb_prompt $" {
+           # Only check for single precision; d0 might be a vector register
+           # if we have NEON.
+           pass "info float (VFP)"
+       }
         -re "No floating.point info available for this processor.*" {
             pass "info float (without FPU)"
        }