Re: [patch] Add support for ARMv7M devices.

Daniel Jacobowitz
2010-08-16T18:06:10Z

On Thu, Jun 24, 2010 at 09:03:52PM +0100, Richard Earnshaw wrote:
> I'd suggest
>
> org.gnu.gdb.arm.m-profile

Here's a version addressing comments from Richard, Matthew, and Doug,
and also incorporating Jonathan Larmour's changes.

I've moved the is_m check lower in arm_pc_is_thumb, to make "set arm
force-mode" continue to do something sensible; you could arguably push
it further down, but this is at least an improvement.

Tested on ARM EABI and by hand; any comments? Jonathan, how's this
work for you? If your target does not give GDB any registers, then
this ought to just switch an M-profile binary over to the xpsr. If
your debug stub previously sends a bogus "cpsr", then it's hard to say
what will happen. I wouldn't be surprised at an error - any target
which does that, probably also supplies the FPA registers. If it's
really necessary, we can try to auto-detect that case in the remote
protocol, but really this is what the XML register descriptions are
for.

--
Daniel Jacobowitz
CodeSourcery

2010-08-16 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.

* gdb.texinfo (ARM Features): Document
org.gnu.gdb.arm.m-profile.

Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.304
diff -u -p -r1.304 arm-tdep.c
--- arm-tdep.c 27 May 2010 19:06:12 -0000 1.304
+++ arm-tdep.c 16 Aug 2010 16:00:57 -0000
@@ -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 (s

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 *f
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 (st
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 *gdbar
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 *gdbar

/* 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
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_i
{
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_i
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 *gdb

/* 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 *gdb
&& TYPE_CODE_FUNC == TYPE_CODE (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 gd
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, ULON
/* 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
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 *
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 gd

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 gdbarc
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,13 +6436,158 @@ arm_gdbarch_init (struct gdbarch_info in
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;
+ const struct target_desc *tdesc = info.target_desc;
+
+ /* If we have an object to base this architecture on, try to determine
+ its ABI. */
+
+ if (arm_abi == ARM_ABI_AUTO && info.abfd != NULL)
+ {
+ int ei_osabi, e_flags;
+
+ switch (bfd_get_flavour (info.abfd))
+ {
+ case bfd_target_aout_flavour:
+ /* Assume it's an old APCS-style ABI. */
+ arm_abi = ARM_ABI_APCS;
+ break;
+
+ case bfd_target_coff_flavour:
+ /* Assume it's an old APCS-style ABI. */
+ /* XXX WinCE? */
+ arm_abi = ARM_ABI_APCS;
+ break;
+
+ case bfd_target_elf_flavour:
+ ei_osabi = elf_elfheader (info.abfd)->e_ident[EI_OSABI];
+ e_flags = elf_elfheader (info.abfd)->e_flags;
+
+ if (ei_osabi == ELFOSABI_ARM)
+ {
+ /* GNU tools used to use this value, but do not for EABI
+ objects. There's nowhere to tag an EABI version
+ anyway, so assume APCS. */
+ arm_abi = ARM_ABI_APCS;
+ }
+ else if (ei_osabi == ELFOSABI_NONE)
+ {
+ int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
+ int attr;
+
+ switch (eabi_ver)
+ {
+ case EF_ARM_EABI_UNKNOWN:
+ /* Assume GNU tools. */
+ arm_abi = ARM_ABI_APCS;
+ break;
+
+ case EF_ARM_EABI_VER4:
+ case EF_ARM_EABI_VER5:
+ arm_abi = ARM_ABI_AAPCS;
+ /* EABI binaries default to VFP float ordering.
+ They may also contain build attributes that can
+ be used to identify if the VFP argument-passing
+ ABI is in use. */
+ if (fp_model == ARM_FLOAT_AUTO)
+ {
+#ifdef HAVE_ELF
+ switch (bfd_elf_get_obj_attr_int (info.abfd,
+ OBJ_ATTR_PROC,
+ Tag_ABI_VFP_args))
+ {
+ case 0:
+ /* "The user intended FP parameter/result
+ passing to conform to AAPCS, base
+ variant". */
+ fp_model = ARM_FLOAT_SOFT_VFP;
+ break;
+ case 1:
+ /* "The user intended FP parameter/result
+ passing to conform to AAPCS, VFP
+ variant". */
+ fp_model = ARM_FLOAT_VFP;
+ break;
+ case 2:
+ /* "The user intended FP parameter/result
+ passing to conform to tool chain-specific
+ conventions" - we don't know any such
+ conventions, so leave it as "auto". */
+ break;
+ default:
+ /* Attribute value not mentioned in the
+ October 2008 ABI, so leave it as
+ "auto". */
+ break;
+ }
+#else
+ fp_model = ARM_FLOAT_SOFT_VFP;
+#endif
+ }
+ break;
+
+ default:
+ /* Leave it as "auto". */
+ warning (_("unknown ARM EABI version 0x%x"), eabi_ver);
+ break;
+ }
+
+#ifdef HAVE_ELF
+ /* Detect M-profile programs. */
+ attr = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch);
+ /* The lowest value with a meaningful profile is V7; V6-M
+ has a higher attribute value. */
+ if (attr >= TAG_CPU_ARCH_V7)
+ {
+ attr = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
+ Tag_CPU_arch_profile);
+ if (attr == 'M' && ! tdesc_has_registers (tdesc))
+ tdesc = tdesc_arm_with_m;
+ }
+#endif
+ }
+
+ if (fp_model == ARM_FLOAT_AUTO)
+ {
+ int e_flags = elf_elfheader (info.abfd)->e_flags;
+
+ switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
+ {
+ case 0:
+ /* Leave it as "auto". Strictly speaking this case
+ means FPA, but almost nobody uses that now, and
+ many toolchains fail to set the appropriate bits
+ for the floating-point model they use. */
+ break;
+ case EF_ARM_SOFT_FLOAT:
+ fp_model = ARM_FLOAT_SOFT_FPA;
+ break;
+ case EF_ARM_VFP_FLOAT:
+ fp_model = ARM_FLOAT_VFP;
+ break;
+ case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
+ fp_model = ARM_FLOAT_SOFT_VFP;
+ break;
+ }
+ }
+
+ if (e_flags & EF_ARM_BE8)
+ info.byte_order_for_code = BFD_ENDIAN_LITTLE;
+
+ break;
+
+ default:
+ /* Leave it as "auto". */
+ break;
+ }
+ }

/* Check any target description for validity. */
- if (tdesc_has_registers (info.target_desc))
+ 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. */
@@ -6428,10 +6598,17 @@ arm_gdbarch_init (struct gdbarch_info in
const struct tdesc_feature *feature;
int valid_p;

- feature = tdesc_find_feature (info.target_desc,
+ feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.core");
if (feature == NULL)
- return 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 ();

@@ -6448,8 +6625,12 @@ arm_gdbarch_init (struct gdbarch_info in
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 (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)
{
@@ -6457,7 +6638,7 @@ arm_gdbarch_init (struct gdbarch_info in
return NULL;
}

- feature = tdesc_find_feature (info.target_desc,
+ feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.fpa");
if (feature != NULL)
{
@@ -6474,7 +6655,7 @@ arm_gdbarch_init (struct gdbarch_info in
else
have_fpa_registers = 0;

- feature = tdesc_find_feature (info.target_desc,
+ feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.xscale.iwmmxt");
if (feature != NULL)
{
@@ -6512,7 +6693,7 @@ arm_gdbarch_init (struct gdbarch_info in
/* 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,
+ feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.vfp");
if (feature != NULL)
{
@@ -6549,7 +6730,7 @@ arm_gdbarch_init (struct gdbarch_info in
/* 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,
+ feature = tdesc_find_feature (tdesc,
"org.gnu.gdb.arm.neon");
if (feature != NULL)
{
@@ -6571,134 +6752,6 @@ arm_gdbarch_init (struct gdbarch_info in
}
}

- /* If we have an object to base this architecture on, try to determine
- its ABI. */
-
- if (arm_abi == ARM_ABI_AUTO && info.abfd != NULL)
- {
- int ei_osabi, e_flags;
-
- switch (bfd_get_flavour (info.abfd))
- {
- case bfd_target_aout_flavour:
- /* Assume it's an old APCS-style ABI. */
- arm_abi = ARM_ABI_APCS;
- break;
-
- case bfd_target_coff_flavour:
- /* Assume it's an old APCS-style ABI. */
- /* XXX WinCE? */
- arm_abi = ARM_ABI_APCS;
- break;
-
- case bfd_target_elf_flavour:
- ei_osabi = elf_elfheader (info.abfd)->e_ident[EI_OSABI];
- e_flags = elf_elfheader (info.abfd)->e_flags;
-
- if (ei_osabi == ELFOSABI_ARM)
- {
- /* GNU tools used to use this value, but do not for EABI
- objects. There's nowhere to tag an EABI version
- anyway, so assume APCS. */
- arm_abi = ARM_ABI_APCS;
- }
- else if (ei_osabi == ELFOSABI_NONE)
- {
- int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
-
- switch (eabi_ver)
- {
- case EF_ARM_EABI_UNKNOWN:
- /* Assume GNU tools. */
- arm_abi = ARM_ABI_APCS;
- break;
-
- case EF_ARM_EABI_VER4:
- case EF_ARM_EABI_VER5:
- arm_abi = ARM_ABI_AAPCS;
- /* EABI binaries default to VFP float ordering.
- They may also contain build attributes that can
- be used to identify if the VFP argument-passing
- ABI is in use. */
- if (fp_model == ARM_FLOAT_AUTO)
- {
-#ifdef HAVE_ELF
- switch (bfd_elf_get_obj_attr_int (info.abfd,
- OBJ_ATTR_PROC,
- Tag_ABI_VFP_args))
- {
- case 0:
- /* "The user intended FP parameter/result
- passing to conform to AAPCS, base
- variant". */
- fp_model = ARM_FLOAT_SOFT_VFP;
- break;
- case 1:
- /* "The user intended FP parameter/result
- passing to conform to AAPCS, VFP
- variant". */
- fp_model = ARM_FLOAT_VFP;
- break;
- case 2:
- /* "The user intended FP parameter/result
- passing to conform to tool chain-specific
- conventions" - we don't know any such
- conventions, so leave it as "auto". */
- break;
- default:
- /* Attribute value not mentioned in the
- October 2008 ABI, so leave it as
- "auto". */
- break;
- }
-#else
- fp_model = ARM_FLOAT_SOFT_VFP;
-#endif
- }
- break;
-
- default:
- /* Leave it as "auto". */
- warning (_("unknown ARM EABI version 0x%x"), eabi_ver);
- break;
- }
- }
-
- if (fp_model == ARM_FLOAT_AUTO)
- {
- int e_flags = elf_elfheader (info.abfd)->e_flags;
-
- switch (e_flags & (EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT))
- {
- case 0:
- /* Leave it as "auto". Strictly speaking this case
- means FPA, but almost nobody uses that now, and
- many toolchains fail to set the appropriate bits
- for the floating-point model they use. */
- break;
- case EF_ARM_SOFT_FLOAT:
- fp_model = ARM_FLOAT_SOFT_FPA;
- break;
- case EF_ARM_VFP_FLOAT:
- fp_model = ARM_FLOAT_VFP;
- break;
- case EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT:
- fp_model = ARM_FLOAT_SOFT_VFP;
- break;
- }
- }
-
- if (e_flags & EF_ARM_BE8)
- info.byte_order_for_code = BFD_ENDIAN_LITTLE;
-
- break;
-
- default:
- /* Leave it as "auto". */
- break;
- }
- }
-
/* If there is already a candidate, use it. */
for (best_arch = gdbarch_list_lookup_by_info (arches, &info);
best_arch != NULL;
@@ -6717,6 +6770,10 @@ arm_gdbarch_init (struct gdbarch_info in
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 +6792,7 @@ arm_gdbarch_init (struct gdbarch_info in
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 +6966,7 @@ arm_gdbarch_init (struct gdbarch_info in
{
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 +7021,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 ();

Index: arm-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.h,v
retrieving revision 1.40
diff -u -p -r1.40 arm-tdep.h
--- arm-tdep.h 12 Apr 2010 13:52:43 -0000 1.40
+++ arm-tdep.h 16 Aug 2010 16:00:57 -0000
@@ -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. */

Index: features/arm-m-profile.xml
===================================================================
RCS file: features/arm-m-profile.xml
diff -N features/arm-m-profile.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ features/arm-m-profile.xml 16 Aug 2010 16:00:58 -0000
@@ -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. -->
+
+
+<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>
Index: features/arm-with-m.c
===================================================================
RCS file: features/arm-with-m.c
diff -N features/arm-with-m.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ features/arm-with-m.c 16 Aug 2010 16:00:58 -0000
@@ -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;
+}
Index: features/arm-with-m.xml
===================================================================
RCS file: features/arm-with-m.xml
diff -N features/arm-with-m.xml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ features/arm-with-m.xml 16 Aug 2010 16:00:58 -0000
@@ -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. -->
+
+
+<target>
+ <xi:include href="arm-m-profile.xml"/>
+</target>
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.754
diff -u -p -r1.754 gdb.texinfo
--- doc/gdb.texinfo 13 Aug 2010 20:39:09 -0000 1.754
+++ doc/gdb.texinfo 16 Aug 2010 18:00:40 -0000
@@ -35606,10 +35606,16 @@ registers using the capitalization used
@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}.

`