mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-02-24 19:42:32 +00:00
* 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:
parent
12b42a1250
commit
58d6951de5
@ -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
|
||||
|
9
gdb/NEWS
9
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
|
||||
|
||||
|
446
gdb/arm-tdep.c
446
gdb/arm-tdep.c
@ -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,
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
28
gdb/features/arm-vfpv2.xml
Normal file
28
gdb/features/arm-vfpv2.xml
Normal 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>
|
44
gdb/features/arm-vfpv3.xml
Normal file
44
gdb/features/arm-vfpv3.xml
Normal 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>
|
72
gdb/features/arm-with-neon.c
Normal file
72
gdb/features/arm-with-neon.c
Normal 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;
|
||||
}
|
13
gdb/features/arm-with-neon.xml
Normal file
13
gdb/features/arm-with-neon.xml
Normal 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>
|
54
gdb/features/arm-with-vfpv2.c
Normal file
54
gdb/features/arm-with-vfpv2.c
Normal 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;
|
||||
}
|
12
gdb/features/arm-with-vfpv2.xml
Normal file
12
gdb/features/arm-with-vfpv2.xml
Normal 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>
|
70
gdb/features/arm-with-vfpv3.c
Normal file
70
gdb/features/arm-with-vfpv3.c
Normal 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;
|
||||
}
|
12
gdb/features/arm-with-vfpv3.xml
Normal file
12
gdb/features/arm-with-vfpv3.xml
Normal 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>
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
63
gdb/regformats/arm-with-neon.dat
Normal file
63
gdb/regformats/arm-with-neon.dat
Normal 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
|
47
gdb/regformats/arm-with-vfpv2.dat
Normal file
47
gdb/regformats/arm-with-vfpv2.dat
Normal 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
|
63
gdb/regformats/arm-with-vfpv3.dat
Normal file
63
gdb/regformats/arm-with-vfpv3.dat
Normal 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
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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)"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user