* 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.

	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.
This commit is contained in:
Daniel Jacobowitz 2009-07-28 18:26:51 +00:00
parent 12b42a1250
commit 58d6951de5
27 changed files with 1215 additions and 55 deletions

View 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

View File

@ -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

View 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,

View 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;
};

View 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>

View 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

View File

@ -31,28 +31,17 @@
# 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

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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>

View 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

View 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

View 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

View File

@ -20,14 +20,17 @@
#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,

View 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. */

View File

@ -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

View File

@ -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

View File

@ -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

View 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);

View 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. */

View 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

View 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)"
}