* arm-tdep.c: Include features/arm-with-m.c.
authorDaniel Jacobowitz <drow@false.org>
Tue, 24 Aug 2010 15:56:15 +0000 (15:56 +0000)
committerDaniel Jacobowitz <drow@false.org>
Tue, 24 Aug 2010 15:56:15 +0000 (15:56 +0000)
(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.

gdb/ChangeLog
gdb/arm-tdep.c
gdb/arm-tdep.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/features/arm-m-profile.xml [new file with mode: 0644]
gdb/features/arm-with-m.c [new file with mode: 0644]
gdb/features/arm-with-m.xml [new file with mode: 0644]

index 9d8af7754d320fd3d932d038f524aee199aa4f99..19416118efa1b483dc943a6762b3bf9d2a39d77d 100644 (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.
index 1ac8817f282c02116196c7c26dd20e891dc24d0a..5a7e76d711ac54cd838e299556dbbf3181fca780 100644 (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,13 +6436,163 @@ 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;
+  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_arch, attr_profile;
+
+             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.  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)
+           {
+             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 +6603,17 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       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 +6630,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       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 +6643,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          return NULL;
        }
 
-      feature = tdesc_find_feature (info.target_desc,
+      feature = tdesc_find_feature (tdesc,
                                    "org.gnu.gdb.arm.fpa");
       if (feature != NULL)
        {
@@ -6474,7 +6660,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       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 +6698,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       /* 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 +6735,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          /* 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 +6757,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
        }
     }
 
-  /* 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 +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 ();
 
index b6283efb91c0110c876202ca5990a05765a3501c..87387aabb64cfac84c04b951549abe71f9123710 100644 (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.  */
 
index a864e2f5c7bc998537b27c068d853095e4adcbea..d66b613e569aa7596f08e5ec4120a893c9950da2 100644 (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:
index d0c7dddac4bb6f850aa4d19e86baf5aa32a68bb1..3418eb2fc6b6b5c49558e736f730564f66be902a 100644 (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}.
 
diff --git a/gdb/features/arm-m-profile.xml b/gdb/features/arm-m-profile.xml
new file mode 100644 (file)
index 0000000..b88e9e6
--- /dev/null
@@ -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>
diff --git a/gdb/features/arm-with-m.c b/gdb/features/arm-with-m.c
new file mode 100644 (file)
index 0000000..b188f57
--- /dev/null
@@ -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;
+}
diff --git a/gdb/features/arm-with-m.xml b/gdb/features/arm-with-m.xml
new file mode 100644 (file)
index 0000000..227b920
--- /dev/null
@@ -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>