* arm-tdep.c: Include features/arm-with-m.c.

(arm_psr_thumb_bit): New.  Update all uses of CPSR_T to
	call this function.
	(arm_pc_is_thumb): Add a gdbarch argument.  Update all callers.
	Check is_m after force-mode.
	(arm_gdbarch_init): Check the binary before the target description.
	Add check for M profile attribute.  If we have an M-profile device,
	but no target register description, use arm-with-m.  Recognize the
	new org.gnu.gdb.arm.m-profile feature and its xpsr register.
	(_initialize_arm_tdep): Call initialize_tdesc_arm_with_m.
	* arm-tdep.h (XPSR_T): Define.
	(struct gdbarch_tdep): Add is_m member.
	* features/arm-m-profile.xml, features/arm-with-m.c,
	features/arm-with-m.xml: New files.

	doc/
	* gdb.texinfo (ARM Features): Document
	org.gnu.gdb.arm.m-profile.
This commit is contained in:
Daniel Jacobowitz 2010-08-24 15:56:15 +00:00
parent b8fa875047
commit 9779414d4e
8 changed files with 354 additions and 182 deletions

View File

@ -1,3 +1,22 @@
2010-08-24 Daniel Jacobowitz <dan@codesourcery.com>
Kazu Hirata <kazu@codesourcery.com>
Jonathan Larmour <jifl@eCosCentric.com>
* arm-tdep.c: Include features/arm-with-m.c.
(arm_psr_thumb_bit): New. Update all uses of CPSR_T to
call this function.
(arm_pc_is_thumb): Add a gdbarch argument. Update all callers.
Check is_m after force-mode.
(arm_gdbarch_init): Check the binary before the target description.
Add check for M profile attribute. If we have an M-profile device,
but no target register description, use arm-with-m. Recognize the
new org.gnu.gdb.arm.m-profile feature and its xpsr register.
(_initialize_arm_tdep): Call initialize_tdesc_arm_with_m.
* arm-tdep.h (XPSR_T): Define.
(struct gdbarch_tdep): Add is_m member.
* features/arm-m-profile.xml, features/arm-with-m.c,
features/arm-with-m.xml: New files.
2010-08-23 Doug Evans <dje@google.com>
* dwarf2read.c (read_structure_type): Add comment.

View File

@ -53,6 +53,8 @@
#include "gdb_assert.h"
#include "vec.h"
#include "features/arm-with-m.c"
static int arm_debug;
/* Macros for setting and testing a bit in a minimal symbol that marks
@ -255,12 +257,24 @@ static CORE_ADDR arm_analyze_prologue (struct gdbarch *gdbarch,
int arm_apcs_32 = 1;
/* Return the bit mask in ARM_PS_REGNUM that indicates Thumb mode. */
static int
arm_psr_thumb_bit (struct gdbarch *gdbarch)
{
if (gdbarch_tdep (gdbarch)->is_m)
return XPSR_T;
else
return CPSR_T;
}
/* Determine if FRAME is executing in Thumb mode. */
static int
arm_frame_is_thumb (struct frame_info *frame)
{
CORE_ADDR cpsr;
ULONGEST t_bit = arm_psr_thumb_bit (get_frame_arch (frame));
/* Every ARM frame unwinder can unwind the T bit of the CPSR, either
directly (from a signal frame or dummy frame) or by interpreting
@ -268,7 +282,7 @@ arm_frame_is_thumb (struct frame_info *frame)
trust the unwinders. */
cpsr = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
return (cpsr & CPSR_T) != 0;
return (cpsr & t_bit) != 0;
}
/* Callback for VEC_lower_bound. */
@ -347,7 +361,7 @@ static CORE_ADDR arm_get_next_pc_raw (struct frame_info *frame,
any executing frame; otherwise, prefer arm_frame_is_thumb. */
static int
arm_pc_is_thumb (CORE_ADDR memaddr)
arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
{
struct obj_section *sec;
struct minimal_symbol *sym;
@ -363,6 +377,10 @@ arm_pc_is_thumb (CORE_ADDR memaddr)
if (strcmp (arm_force_mode_string, "thumb") == 0)
return 1;
/* ARM v6-M and v7-M are always in Thumb mode. */
if (gdbarch_tdep (gdbarch)->is_m)
return 1;
/* If there are mapping symbols, consult them. */
type = arm_find_mapping_symbol (memaddr, NULL);
if (type)
@ -815,7 +833,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
associate prologue code with the opening brace; so this
lets us skip the first line if we think it is the opening
brace. */
if (arm_pc_is_thumb (func_addr))
if (arm_pc_is_thumb (gdbarch, func_addr))
analyzed_limit = thumb_analyze_prologue (gdbarch, func_addr,
post_prologue_pc, NULL);
else
@ -842,7 +860,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
/* Check if this is Thumb code. */
if (arm_pc_is_thumb (pc))
if (arm_pc_is_thumb (gdbarch, pc))
return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
@ -1507,13 +1525,14 @@ arm_prologue_prev_register (struct frame_info *this_frame,
if (prev_regnum == ARM_PS_REGNUM)
{
CORE_ADDR lr, cpsr;
ULONGEST t_bit = arm_psr_thumb_bit (gdbarch);
cpsr = get_frame_register_unsigned (this_frame, prev_regnum);
lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
if (IS_THUMB_ADDR (lr))
cpsr |= CPSR_T;
cpsr |= t_bit;
else
cpsr &= ~CPSR_T;
cpsr &= ~t_bit;
return frame_unwind_got_constant (this_frame, prev_regnum, cpsr);
}
@ -1640,6 +1659,7 @@ arm_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
{
struct gdbarch * gdbarch = get_frame_arch (this_frame);
CORE_ADDR lr, cpsr;
ULONGEST t_bit = arm_psr_thumb_bit (gdbarch);
switch (regnum)
{
@ -1657,9 +1677,9 @@ arm_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
cpsr = get_frame_register_unsigned (this_frame, regnum);
lr = frame_unwind_register_unsigned (this_frame, ARM_LR_REGNUM);
if (IS_THUMB_ADDR (lr))
cpsr |= CPSR_T;
cpsr |= t_bit;
else
cpsr &= ~CPSR_T;
cpsr &= ~t_bit;
return frame_unwind_got_constant (this_frame, regnum, cpsr);
default:
@ -2008,7 +2028,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
/* Set the return address. For the ARM, the return breakpoint is
always at BP_ADDR. */
if (arm_pc_is_thumb (bp_addr))
if (arm_pc_is_thumb (gdbarch, bp_addr))
bp_addr |= 1;
regcache_cooked_write_unsigned (regcache, ARM_LR_REGNUM, bp_addr);
@ -2147,7 +2167,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
&& TYPE_CODE_FUNC == TYPE_CODE (check_typedef (target_type)))
{
CORE_ADDR regval = extract_unsigned_integer (val, len, byte_order);
if (arm_pc_is_thumb (regval))
if (arm_pc_is_thumb (gdbarch, regval))
{
bfd_byte *copy = alloca (len);
store_unsigned_integer (copy, len, byte_order,
@ -3352,7 +3372,7 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
return bpaddr;
/* ARM mode does not have this problem. */
if (!arm_pc_is_thumb (bpaddr))
if (!arm_pc_is_thumb (gdbarch, bpaddr))
return bpaddr;
/* We are setting a breakpoint in Thumb code that could potentially
@ -3543,10 +3563,11 @@ static int
displaced_in_arm_mode (struct regcache *regs)
{
ULONGEST ps;
ULONGEST t_bit = arm_psr_thumb_bit (get_regcache_arch (regs));
regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &ps);
return (ps & CPSR_T) == 0;
return (ps & t_bit) == 0;
}
/* Write to the PC as from a branch instruction. */
@ -3568,18 +3589,18 @@ static void
bx_write_pc (struct regcache *regs, ULONGEST val)
{
ULONGEST ps;
ULONGEST t_bit = arm_psr_thumb_bit (get_regcache_arch (regs));
regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &ps);
if ((val & 1) == 1)
{
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps | CPSR_T);
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps | t_bit);
regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val & 0xfffffffe);
}
else if ((val & 2) == 0)
{
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM,
ps & ~(ULONGEST) CPSR_T);
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps & ~t_bit);
regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val);
}
else
@ -3587,8 +3608,7 @@ bx_write_pc (struct regcache *regs, ULONGEST val)
/* Unpredictable behaviour. Try to do something sensible (switch to ARM
mode, align dest to 4 bytes). */
warning (_("Single-stepping BX to non-word-aligned ARM instruction."));
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM,
ps & ~(ULONGEST) CPSR_T);
regcache_cooked_write_unsigned (regs, ARM_PS_REGNUM, ps & ~t_bit);
regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, val & 0xfffffffc);
}
}
@ -5345,7 +5365,9 @@ arm_displaced_step_fixup (struct gdbarch *gdbarch,
static int
gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
{
if (arm_pc_is_thumb (memaddr))
struct gdbarch *gdbarch = info->application_data;
if (arm_pc_is_thumb (gdbarch, memaddr))
{
static asymbol *asym;
static combined_entry_type ce;
@ -5435,7 +5457,7 @@ arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
if (arm_pc_is_thumb (*pcptr))
if (arm_pc_is_thumb (gdbarch, *pcptr))
{
*pcptr = UNMAKE_THUMB_ADDR (*pcptr);
@ -5474,7 +5496,7 @@ arm_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
arm_breakpoint_from_pc (gdbarch, pcptr, kindptr);
if (arm_pc_is_thumb (*pcptr) && *kindptr == 4)
if (arm_pc_is_thumb (gdbarch, *pcptr) && *kindptr == 4)
/* The documented magic value for a 32-bit Thumb-2 breakpoint, so
that this is not confused with a 32-bit ARM breakpoint. */
*kindptr = 3;
@ -6219,18 +6241,21 @@ arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
static void
arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
regcache_cooked_write_unsigned (regcache, ARM_PC_REGNUM, pc);
/* If necessary, set the T bit. */
if (arm_apcs_32)
{
ULONGEST val;
ULONGEST val, t_bit;
regcache_cooked_read_unsigned (regcache, ARM_PS_REGNUM, &val);
if (arm_pc_is_thumb (pc))
regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM, val | CPSR_T);
t_bit = arm_psr_thumb_bit (gdbarch);
if (arm_pc_is_thumb (gdbarch, pc))
regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM,
val | t_bit);
else
regcache_cooked_write_unsigned (regcache, ARM_PS_REGNUM,
val & ~(ULONGEST) CPSR_T);
val & ~t_bit);
}
}
@ -6411,165 +6436,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
enum arm_abi_kind arm_abi = arm_abi_global;
enum arm_float_model fp_model = arm_fp_model;
struct tdesc_arch_data *tdesc_data = NULL;
int i;
int i, is_m = 0;
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. */
if (tdesc_has_registers (info.target_desc))
{
/* For most registers we require GDB's default names; but also allow
the numeric names for sp / lr / pc, as a convenience. */
static const char *const arm_sp_names[] = { "r13", "sp", NULL };
static const char *const arm_lr_names[] = { "r14", "lr", NULL };
static const char *const arm_pc_names[] = { "r15", "pc", NULL };
const struct tdesc_feature *feature;
int valid_p;
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.arm.core");
if (feature == NULL)
return NULL;
tdesc_data = tdesc_data_alloc ();
valid_p = 1;
for (i = 0; i < ARM_SP_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_SP_REGNUM,
arm_sp_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_LR_REGNUM,
arm_lr_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_PC_REGNUM,
arm_pc_names);
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "cpsr");
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.arm.fpa");
if (feature != NULL)
{
valid_p = 1;
for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
}
else
have_fpa_registers = 0;
feature = tdesc_find_feature (info.target_desc,
"org.gnu.gdb.xscale.iwmmxt");
if (feature != NULL)
{
static const char *const iwmmxt_names[] = {
"wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7",
"wR8", "wR9", "wR10", "wR11", "wR12", "wR13", "wR14", "wR15",
"wCID", "wCon", "wCSSF", "wCASF", "", "", "", "",
"wCGR0", "wCGR1", "wCGR2", "wCGR3", "", "", "", "",
};
valid_p = 1;
for (i = ARM_WR0_REGNUM; i <= ARM_WR15_REGNUM; i++)
valid_p
&= tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
/* Check for the control registers, but do not fail if they
are missing. */
for (i = ARM_WC0_REGNUM; i <= ARM_WCASF_REGNUM; i++)
tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
for (i = ARM_WCGR0_REGNUM; i <= ARM_WCGR3_REGNUM; i++)
valid_p
&= tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
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;
}
}
}
const struct target_desc *tdesc = info.target_desc;
/* If we have an object to base this architecture on, try to determine
its ABI. */
@ -6605,6 +6476,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
else if (ei_osabi == ELFOSABI_NONE)
{
int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
int attr_arch, attr_profile;
switch (eabi_ver)
{
@ -6662,6 +6534,26 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
warning (_("unknown ARM EABI version 0x%x"), eabi_ver);
break;
}
#ifdef HAVE_ELF
/* Detect M-profile programs. This only works if the
executable file includes build attributes; GCC does
copy them to the executable, but e.g. RealView does
not. */
attr_arch = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
Tag_CPU_arch);
attr_profile = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
Tag_CPU_arch_profile);
/* GCC specifies the profile for v6-M; RealView only
specifies the profile for architectures starting with
V7 (as opposed to architectures with a tag
numerically greater than TAG_CPU_ARCH_V7). */
if (!tdesc_has_registers (tdesc)
&& (attr_arch == TAG_CPU_ARCH_V6_M
|| attr_arch == TAG_CPU_ARCH_V6S_M
|| attr_profile == 'M'))
tdesc = tdesc_arm_with_m;
#endif
}
if (fp_model == ARM_FLOAT_AUTO)
@ -6699,6 +6591,172 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
}
/* Check any target description for validity. */
if (tdesc_has_registers (tdesc))
{
/* For most registers we require GDB's default names; but also allow
the numeric names for sp / lr / pc, as a convenience. */
static const char *const arm_sp_names[] = { "r13", "sp", NULL };
static const char *const arm_lr_names[] = { "r14", "lr", NULL };
static const char *const arm_pc_names[] = { "r15", "pc", NULL };
const struct tdesc_feature *feature;
int valid_p;
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.core");
if (feature == NULL)
{
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.m-profile");
if (feature == NULL)
return NULL;
else
is_m = 1;
}
tdesc_data = tdesc_data_alloc ();
valid_p = 1;
for (i = 0; i < ARM_SP_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_SP_REGNUM,
arm_sp_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_LR_REGNUM,
arm_lr_names);
valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
ARM_PC_REGNUM,
arm_pc_names);
if (is_m)
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "xpsr");
else
valid_p &= tdesc_numbered_register (feature, tdesc_data,
ARM_PS_REGNUM, "cpsr");
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.fpa");
if (feature != NULL)
{
valid_p = 1;
for (i = ARM_F0_REGNUM; i <= ARM_FPS_REGNUM; i++)
valid_p &= tdesc_numbered_register (feature, tdesc_data, i,
arm_register_names[i]);
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
return NULL;
}
}
else
have_fpa_registers = 0;
feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.xscale.iwmmxt");
if (feature != NULL)
{
static const char *const iwmmxt_names[] = {
"wR0", "wR1", "wR2", "wR3", "wR4", "wR5", "wR6", "wR7",
"wR8", "wR9", "wR10", "wR11", "wR12", "wR13", "wR14", "wR15",
"wCID", "wCon", "wCSSF", "wCASF", "", "", "", "",
"wCGR0", "wCGR1", "wCGR2", "wCGR3", "", "", "", "",
};
valid_p = 1;
for (i = ARM_WR0_REGNUM; i <= ARM_WR15_REGNUM; i++)
valid_p
&= tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
/* Check for the control registers, but do not fail if they
are missing. */
for (i = ARM_WC0_REGNUM; i <= ARM_WCASF_REGNUM; i++)
tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
for (i = ARM_WCGR0_REGNUM; i <= ARM_WCGR3_REGNUM; i++)
valid_p
&= tdesc_numbered_register (feature, tdesc_data, i,
iwmmxt_names[i - ARM_WR0_REGNUM]);
if (!valid_p)
{
tdesc_data_cleanup (tdesc_data);
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 (tdesc,
"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 (tdesc,
"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 there is already a candidate, use it. */
for (best_arch = gdbarch_list_lookup_by_info (arches, &info);
best_arch != NULL;
@ -6717,6 +6775,10 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
since gdbarches with a different target description are
automatically disqualified. */
/* Do check is_m, though, since it might come from the binary. */
if (is_m != gdbarch_tdep (best_arch->gdbarch)->is_m)
continue;
/* Found a match. */
break;
}
@ -6735,6 +6797,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
These are gdbarch discriminators, like the OSABI. */
tdep->arm_abi = arm_abi;
tdep->fp_model = fp_model;
tdep->is_m = is_m;
tdep->have_fpa_registers = have_fpa_registers;
tdep->have_vfp_registers = have_vfp_registers;
tdep->have_vfp_pseudos = have_vfp_pseudos;
@ -6908,7 +6971,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
set_tdesc_pseudo_register_name (gdbarch, arm_register_name);
tdesc_use_registers (gdbarch, info.target_desc, tdesc_data);
tdesc_use_registers (gdbarch, tdesc, tdesc_data);
/* Override tdesc_register_type to adjust the types of VFP
registers for NEON. */
@ -6963,6 +7026,9 @@ _initialize_arm_tdep (void)
bfd_target_elf_flavour,
arm_elf_osabi_sniffer);
/* Initialize the standard target descriptions. */
initialize_tdesc_arm_with_m ();
/* Get the number of possible sets of register names defined in opcodes. */
num_disassembly_options = get_arm_regname_num_options ();

View File

@ -108,6 +108,8 @@ enum gdb_regnum {
#define CPSR_T 0x20
#define XPSR_T 0x01000000
/* Type of floating-point code in use by inferior. There are really 3 models
that are traditionally supported (plus the endianness issue), but gcc can
only generate 2 of those. The third is APCS_FLOAT, where arguments to
@ -163,6 +165,7 @@ struct gdbarch_tdep
have_vfp_pseudos. */
int have_neon; /* Do we have a NEON unit? */
int is_m; /* Does the target follow the "M" profile. */
CORE_ADDR lowest_pc; /* Lowest address at which instructions
will appear. */

View File

@ -1,3 +1,8 @@
2010-08-24 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (ARM Features): Document
org.gnu.gdb.arm.m-profile.
2010-08-23 Tom Tromey <tromey@redhat.com>
PR python/11145:

View File

@ -35647,10 +35647,16 @@ registers using the capitalization used in the description.
@subsection ARM Features
@cindex target descriptions, ARM features
The @samp{org.gnu.gdb.arm.core} feature is required for ARM targets.
The @samp{org.gnu.gdb.arm.core} feature is required for non-M-profile
ARM targets.
It should contain registers @samp{r0} through @samp{r13}, @samp{sp},
@samp{lr}, @samp{pc}, and @samp{cpsr}.
For M-profile targets (e.g. Cortex-M3), the @samp{org.gnu.gdb.arm.core}
feature is replaced by @samp{org.gnu.gdb.arm.m-profile}. It should contain
registers @samp{r0} through @samp{r13}, @samp{sp}, @samp{lr}, @samp{pc},
and @samp{xpsr}.
The @samp{org.gnu.gdb.arm.fpa} feature is optional. If present, it
should contain registers @samp{f0} through @samp{f7} and @samp{fps}.

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2010 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.m-profile">
<reg name="r0" bitsize="32"/>
<reg name="r1" bitsize="32"/>
<reg name="r2" bitsize="32"/>
<reg name="r3" bitsize="32"/>
<reg name="r4" bitsize="32"/>
<reg name="r5" bitsize="32"/>
<reg name="r6" bitsize="32"/>
<reg name="r7" bitsize="32"/>
<reg name="r8" bitsize="32"/>
<reg name="r9" bitsize="32"/>
<reg name="r10" bitsize="32"/>
<reg name="r11" bitsize="32"/>
<reg name="r12" bitsize="32"/>
<reg name="sp" bitsize="32" type="data_ptr"/>
<reg name="lr" bitsize="32"/>
<reg name="pc" bitsize="32" type="code_ptr"/>
<reg name="xpsr" bitsize="32" regnum="25"/>
</feature>

35
gdb/features/arm-with-m.c Normal file
View File

@ -0,0 +1,35 @@
/* THIS FILE IS GENERATED. Original: arm-with-m.xml */
#include "defs.h"
#include "osabi.h"
#include "target-descriptions.h"
struct target_desc *tdesc_arm_with_m;
static void
initialize_tdesc_arm_with_m (void)
{
struct target_desc *result = allocate_target_description ();
struct tdesc_feature *feature;
struct tdesc_type *field_type, *type;
feature = tdesc_create_feature (result, "org.gnu.gdb.arm.m-profile");
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, "xpsr", 25, 1, NULL, 32, "int");
tdesc_arm_with_m = result;
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!-- Copyright (C) 2010 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-m-profile.xml"/>
</target>