]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdb/arm-tdep.c
Fix exception stack unwinding for ARM Cortex-M
[thirdparty/binutils-gdb.git] / gdb / arm-tdep.c
index ac92c88b5981d154505b6348b35c5e5c8cff59f2..1a5017495adf9cf2c5e7d2438a455dadefd24710 100644 (file)
@@ -1,6 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
 
-   Copyright (C) 1988-2017 Free Software Foundation, Inc.
+   Copyright (C) 1988-2020 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "frame-base.h"
 #include "trad-frame.h"
 #include "objfiles.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
 #include "gdbtypes.h"
 #include "prologue-value.h"
 #include "remote.h"
 #include "target-descriptions.h"
 #include "user-regs.h"
-#include "observer.h"
+#include "observable.h"
+#include "count-one-bits.h"
 
 #include "arch/arm.h"
 #include "arch/arm-get-next-pcs.h"
 #include "coff/internal.h"
 #include "elf/arm.h"
 
-#include "vec.h"
-
 #include "record.h"
 #include "record-full.h"
 #include <algorithm>
 
-#include "features/arm/arm-with-m.c"
-#include "features/arm/arm-with-m-fpa-layout.c"
-#include "features/arm/arm-with-m-vfp-d16.c"
-#include "features/arm/arm-with-iwmmxt.c"
-#include "features/arm/arm-with-vfpv2.c"
-#include "features/arm/arm-with-vfpv3.c"
-#include "features/arm/arm-with-neon.c"
+#include "producer.h"
 
 #if GDB_SELF_TEST
-#include "selftest.h"
+#include "gdbsupport/selftest.h"
 #endif
 
-static int arm_debug;
+static bool arm_debug;
 
 /* Macros for setting and testing a bit in a minimal symbol that marks
    it as Thumb function.  The MSB of the minimal symbol's "info" field
@@ -88,22 +81,44 @@ static int arm_debug;
 #define MSYMBOL_IS_SPECIAL(msym)                               \
        MSYMBOL_TARGET_FLAG_1 (msym)
 
-/* Per-objfile data used for mapping symbols.  */
-static const struct objfile_data *arm_objfile_data_key;
-
 struct arm_mapping_symbol
 {
-  bfd_vma value;
+  CORE_ADDR value;
   char type;
+
+  bool operator< (const arm_mapping_symbol &other) const
+  { return this->value < other.value; }
 };
-typedef struct arm_mapping_symbol arm_mapping_symbol_s;
-DEF_VEC_O(arm_mapping_symbol_s);
 
-struct arm_per_objfile
+typedef std::vector<arm_mapping_symbol> arm_mapping_symbol_vec;
+
+struct arm_per_bfd
 {
-  VEC(arm_mapping_symbol_s) **section_maps;
+  explicit arm_per_bfd (size_t num_sections)
+  : section_maps (new arm_mapping_symbol_vec[num_sections]),
+    section_maps_sorted (new bool[num_sections] ())
+  {}
+
+  DISABLE_COPY_AND_ASSIGN (arm_per_bfd);
+
+  /* Information about mapping symbols ($a, $d, $t) in the objfile.
+
+     The format is an array of vectors of arm_mapping_symbols, there is one
+     vector for each section of the objfile (the array is index by BFD section
+     index).
+
+     For each section, the vector of arm_mapping_symbol is sorted by
+     symbol value (address).  */
+  std::unique_ptr<arm_mapping_symbol_vec[]> section_maps;
+
+  /* For each corresponding element of section_maps above, is this vector
+     sorted.  */
+  std::unique_ptr<bool[]> section_maps_sorted;
 };
 
+/* Per-bfd data used for mapping symbols.  */
+static bfd_key<arm_per_bfd> arm_bfd_data_key;
+
 /* The list of available "set arm ..." and "show arm ..." commands.  */
 static struct cmd_list_element *setarmcmdlist = NULL;
 static struct cmd_list_element *showarmcmdlist = NULL;
@@ -218,6 +233,10 @@ static const char **valid_disassembly_styles;
 /* Disassembly style to use. Default to "std" register names.  */
 static const char *disassembly_style;
 
+/* All possible arm target descriptors.  */
+static struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];
+static struct target_desc *tdesc_arm_mprofile_list[ARM_M_TYPE_INVALID];
+
 /* This is used to keep the bfd arch_info in sync with the disassembly
    style.  */
 static void set_disassembly_style_sfunc (const char *, int,
@@ -227,7 +246,7 @@ static void show_disassembly_style_sfunc (struct ui_file *, int,
                                          const char *);
 
 static enum register_status arm_neon_quad_read (struct gdbarch *gdbarch,
-                                               struct regcache *regcache,
+                                               readable_regcache *regcache,
                                                int regnum, gdb_byte *buf);
 static void arm_neon_quad_write (struct gdbarch *gdbarch,
                                 struct regcache *regcache,
@@ -276,9 +295,9 @@ static CORE_ADDR arm_analyze_prologue (struct gdbarch *gdbarch,
 
 #define DISPLACED_STEPPING_ARCH_VERSION                5
 
-/* Set to true if the 32-bit mode is in use.  */
+/* See arm-tdep.h.  */
 
-int arm_apcs_32 = 1;
+bool arm_apcs_32 = true;
 
 /* Return the bit mask in ARM_PS_REGNUM that indicates Thumb mode.  */
 
@@ -321,15 +340,6 @@ arm_frame_is_thumb (struct frame_info *frame)
   return (cpsr & t_bit) != 0;
 }
 
-/* Callback for VEC_lower_bound.  */
-
-static inline int
-arm_compare_mapping_symbols (const struct arm_mapping_symbol *lhs,
-                            const struct arm_mapping_symbol *rhs)
-{
-  return lhs->value < rhs->value;
-}
-
 /* Search for the mapping symbol covering MEMADDR.  If one is found,
    return its type.  Otherwise, return 0.  If START is non-NULL,
    set *START to the location of the mapping symbol.  */
@@ -343,47 +353,48 @@ arm_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
   sec = find_pc_section (memaddr);
   if (sec != NULL)
     {
-      struct arm_per_objfile *data;
-      VEC(arm_mapping_symbol_s) *map;
-      struct arm_mapping_symbol map_key = { memaddr - obj_section_addr (sec),
-                                           0 };
-      unsigned int idx;
-
-      data = (struct arm_per_objfile *) objfile_data (sec->objfile,
-                                                     arm_objfile_data_key);
+      arm_per_bfd *data = arm_bfd_data_key.get (sec->objfile->obfd);
       if (data != NULL)
        {
-         map = data->section_maps[sec->the_bfd_section->index];
-         if (!VEC_empty (arm_mapping_symbol_s, map))
-           {
-             struct arm_mapping_symbol *map_sym;
+         unsigned int section_idx = sec->the_bfd_section->index;
+         arm_mapping_symbol_vec &map
+           = data->section_maps[section_idx];
 
-             idx = VEC_lower_bound (arm_mapping_symbol_s, map, &map_key,
-                                    arm_compare_mapping_symbols);
+         /* Sort the vector on first use.  */
+         if (!data->section_maps_sorted[section_idx])
+           {
+             std::sort (map.begin (), map.end ());
+             data->section_maps_sorted[section_idx] = true;
+           }
 
-             /* VEC_lower_bound finds the earliest ordered insertion
-                point.  If the following symbol starts at this exact
-                address, we use that; otherwise, the preceding
-                mapping symbol covers this address.  */
-             if (idx < VEC_length (arm_mapping_symbol_s, map))
-               {
-                 map_sym = VEC_index (arm_mapping_symbol_s, map, idx);
-                 if (map_sym->value == map_key.value)
-                   {
-                     if (start)
-                       *start = map_sym->value + obj_section_addr (sec);
-                     return map_sym->type;
-                   }
-               }
+         struct arm_mapping_symbol map_key
+           = { memaddr - obj_section_addr (sec), 0 };
+         arm_mapping_symbol_vec::const_iterator it
+           = std::lower_bound (map.begin (), map.end (), map_key);
 
-             if (idx > 0)
+         /* std::lower_bound finds the earliest ordered insertion
+            point.  If the symbol at this position starts at this exact
+            address, we use that; otherwise, the preceding
+            mapping symbol covers this address.  */
+         if (it < map.end ())
+           {
+             if (it->value == map_key.value)
                {
-                 map_sym = VEC_index (arm_mapping_symbol_s, map, idx - 1);
                  if (start)
-                   *start = map_sym->value + obj_section_addr (sec);
-                 return map_sym->type;
+                   *start = it->value + obj_section_addr (sec);
+                 return it->type;
                }
            }
+
+         if (it > map.begin ())
+           {
+             arm_mapping_symbol_vec::const_iterator prev_it
+               = it - 1;
+
+             if (start)
+               *start = prev_it->value + obj_section_addr (sec);
+             return prev_it->type;
+           }
        }
     }
 
@@ -458,7 +469,7 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 }
 
 /* Determine if the address specified equals any of these magic return
-   values, called EXC_RETURN, defined by the ARM v6-M and v7-M
+   values, called EXC_RETURN, defined by the ARM v6-M, v7-M and v8-M
    architectures.
 
    From ARMv6-M Reference Manual B1.5.8
@@ -489,13 +500,25 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
    0xFFFFFFFD    Thread mode      Process         Basic
 
    For more details see "B1.5.8 Exception return behavior"
-   in both ARMv6-M and ARMv7-M Architecture Reference Manuals.  */
+   in both ARMv6-M and ARMv7-M Architecture Reference Manuals.
+
+   In the ARMv8-M Architecture Technical Reference also adds
+   for implementations without the Security Extension:
+
+   EXC_RETURN    Condition
+   0xFFFFFFB0    Return to Handler mode.
+   0xFFFFFFB8    Return to Thread mode using the main stack.
+   0xFFFFFFBC    Return to Thread mode using the process stack.  */
 
 static int
 arm_m_addr_is_magic (CORE_ADDR addr)
 {
   switch (addr)
     {
+      /* Values from ARMv8-M Architecture Technical Reference.  */
+      case 0xffffffb0:
+      case 0xffffffb8:
+      case 0xffffffbc:
       /* Values from Tables in B1.5.8 the EXC_RETURN definitions of
         the exception return behavior.  */
       case 0xffffffe1:
@@ -542,9 +565,9 @@ skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
   msym = lookup_minimal_symbol_by_pc (pc);
   if (msym.minsym != NULL
       && BMSYMBOL_VALUE_ADDRESS (msym) == pc
-      && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL)
+      && msym.minsym->linkage_name () != NULL)
     {
-      const char *name = MSYMBOL_LINKAGE_NAME (msym.minsym);
+      const char *name = msym.minsym->linkage_name ();
 
       /* The GNU linker's Thumb call stub to foo is named
         __foo_from_thumb.  */
@@ -922,7 +945,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
               parameters from memory.  */
            ;
 
-         else if ((insn & 0xffb0) == 0xe950    /* ldrd Rt, Rt2,
+         else if ((insn & 0xff70) == 0xe950    /* ldrd Rt, Rt2,
                                                   [Rn, #+/-imm] */
                   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
            /* Similarly ignore dual loads from the stack.  */
@@ -1246,7 +1269,7 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
   /* ADDR must correspond to a symbol whose name is __stack_chk_guard.
      Otherwise, this sequence cannot be for stack protector.  */
   if (stack_chk_guard.minsym == NULL
-      || !startswith (MSYMBOL_LINKAGE_NAME (stack_chk_guard.minsym), "__stack_chk_guard"))
+      || !startswith (stack_chk_guard.minsym->linkage_name (), "__stack_chk_guard"))
    return pc;
 
   if (is_thumb)
@@ -1342,7 +1365,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
          && (cust == NULL
              || COMPUNIT_PRODUCER (cust) == NULL
              || startswith (COMPUNIT_PRODUCER (cust), "GNU ")
-             || startswith (COMPUNIT_PRODUCER (cust), "clang ")))
+             || producer_is_llvm (COMPUNIT_PRODUCER (cust))))
        return post_prologue_pc;
 
       if (post_prologue_pc != 0)
@@ -1801,6 +1824,10 @@ arm_scan_prologue (struct frame_info *this_frame,
       CORE_ADDR frame_loc;
       ULONGEST return_value;
 
+      /* AAPCS does not use a frame register, so we can abort here.  */
+      if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_AAPCS)
+        return;
+
       frame_loc = get_frame_register_unsigned (this_frame, ARM_FP_REGNUM);
       if (!safe_read_memory_unsigned_integer (frame_loc, 4, byte_order,
                                              &return_value))
@@ -1971,37 +1998,24 @@ struct frame_unwind arm_prologue_unwind = {
    personality routines; the cache will contain only the frame unwinding
    instructions associated with the entry (not the descriptors).  */
 
-static const struct objfile_data *arm_exidx_data_key;
-
 struct arm_exidx_entry
 {
-  bfd_vma addr;
+  CORE_ADDR addr;
   gdb_byte *entry;
+
+  bool operator< (const arm_exidx_entry &other) const
+  {
+    return addr < other.addr;
+  }
 };
-typedef struct arm_exidx_entry arm_exidx_entry_s;
-DEF_VEC_O(arm_exidx_entry_s);
 
 struct arm_exidx_data
 {
-  VEC(arm_exidx_entry_s) **section_maps;
+  std::vector<std::vector<arm_exidx_entry>> section_maps;
 };
 
-static void
-arm_exidx_data_free (struct objfile *objfile, void *arg)
-{
-  struct arm_exidx_data *data = (struct arm_exidx_data *) arg;
-  unsigned int i;
-
-  for (i = 0; i < objfile->obfd->section_count; i++)
-    VEC_free (arm_exidx_entry_s, data->section_maps[i]);
-}
-
-static inline int
-arm_compare_exidx_entries (const struct arm_exidx_entry *lhs,
-                          const struct arm_exidx_entry *rhs)
-{
-  return lhs->addr < rhs->addr;
-}
+/* Per-BFD key to store exception handling information.  */
+static const struct bfd_key<arm_exidx_data> arm_exidx_data_key;
 
 static struct obj_section *
 arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
@@ -2009,12 +2023,11 @@ arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
   struct obj_section *osect;
 
   ALL_OBJFILE_OSECTIONS (objfile, osect)
-    if (bfd_get_section_flags (objfile->obfd,
-                              osect->the_bfd_section) & SEC_ALLOC)
+    if (bfd_section_flags (osect->the_bfd_section) & SEC_ALLOC)
       {
        bfd_vma start, size;
-       start = bfd_get_section_vma (objfile->obfd, osect->the_bfd_section);
-       size = bfd_get_section_size (osect->the_bfd_section);
+       start = bfd_section_vma (osect->the_bfd_section);
+       size = bfd_section_size (osect->the_bfd_section);
 
        if (start <= vma && vma < start + size)
          return osect;
@@ -2040,65 +2053,53 @@ arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
 static void
 arm_exidx_new_objfile (struct objfile *objfile)
 {
-  struct cleanup *cleanups;
   struct arm_exidx_data *data;
   asection *exidx, *extab;
   bfd_vma exidx_vma = 0, extab_vma = 0;
-  bfd_size_type exidx_size = 0, extab_size = 0;
-  gdb_byte *exidx_data = NULL, *extab_data = NULL;
   LONGEST i;
 
   /* If we've already touched this file, do nothing.  */
-  if (!objfile || objfile_data (objfile, arm_exidx_data_key) != NULL)
+  if (!objfile || arm_exidx_data_key.get (objfile->obfd) != NULL)
     return;
-  cleanups = make_cleanup (null_cleanup, NULL);
 
   /* Read contents of exception table and index.  */
   exidx = bfd_get_section_by_name (objfile->obfd, ELF_STRING_ARM_unwind);
+  gdb::byte_vector exidx_data;
   if (exidx)
     {
-      exidx_vma = bfd_section_vma (objfile->obfd, exidx);
-      exidx_size = bfd_get_section_size (exidx);
-      exidx_data = (gdb_byte *) xmalloc (exidx_size);
-      make_cleanup (xfree, exidx_data);
+      exidx_vma = bfd_section_vma (exidx);
+      exidx_data.resize (bfd_section_size (exidx));
 
       if (!bfd_get_section_contents (objfile->obfd, exidx,
-                                    exidx_data, 0, exidx_size))
-       {
-         do_cleanups (cleanups);
-         return;
-       }
+                                    exidx_data.data (), 0,
+                                    exidx_data.size ()))
+       return;
     }
 
   extab = bfd_get_section_by_name (objfile->obfd, ".ARM.extab");
+  gdb::byte_vector extab_data;
   if (extab)
     {
-      extab_vma = bfd_section_vma (objfile->obfd, extab);
-      extab_size = bfd_get_section_size (extab);
-      extab_data = (gdb_byte *) xmalloc (extab_size);
-      make_cleanup (xfree, extab_data);
+      extab_vma = bfd_section_vma (extab);
+      extab_data.resize (bfd_section_size (extab));
 
       if (!bfd_get_section_contents (objfile->obfd, extab,
-                                    extab_data, 0, extab_size))
-       {
-         do_cleanups (cleanups);
-         return;
-       }
+                                    extab_data.data (), 0,
+                                    extab_data.size ()))
+       return;
     }
 
   /* Allocate exception table data structure.  */
-  data = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct arm_exidx_data);
-  set_objfile_data (objfile, arm_exidx_data_key, data);
-  data->section_maps = OBSTACK_CALLOC (&objfile->objfile_obstack,
-                                      objfile->obfd->section_count,
-                                      VEC(arm_exidx_entry_s) *);
+  data = arm_exidx_data_key.emplace (objfile->obfd);
+  data->section_maps.resize (objfile->obfd->section_count);
 
   /* Fill in exception table.  */
-  for (i = 0; i < exidx_size / 8; i++)
+  for (i = 0; i < exidx_data.size () / 8; i++)
     {
       struct arm_exidx_entry new_exidx_entry;
-      bfd_vma idx = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8);
-      bfd_vma val = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8 + 4);
+      bfd_vma idx = bfd_h_get_32 (objfile->obfd, exidx_data.data () + i * 8);
+      bfd_vma val = bfd_h_get_32 (objfile->obfd,
+                                 exidx_data.data () + i * 8 + 4);
       bfd_vma addr = 0, word = 0;
       int n_bytes = 0, n_words = 0;
       struct obj_section *sec;
@@ -2112,7 +2113,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
       sec = arm_obj_section_from_vma (objfile, idx);
       if (sec == NULL)
        continue;
-      idx -= bfd_get_section_vma (objfile->obfd, sec->the_bfd_section);
+      idx -= bfd_section_vma (sec->the_bfd_section);
 
       /* Determine address of exception table entry.  */
       if (val == 1)
@@ -2132,10 +2133,10 @@ arm_exidx_new_objfile (struct objfile *objfile)
          addr = ((val & 0x7fffffff) ^ 0x40000000) - 0x40000000;
          addr += exidx_vma + i * 8 + 4;
 
-         if (addr >= extab_vma && addr + 4 <= extab_vma + extab_size)
+         if (addr >= extab_vma && addr + 4 <= extab_vma + extab_data.size ())
            {
              word = bfd_h_get_32 (objfile->obfd,
-                                  extab_data + addr - extab_vma);
+                                  extab_data.data () + addr - extab_vma);
              addr += 4;
 
              if ((word & 0xff000000) == 0x80000000)
@@ -2190,10 +2191,11 @@ arm_exidx_new_objfile (struct objfile *objfile)
                     byte, followed by the same unwind instructions as the
                     pre-defined forms.  */
                  if (gnu_personality
-                     && addr + 4 <= extab_vma + extab_size)
+                     && addr + 4 <= extab_vma + extab_data.size ())
                    {
                      word = bfd_h_get_32 (objfile->obfd,
-                                          extab_data + addr - extab_vma);
+                                          (extab_data.data ()
+                                           + addr - extab_vma));
                      addr += 4;
                      n_bytes = 3;
                      n_words = ((word >> 24) & 0xff);
@@ -2204,7 +2206,8 @@ arm_exidx_new_objfile (struct objfile *objfile)
 
       /* Sanity check address.  */
       if (n_words)
-       if (addr < extab_vma || addr + 4 * n_words > extab_vma + extab_size)
+       if (addr < extab_vma
+           || addr + 4 * n_words > extab_vma + extab_data.size ())
          n_words = n_bytes = 0;
 
       /* The unwind instructions reside in WORD (only the N_BYTES least
@@ -2222,7 +2225,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
          while (n_words--)
            {
              word = bfd_h_get_32 (objfile->obfd,
-                                  extab_data + addr - extab_vma);
+                                  extab_data.data () + addr - extab_vma);
              addr += 4;
 
              *p++ = (gdb_byte) ((word >> 24) & 0xff);
@@ -2239,12 +2242,9 @@ arm_exidx_new_objfile (struct objfile *objfile)
         appear in order of increasing addresses.  */
       new_exidx_entry.addr = idx;
       new_exidx_entry.entry = entry;
-      VEC_safe_push (arm_exidx_entry_s,
-                    data->section_maps[sec->the_bfd_section->index],
-                    &new_exidx_entry);
+      data->section_maps[sec->the_bfd_section->index].push_back
+       (new_exidx_entry);
     }
-
-  do_cleanups (cleanups);
 }
 
 /* Search for the exception table entry covering MEMADDR.  If one is found,
@@ -2260,43 +2260,37 @@ arm_find_exidx_entry (CORE_ADDR memaddr, CORE_ADDR *start)
   if (sec != NULL)
     {
       struct arm_exidx_data *data;
-      VEC(arm_exidx_entry_s) *map;
       struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
-      unsigned int idx;
 
-      data = ((struct arm_exidx_data *)
-             objfile_data (sec->objfile, arm_exidx_data_key));
+      data = arm_exidx_data_key.get (sec->objfile->obfd);
       if (data != NULL)
        {
-         map = data->section_maps[sec->the_bfd_section->index];
-         if (!VEC_empty (arm_exidx_entry_s, map))
+         std::vector<arm_exidx_entry> &map
+           = data->section_maps[sec->the_bfd_section->index];
+         if (!map.empty ())
            {
-             struct arm_exidx_entry *map_sym;
-
-             idx = VEC_lower_bound (arm_exidx_entry_s, map, &map_key,
-                                    arm_compare_exidx_entries);
+             auto idx = std::lower_bound (map.begin (), map.end (), map_key);
 
-             /* VEC_lower_bound finds the earliest ordered insertion
+             /* std::lower_bound finds the earliest ordered insertion
                 point.  If the following symbol starts at this exact
                 address, we use that; otherwise, the preceding
                 exception table entry covers this address.  */
-             if (idx < VEC_length (arm_exidx_entry_s, map))
+             if (idx < map.end ())
                {
-                 map_sym = VEC_index (arm_exidx_entry_s, map, idx);
-                 if (map_sym->addr == map_key.addr)
+                 if (idx->addr == map_key.addr)
                    {
                      if (start)
-                       *start = map_sym->addr + obj_section_addr (sec);
-                     return map_sym->entry;
+                       *start = idx->addr + obj_section_addr (sec);
+                     return idx->entry;
                    }
                }
 
-             if (idx > 0)
+             if (idx > map.begin ())
                {
-                 map_sym = VEC_index (arm_exidx_entry_s, map, idx - 1);
+                 idx = idx - 1;
                  if (start)
-                   *start = map_sym->addr + obj_section_addr (sec);
-                 return map_sym->entry;
+                   *start = idx->addr + obj_section_addr (sec);
+                 return idx->entry;
                }
            }
        }
@@ -2941,14 +2935,64 @@ arm_m_exception_cache (struct frame_info *this_frame)
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct arm_prologue_cache *cache;
+  CORE_ADDR lr;
+  CORE_ADDR sp;
   CORE_ADDR unwound_sp;
   LONGEST xpsr;
+  uint32_t exc_return;
+  uint32_t process_stack_used;
+  uint32_t extended_frame_used;
+  uint32_t secure_stack_used;
 
   cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-  unwound_sp = get_frame_register_unsigned (this_frame,
-                                           ARM_SP_REGNUM);
+  /* ARMv7-M Architecture Reference "B1.5.6 Exception entry behavior"
+     describes which bits in LR that define which stack was used prior
+     to the exception and if FPU is used (causing extended stack frame).  */
+
+  lr = get_frame_register_unsigned (this_frame, ARM_LR_REGNUM);
+  sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+
+  /* Check EXC_RETURN indicator bits.  */
+  exc_return = (((lr >> 28) & 0xf) == 0xf);
+
+  /* Check EXC_RETURN bit SPSEL if Main or Thread (process) stack used.  */
+  process_stack_used = ((lr & (1 << 2)) != 0);
+  if (exc_return && process_stack_used)
+    {
+      /* Thread (process) stack used.
+         Potentially this could be other register defined by target, but PSP
+         can be considered a standard name for the "Process Stack Pointer".
+         To be fully aware of system registers like MSP and PSP, these could
+         be added to a separate XML arm-m-system-profile that is valid for
+         ARMv6-M and ARMv7-M architectures. Also to be able to debug eg a
+         corefile off-line, then these registers must be defined by GDB,
+         and also be included in the corefile regsets.  */
+
+      int psp_regnum = user_reg_map_name_to_regnum (gdbarch, "psp", -1);
+      if (psp_regnum == -1)
+        {
+          /* Thread (process) stack could not be fetched,
+             give warning and exit.  */
+
+          warning (_("no PSP thread stack unwinding supported."));
+
+          /* Terminate any further stack unwinding by refer to self.  */
+          cache->prev_sp = sp;
+          return cache;
+        }
+      else
+        {
+          /* Thread (process) stack used, use PSP as SP.  */
+          unwound_sp = get_frame_register_unsigned (this_frame, psp_regnum);
+        }
+    }
+  else
+    {
+      /* Main stack used, use MSP as SP.  */
+      unwound_sp = sp;
+    }
 
   /* The hardware saves eight 32-bit words, comprising xPSR,
      ReturnAddress, LR (R14), R12, R3, R2, R1, R0.  See details in
@@ -2958,15 +3002,62 @@ arm_m_exception_cache (struct frame_info *this_frame)
   cache->saved_regs[1].addr = unwound_sp + 4;
   cache->saved_regs[2].addr = unwound_sp + 8;
   cache->saved_regs[3].addr = unwound_sp + 12;
-  cache->saved_regs[12].addr = unwound_sp + 16;
-  cache->saved_regs[14].addr = unwound_sp + 20;
-  cache->saved_regs[15].addr = unwound_sp + 24;
+  cache->saved_regs[ARM_IP_REGNUM].addr = unwound_sp + 16;
+  cache->saved_regs[ARM_LR_REGNUM].addr = unwound_sp + 20;
+  cache->saved_regs[ARM_PC_REGNUM].addr = unwound_sp + 24;
   cache->saved_regs[ARM_PS_REGNUM].addr = unwound_sp + 28;
 
+  /* Check EXC_RETURN bit FTYPE if extended stack frame (FPU regs stored)
+     type used.  */
+  extended_frame_used = ((lr & (1 << 4)) == 0);
+  if (exc_return && extended_frame_used)
+    {
+      int i;
+      int fpu_regs_stack_offset;
+
+      /* This code does not take into account the lazy stacking, see "Lazy
+         context save of FP state", in B1.5.7, also ARM AN298, supported
+         by Cortex-M4F architecture.
+         To fully handle this the FPCCR register (Floating-point Context
+         Control Register) needs to be read out and the bits ASPEN and LSPEN
+         could be checked to setup correct lazy stacked FP registers.
+         This register is located at address 0xE000EF34.  */
+
+      /* Extended stack frame type used.  */
+      fpu_regs_stack_offset = unwound_sp + 0x20;
+      for (i = 0; i < 16; i++)
+        {
+          cache->saved_regs[ARM_D0_REGNUM + i].addr = fpu_regs_stack_offset;
+          fpu_regs_stack_offset += 4;
+        }
+      cache->saved_regs[ARM_FPSCR_REGNUM].addr = unwound_sp + 0x60;
+
+      /* Offset 0x64 is reserved.  */
+      cache->prev_sp = unwound_sp + 0x68;
+    }
+  else
+    {
+      /* Standard stack frame type used.  */
+      cache->prev_sp = unwound_sp + 0x20;
+    }
+
+  /* Check EXC_RETURN bit S if Secure or Non-secure stack used.  */
+  secure_stack_used = ((lr & (1 << 6)) != 0);
+  if (exc_return && secure_stack_used)
+    {
+      /* ARMv8-M Exception and interrupt handling is not considered here.
+        In the ARMv8-M architecture also EXC_RETURN bit S is controlling if
+        the Secure or Non-secure stack was used. To separate Secure and
+        Non-secure stacks, processors that are based on the ARMv8-M
+        architecture support 4 stack pointers: MSP_S, PSP_S, MSP_NS, PSP_NS.
+        In addition, a stack limit feature is provided using stack limit
+        registers (accessible using MSR and MRS instructions) in Privileged
+        level.  */
+    }
+
   /* If bit 9 of the saved xPSR is set, then there is a four-byte
      aligner between the top of the 32-byte stack frame and the
      previous context's stack pointer.  */
-  cache->prev_sp = unwound_sp + 32;
   if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr)
       && (xpsr & (1 << 9)) != 0)
     cache->prev_sp += 4;
@@ -3064,38 +3155,6 @@ struct frame_base arm_normal_base = {
   arm_normal_frame_base
 };
 
-/* Assuming THIS_FRAME is a dummy, return the frame ID of that
-   dummy frame.  The frame ID's base needs to match the TOS value
-   saved by save_dummy_frame_tos() and returned from
-   arm_push_dummy_call, and the PC needs to match the dummy frame's
-   breakpoint.  */
-
-static struct frame_id
-arm_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_id_build (get_frame_register_unsigned (this_frame,
-                                                     ARM_SP_REGNUM),
-                        get_frame_pc (this_frame));
-}
-
-/* Given THIS_FRAME, find the previous frame's resume PC (which will
-   be used to construct the previous frame's ID, after looking up the
-   containing function).  */
-
-static CORE_ADDR
-arm_unwind_pc (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  CORE_ADDR pc;
-  pc = frame_unwind_register_unsigned (this_frame, ARM_PC_REGNUM);
-  return arm_addr_bits_remove (gdbarch, pc);
-}
-
-static CORE_ADDR
-arm_unwind_sp (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
-  return frame_unwind_register_unsigned (this_frame, ARM_SP_REGNUM);
-}
-
 static struct value *
 arm_dwarf2_prev_register (struct frame_info *this_frame, void **this_cache,
                          int regnum)
@@ -3351,62 +3410,25 @@ pop_stack_item (struct stack_item *si)
   return si;
 }
 
+/* Implement the gdbarch type alignment method, overrides the generic
+   alignment algorithm for anything that is arm specific.  */
 
-/* Return the alignment (in bytes) of the given type.  */
-
-static int
-arm_type_align (struct type *t)
+static ULONGEST
+arm_type_align (gdbarch *gdbarch, struct type *t)
 {
-  int n;
-  int align;
-  int falign;
-
   t = check_typedef (t);
-  switch (TYPE_CODE (t))
+  if (t->code () == TYPE_CODE_ARRAY && TYPE_VECTOR (t))
     {
-    default:
-      /* Should never happen.  */
-      internal_error (__FILE__, __LINE__, _("unknown type alignment"));
-      return 4;
-
-    case TYPE_CODE_PTR:
-    case TYPE_CODE_ENUM:
-    case TYPE_CODE_INT:
-    case TYPE_CODE_FLT:
-    case TYPE_CODE_SET:
-    case TYPE_CODE_RANGE:
-    case TYPE_CODE_REF:
-    case TYPE_CODE_RVALUE_REF:
-    case TYPE_CODE_CHAR:
-    case TYPE_CODE_BOOL:
-      return TYPE_LENGTH (t);
-
-    case TYPE_CODE_ARRAY:
-      if (TYPE_VECTOR (t))
-       {
-         /* Use the natural alignment for vector types (the same for
-            scalar type), but the maximum alignment is 64-bit.  */
-         if (TYPE_LENGTH (t) > 8)
-           return 8;
-         else
-           return TYPE_LENGTH (t);
-       }
+      /* Use the natural alignment for vector types (the same for
+        scalar type), but the maximum alignment is 64-bit.  */
+      if (TYPE_LENGTH (t) > 8)
+       return 8;
       else
-       return arm_type_align (TYPE_TARGET_TYPE (t));
-    case TYPE_CODE_COMPLEX:
-      return arm_type_align (TYPE_TARGET_TYPE (t));
-
-    case TYPE_CODE_STRUCT:
-    case TYPE_CODE_UNION:
-      align = 1;
-      for (n = 0; n < TYPE_NFIELDS (t); n++)
-       {
-         falign = arm_type_align (TYPE_FIELD_TYPE (t, n));
-         if (falign > align)
-           align = falign;
-       }
-      return align;
+       return TYPE_LENGTH (t);
     }
+
+  /* Allow the common code to calculate the alignment.  */
+  return 0;
 }
 
 /* Possible base types for a candidate for passing and returning in
@@ -3482,7 +3504,7 @@ arm_vfp_cprc_sub_candidate (struct type *t,
                            enum arm_vfp_cprc_base_type *base_type)
 {
   t = check_typedef (t);
-  switch (TYPE_CODE (t))
+  switch (t->code ())
     {
     case TYPE_CODE_FLT:
       switch (TYPE_LENGTH (t))
@@ -3586,12 +3608,12 @@ arm_vfp_cprc_sub_candidate (struct type *t,
        int count = 0;
        unsigned unitlen;
        int i;
-       for (i = 0; i < TYPE_NFIELDS (t); i++)
+       for (i = 0; i < t->num_fields (); i++)
          {
            int sub_count = 0;
 
-           if (!field_is_static (&TYPE_FIELD (t, i)))
-             sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
+           if (!field_is_static (&t->field (i)))
+             sub_count = arm_vfp_cprc_sub_candidate (t->field (i).type (),
                                                      base_type);
            if (sub_count == -1)
              return -1;
@@ -3615,9 +3637,9 @@ arm_vfp_cprc_sub_candidate (struct type *t,
        int count = 0;
        unsigned unitlen;
        int i;
-       for (i = 0; i < TYPE_NFIELDS (t); i++)
+       for (i = 0; i < t->num_fields (); i++)
          {
-           int sub_count = arm_vfp_cprc_sub_candidate (TYPE_FIELD_TYPE (t, i),
+           int sub_count = arm_vfp_cprc_sub_candidate (t->field (i).type (),
                                                        base_type);
            if (sub_count == -1)
              return -1;
@@ -3688,7 +3710,8 @@ arm_vfp_abi_for_function (struct gdbarch *gdbarch, struct type *func_type)
 static CORE_ADDR
 arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                     struct regcache *regcache, CORE_ADDR bp_addr, int nargs,
-                    struct value **args, CORE_ADDR sp, int struct_return,
+                    struct value **args, CORE_ADDR sp,
+                    function_call_return_method return_method,
                     CORE_ADDR struct_addr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
@@ -3703,7 +3726,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
   /* Determine the type of this function and whether the VFP ABI
      applies.  */
   ftype = check_typedef (value_type (function));
-  if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+  if (ftype->code () == TYPE_CODE_PTR)
     ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
   use_vfp_abi = arm_vfp_abi_for_function (gdbarch, ftype);
 
@@ -3723,7 +3746,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* The struct_return pointer occupies the first parameter
      passing register.  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     {
       if (arm_debug)
        fprintf_unfiltered (gdb_stdlog, "struct return in %s = %s\n",
@@ -3748,23 +3771,24 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
       arg_type = check_typedef (value_type (args[argnum]));
       len = TYPE_LENGTH (arg_type);
       target_type = TYPE_TARGET_TYPE (arg_type);
-      typecode = TYPE_CODE (arg_type);
+      typecode = arg_type->code ();
       val = value_contents (args[argnum]);
 
-      align = arm_type_align (arg_type);
+      align = type_align (arg_type);
       /* Round alignment up to a whole number of words.  */
-      align = (align + INT_REGISTER_SIZE - 1) & ~(INT_REGISTER_SIZE - 1);
+      align = (align + ARM_INT_REGISTER_SIZE - 1)
+               & ~(ARM_INT_REGISTER_SIZE - 1);
       /* Different ABIs have different maximum alignments.  */
       if (gdbarch_tdep (gdbarch)->arm_abi == ARM_ABI_APCS)
        {
          /* The APCS ABI only requires word alignment.  */
-         align = INT_REGISTER_SIZE;
+         align = ARM_INT_REGISTER_SIZE;
        }
       else
        {
          /* The AAPCS requires at most doubleword alignment.  */
-         if (align > INT_REGISTER_SIZE * 2)
-           align = INT_REGISTER_SIZE * 2;
+         if (align > ARM_INT_REGISTER_SIZE * 2)
+           align = ARM_INT_REGISTER_SIZE * 2;
        }
 
       if (use_vfp_abi
@@ -3813,8 +3837,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                                 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);
+                     regcache->cooked_write (regnum, val + i * unit_length);
                    }
                }
              continue;
@@ -3827,17 +3850,17 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
            }
        }
 
-      /* Push stack padding for dowubleword alignment.  */
+      /* Push stack padding for doubleword alignment.  */
       if (nstack & (align - 1))
        {
-         si = push_stack_item (si, val, INT_REGISTER_SIZE);
-         nstack += INT_REGISTER_SIZE;
+         si = push_stack_item (si, val, ARM_INT_REGISTER_SIZE);
+         nstack += ARM_INT_REGISTER_SIZE;
        }
       
       /* Doubleword aligned quantities must go in even register pairs.  */
       if (may_use_core_reg
          && argreg <= ARM_LAST_ARG_REGNUM
-         && align > INT_REGISTER_SIZE
+         && align > ARM_INT_REGISTER_SIZE
          && argreg & 1)
        argreg++;
 
@@ -3846,7 +3869,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
         the THUMB bit in it.  */
       if (TYPE_CODE_PTR == typecode
          && target_type != NULL
-         && TYPE_CODE_FUNC == TYPE_CODE (check_typedef (target_type)))
+         && TYPE_CODE_FUNC == check_typedef (target_type)->code ())
        {
          CORE_ADDR regval = extract_unsigned_integer (val, len, byte_order);
          if (arm_pc_is_thumb (gdbarch, regval))
@@ -3863,7 +3886,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
         registers and stack.  */
       while (len > 0)
        {
-         int partial_len = len < INT_REGISTER_SIZE ? len : INT_REGISTER_SIZE;
+         int partial_len = len < ARM_INT_REGISTER_SIZE
+                           ? len : ARM_INT_REGISTER_SIZE;
          CORE_ADDR regval
            = extract_unsigned_integer (val, partial_len, byte_order);
 
@@ -3872,19 +3896,19 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              /* The argument is being passed in a general purpose
                 register.  */
              if (byte_order == BFD_ENDIAN_BIG)
-               regval <<= (INT_REGISTER_SIZE - partial_len) * 8;
+               regval <<= (ARM_INT_REGISTER_SIZE - partial_len) * 8;
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d in %s = 0x%s\n",
                                    argnum,
                                    gdbarch_register_name
                                      (gdbarch, argreg),
-                                   phex (regval, INT_REGISTER_SIZE));
+                                   phex (regval, ARM_INT_REGISTER_SIZE));
              regcache_cooked_write_unsigned (regcache, argreg, regval);
              argreg++;
            }
          else
            {
-             gdb_byte buf[INT_REGISTER_SIZE];
+             gdb_byte buf[ARM_INT_REGISTER_SIZE];
 
              memset (buf, 0, sizeof (buf));
              store_unsigned_integer (buf, partial_len, byte_order, regval);
@@ -3893,8 +3917,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
              if (arm_debug)
                fprintf_unfiltered (gdb_stdlog, "arg %d @ sp + %d\n",
                                    argnum, nstack);
-             si = push_stack_item (si, buf, INT_REGISTER_SIZE);
-             nstack += INT_REGISTER_SIZE;
+             si = push_stack_item (si, buf, ARM_INT_REGISTER_SIZE);
+             nstack += ARM_INT_REGISTER_SIZE;
            }
              
          len -= partial_len;
@@ -4007,7 +4031,7 @@ arm_neon_double_type (struct gdbarch *gdbarch)
       append_composite_type_field (t, "f64", elem);
 
       TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "neon_d";
+      t->set_name ("neon_d");
       tdep->neon_double_type = t;
     }
 
@@ -4046,7 +4070,7 @@ arm_neon_quad_type (struct gdbarch *gdbarch)
       append_composite_type_field (t, "f64", init_vector_type (elem, 2));
 
       TYPE_VECTOR (t) = 1;
-      TYPE_NAME (t) = "neon_q";
+      t->set_name ("neon_q");
       tdep->neon_quad_type = t;
     }
 
@@ -4077,7 +4101,7 @@ arm_register_type (struct gdbarch *gdbarch, int regnum)
       struct type *t = tdesc_register_type (gdbarch, regnum);
 
       if (regnum >= ARM_D0_REGNUM && regnum < ARM_D0_REGNUM + 32
-         && TYPE_CODE (t) == TYPE_CODE_FLT
+         && t->code () == TYPE_CODE_FLT
          && gdbarch_tdep (gdbarch)->have_neon)
        return arm_neon_double_type (gdbarch);
       else
@@ -4917,7 +4941,7 @@ cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
   if (dsc->u.branch.link)
     {
       /* The value of LR should be the next insn of current one.  In order
-       not to confuse logic hanlding later insn `bx lr', if current insn mode
+       not to confuse logic handling later insn `bx lr', if current insn mode
        is Thumb, the bit 0 of LR value should be set to 1.  */
       ULONGEST next_insn_addr = dsc->insn_addr + dsc->insn_size;
 
@@ -5608,7 +5632,7 @@ install_load_store (struct gdbarch *gdbarch, struct regcache *regs,
 
      Before this sequence of instructions:
      r0 is the PC value got from displaced_read_reg, so r0 = from + 8;
-     r2 is the Rn value got from dispalced_read_reg.
+     r2 is the Rn value got from displaced_read_reg.
 
      Insn1: push {pc} Write address of STR instruction + offset on stack
      Insn2: pop  {r4} Read it back from stack, r4 = addr(Insn1) + offset
@@ -5886,7 +5910,8 @@ cleanup_block_store_pc (struct gdbarch *gdbarch, struct regcache *regs,
 {
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
   int store_executed = condition_true (dsc->u.block.cond, status);
-  CORE_ADDR pc_stored_at, transferred_regs = bitcount (dsc->u.block.regmask);
+  CORE_ADDR pc_stored_at, transferred_regs
+    = count_one_bits (dsc->u.block.regmask);
   CORE_ADDR stm_insn_addr;
   uint32_t pc_val;
   long offset;
@@ -5938,7 +5963,7 @@ cleanup_block_load_pc (struct gdbarch *gdbarch,
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
   int load_executed = condition_true (dsc->u.block.cond, status);
   unsigned int mask = dsc->u.block.regmask, write_reg = ARM_PC_REGNUM;
-  unsigned int regs_loaded = bitcount (mask);
+  unsigned int regs_loaded = count_one_bits (mask);
   unsigned int num_to_shuffle = regs_loaded, clobbered;
 
   /* The method employed here will fail if the register list is fully populated
@@ -6070,7 +6095,7 @@ arm_copy_block_xfer (struct gdbarch *gdbarch, uint32_t insn,
             contiguous chunk r0...rX before doing the transfer, then shuffling
             registers into the correct places in the cleanup routine.  */
          unsigned int regmask = insn & 0xffff;
-         unsigned int num_in_list = bitcount (regmask), new_regmask;
+         unsigned int num_in_list = count_one_bits (regmask), new_regmask;
          unsigned int i;
 
          for (i = 0; i < num_in_list; i++)
@@ -6172,7 +6197,7 @@ thumb2_copy_block_xfer (struct gdbarch *gdbarch, uint16_t insn1, uint16_t insn2,
       else
        {
          unsigned int regmask = dsc->u.block.regmask;
-         unsigned int num_in_list = bitcount (regmask), new_regmask;
+         unsigned int num_in_list = count_one_bits (regmask), new_regmask;
          unsigned int i;
 
          for (i = 0; i < num_in_list; i++)
@@ -6285,7 +6310,7 @@ cleanup_svc (struct gdbarch *gdbarch, struct regcache *regs,
 }
 
 
-/* Common copy routine for svc instruciton.  */
+/* Common copy routine for svc instruction.  */
 
 static int
 install_svc (struct gdbarch *gdbarch, struct regcache *regs,
@@ -6577,6 +6602,7 @@ arm_decode_miscellaneous (struct gdbarch *gdbarch, uint32_t insn,
       else if (op == 0x3)
         /* Not really supported.  */
        return arm_copy_unmodified (gdbarch, insn, "smc", dsc);
+      /* Fall through.  */
 
     default:
       return arm_copy_undef (gdbarch, insn, dsc);
@@ -6897,7 +6923,7 @@ thumb2_decode_svc_copro (struct gdbarch *gdbarch, uint16_t insn1,
              if (bit_4 == 0) /* STC/STC2.  */
                return thumb_copy_unmodified_32bit (gdbarch, insn1, insn2,
                                                    "stc/stc2", dsc);
-             else /* LDC/LDC2 {literal, immeidate}.  */
+             else /* LDC/LDC2 {literal, immediate}.  */
                return thumb2_copy_copro_load_store (gdbarch, insn1, insn2,
                                                     regs, dsc);
            }
@@ -7042,7 +7068,7 @@ thumb_copy_16bit_ldr_literal (struct gdbarch *gdbarch, uint16_t insn1,
   return 0;
 }
 
-/* Copy Thumb cbnz/cbz insruction.  */
+/* Copy Thumb cbnz/cbz instruction.  */
 
 static int
 thumb_copy_cbnz_cbz (struct gdbarch *gdbarch, uint16_t insn1,
@@ -7189,7 +7215,7 @@ thumb_copy_pop_pc_16bit (struct gdbarch *gdbarch, uint16_t insn1,
     }
   else
     {
-      unsigned int num_in_list = bitcount (dsc->u.block.regmask);
+      unsigned int num_in_list = count_one_bits (dsc->u.block.regmask);
       unsigned int i;
       unsigned int new_regmask;
 
@@ -7417,7 +7443,7 @@ thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
          case 0:
            if (bit (insn1, 6))
              {
-               /* Load/store {dual, execlusive}, table branch.  */
+               /* Load/store {dual, exclusive}, table branch.  */
                if (bits (insn1, 7, 8) == 1 && bits (insn1, 4, 5) == 1
                    && bits (insn2, 5, 7) == 0)
                  err = thumb2_copy_table_branch (gdbarch, insn1, insn2, regs,
@@ -7469,16 +7495,16 @@ thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1,
        {
          if (bit (insn1, 9)) /* Data processing (plain binary imm).  */
            {
-             int op = bits (insn1, 4, 8);
+             int dp_op = bits (insn1, 4, 8);
              int rn = bits (insn1, 0, 3);
-             if ((op == 0 || op == 0xa) && rn == 0xf)
+             if ((dp_op == 0 || dp_op == 0xa) && rn == 0xf)
                err = thumb_copy_pc_relative_32bit (gdbarch, insn1, insn2,
                                                    regs, dsc);
              else
                err = thumb_copy_unmodified_32bit (gdbarch, insn1, insn2,
                                                   "dp/pb", dsc);
            }
-         else /* Data processing (modified immeidate) */
+         else /* Data processing (modified immediate) */
            err = thumb_copy_unmodified_32bit (gdbarch, insn1, insn2,
                                               "dp/mi", dsc);
        }
@@ -7890,7 +7916,7 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
   struct gdbarch *gdbarch = regs->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
-  if (TYPE_CODE_FLT == TYPE_CODE (type))
+  if (TYPE_CODE_FLT == type->code ())
     {
       switch (gdbarch_tdep (gdbarch)->fp_model)
        {
@@ -7899,9 +7925,9 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
            /* The value is in register F0 in internal format.  We need to
               extract the raw value and then convert it to the desired
               internal type.  */
-           bfd_byte tmpbuf[FP_REGISTER_SIZE];
+           bfd_byte tmpbuf[ARM_FP_REGISTER_SIZE];
 
-           regcache_cooked_read (regs, ARM_F0_REGNUM, tmpbuf);
+           regs->cooked_read (ARM_F0_REGNUM, tmpbuf);
            target_float_convert (tmpbuf, arm_ext_type (gdbarch),
                                  valbuf, type);
          }
@@ -7912,10 +7938,10 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
          /* ARM_FLOAT_VFP can arise if this is a variadic function so
             not using the VFP ABI code.  */
        case ARM_FLOAT_VFP:
-         regcache_cooked_read (regs, ARM_A1_REGNUM, valbuf);
+         regs->cooked_read (ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
-           regcache_cooked_read (regs, ARM_A1_REGNUM + 1,
-                                 valbuf + INT_REGISTER_SIZE);
+           regs->cooked_read (ARM_A1_REGNUM + 1,
+                              valbuf + ARM_INT_REGISTER_SIZE);
          break;
 
        default:
@@ -7925,12 +7951,12 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
          break;
        }
     }
-  else if (TYPE_CODE (type) == TYPE_CODE_INT
-          || TYPE_CODE (type) == TYPE_CODE_CHAR
-          || TYPE_CODE (type) == TYPE_CODE_BOOL
-          || TYPE_CODE (type) == TYPE_CODE_PTR
+  else if (type->code () == TYPE_CODE_INT
+          || type->code () == TYPE_CODE_CHAR
+          || type->code () == TYPE_CODE_BOOL
+          || type->code () == TYPE_CODE_PTR
           || TYPE_IS_REFERENCE (type)
-          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+          || type->code () == TYPE_CODE_ENUM)
     {
       /* If the type is a plain integer, then the access is
         straight-forward.  Otherwise we have to play around a bit
@@ -7945,11 +7971,11 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
             anything special for small big-endian values.  */
          regcache_cooked_read_unsigned (regs, regno++, &tmp);
          store_unsigned_integer (valbuf, 
-                                 (len > INT_REGISTER_SIZE
-                                  ? INT_REGISTER_SIZE : len),
+                                 (len > ARM_INT_REGISTER_SIZE
+                                  ? ARM_INT_REGISTER_SIZE : len),
                                  byte_order, tmp);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
   else
@@ -7959,15 +7985,15 @@ arm_extract_return_value (struct type *type, struct regcache *regs,
          registers with 32-bit load instruction(s).  */
       int len = TYPE_LENGTH (type);
       int regno = ARM_A1_REGNUM;
-      bfd_byte tmpbuf[INT_REGISTER_SIZE];
+      bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
 
       while (len > 0)
        {
-         regcache_cooked_read (regs, regno++, tmpbuf);
+         regs->cooked_read (regno++, tmpbuf);
          memcpy (valbuf, tmpbuf,
-                 len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+                 len > ARM_INT_REGISTER_SIZE ? ARM_INT_REGISTER_SIZE : len);
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
 }
@@ -7986,7 +8012,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
 
   /* Simple, non-aggregate types (ie not including vectors and
      complex) are always returned in a register (or registers).  */
-  code = TYPE_CODE (type);
+  code = type->code ();
   if (TYPE_CODE_STRUCT != code && TYPE_CODE_UNION != code
       && TYPE_CODE_ARRAY != code && TYPE_CODE_COMPLEX != code)
     return 0;
@@ -8002,7 +8028,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
     {
       /* The AAPCS says all aggregates not larger than a word are returned
         in a register.  */
-      if (TYPE_LENGTH (type) <= INT_REGISTER_SIZE)
+      if (TYPE_LENGTH (type) <= ARM_INT_REGISTER_SIZE)
        return 0;
 
       return 1;
@@ -8013,12 +8039,12 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
 
       /* All aggregate types that won't fit in a register must be returned
         in memory.  */
-      if (TYPE_LENGTH (type) > INT_REGISTER_SIZE)
+      if (TYPE_LENGTH (type) > ARM_INT_REGISTER_SIZE)
        return 1;
 
       /* In the ARM ABI, "integer" like aggregate types are returned in
         registers.  For an aggregate type to be integer like, its size
-        must be less than or equal to INT_REGISTER_SIZE and the
+        must be less than or equal to ARM_INT_REGISTER_SIZE and the
         offset of each addressable subfield must be zero.  Note that bit
         fields are not addressable, and all addressable subfields of
         unions always start at offset zero.
@@ -8042,7 +8068,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
          int i;
          /* Need to check if this struct/union is "integer" like.  For
             this to be true, its size must be less than or equal to
-            INT_REGISTER_SIZE and the offset of each addressable
+            ARM_INT_REGISTER_SIZE and the offset of each addressable
             subfield must be zero.  Note that bit fields are not
             addressable, and unions always start at offset zero.  If any
             of the subfields is a floating point type, the struct/union
@@ -8055,13 +8081,12 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
             --> yes, nRc = 1
          */
 
-         for (i = 0; i < TYPE_NFIELDS (type); i++)
+         for (i = 0; i < type->num_fields (); i++)
            {
              enum type_code field_type_code;
 
              field_type_code
-               = TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type,
-                                                            i)));
+               = check_typedef (type->field (i).type ())->code ();
 
              /* Is it a floating point type field?  */
              if (field_type_code == TYPE_CODE_FLT)
@@ -8099,16 +8124,16 @@ arm_store_return_value (struct type *type, struct regcache *regs,
   struct gdbarch *gdbarch = regs->arch ();
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
 
-  if (TYPE_CODE (type) == TYPE_CODE_FLT)
+  if (type->code () == TYPE_CODE_FLT)
     {
-      gdb_byte buf[FP_REGISTER_SIZE];
+      gdb_byte buf[ARM_FP_REGISTER_SIZE];
 
       switch (gdbarch_tdep (gdbarch)->fp_model)
        {
        case ARM_FLOAT_FPA:
 
          target_float_convert (valbuf, type, buf, arm_ext_type (gdbarch));
-         regcache_cooked_write (regs, ARM_F0_REGNUM, buf);
+         regs->cooked_write (ARM_F0_REGNUM, buf);
          break;
 
        case ARM_FLOAT_SOFT_FPA:
@@ -8116,10 +8141,10 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          /* ARM_FLOAT_VFP can arise if this is a variadic function so
             not using the VFP ABI code.  */
        case ARM_FLOAT_VFP:
-         regcache_cooked_write (regs, ARM_A1_REGNUM, valbuf);
+         regs->cooked_write (ARM_A1_REGNUM, valbuf);
          if (TYPE_LENGTH (type) > 4)
-           regcache_cooked_write (regs, ARM_A1_REGNUM + 1, 
-                                  valbuf + INT_REGISTER_SIZE);
+           regs->cooked_write (ARM_A1_REGNUM + 1,
+                               valbuf + ARM_INT_REGISTER_SIZE);
          break;
 
        default:
@@ -8129,22 +8154,22 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          break;
        }
     }
-  else if (TYPE_CODE (type) == TYPE_CODE_INT
-          || TYPE_CODE (type) == TYPE_CODE_CHAR
-          || TYPE_CODE (type) == TYPE_CODE_BOOL
-          || TYPE_CODE (type) == TYPE_CODE_PTR
+  else if (type->code () == TYPE_CODE_INT
+          || type->code () == TYPE_CODE_CHAR
+          || type->code () == TYPE_CODE_BOOL
+          || type->code () == TYPE_CODE_PTR
           || TYPE_IS_REFERENCE (type)
-          || TYPE_CODE (type) == TYPE_CODE_ENUM)
+          || type->code () == TYPE_CODE_ENUM)
     {
       if (TYPE_LENGTH (type) <= 4)
        {
          /* Values of one word or less are zero/sign-extended and
             returned in r0.  */
-         bfd_byte tmpbuf[INT_REGISTER_SIZE];
+         bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
          LONGEST val = unpack_long (type, valbuf);
 
-         store_signed_integer (tmpbuf, INT_REGISTER_SIZE, byte_order, val);
-         regcache_cooked_write (regs, ARM_A1_REGNUM, tmpbuf);
+         store_signed_integer (tmpbuf, ARM_INT_REGISTER_SIZE, byte_order, val);
+         regs->cooked_write (ARM_A1_REGNUM, tmpbuf);
        }
       else
        {
@@ -8156,9 +8181,9 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 
          while (len > 0)
            {
-             regcache_cooked_write (regs, regno++, valbuf);
-             len -= INT_REGISTER_SIZE;
-             valbuf += INT_REGISTER_SIZE;
+             regs->cooked_write (regno++, valbuf);
+             len -= ARM_INT_REGISTER_SIZE;
+             valbuf += ARM_INT_REGISTER_SIZE;
            }
        }
     }
@@ -8169,15 +8194,15 @@ arm_store_return_value (struct type *type, struct regcache *regs,
          registers with 32-bit load instruction(s).  */
       int len = TYPE_LENGTH (type);
       int regno = ARM_A1_REGNUM;
-      bfd_byte tmpbuf[INT_REGISTER_SIZE];
+      bfd_byte tmpbuf[ARM_INT_REGISTER_SIZE];
 
       while (len > 0)
        {
          memcpy (tmpbuf, valbuf,
-                 len > INT_REGISTER_SIZE ? INT_REGISTER_SIZE : len);
-         regcache_cooked_write (regs, regno++, tmpbuf);
-         len -= INT_REGISTER_SIZE;
-         valbuf += INT_REGISTER_SIZE;
+                 len > ARM_INT_REGISTER_SIZE ? ARM_INT_REGISTER_SIZE : len);
+         regs->cooked_write (regno++, tmpbuf);
+         len -= ARM_INT_REGISTER_SIZE;
+         valbuf += ARM_INT_REGISTER_SIZE;
        }
     }
 }
@@ -8222,25 +8247,23 @@ arm_return_value (struct gdbarch *gdbarch, struct value *function,
              regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                    strlen (name_buf));
              if (writebuf)
-               regcache_cooked_write (regcache, regnum,
-                                      writebuf + i * unit_length);
+               regcache->cooked_write (regnum, writebuf + i * unit_length);
              if (readbuf)
-               regcache_cooked_read (regcache, regnum,
-                                     readbuf + i * unit_length);
+               regcache->cooked_read (regnum, readbuf + i * unit_length);
            }
        }
       return RETURN_VALUE_REGISTER_CONVENTION;
     }
 
-  if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT
-      || TYPE_CODE (valtype) == TYPE_CODE_UNION
-      || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+  if (valtype->code () == TYPE_CODE_STRUCT
+      || valtype->code () == TYPE_CODE_UNION
+      || valtype->code () == TYPE_CODE_ARRAY)
     {
       if (tdep->struct_return == pcc_struct_return
          || arm_return_in_memory (gdbarch, valtype))
        return RETURN_VALUE_STRUCT_CONVENTION;
     }
-  else if (TYPE_CODE (valtype) == TYPE_CODE_COMPLEX)
+  else if (valtype->code () == TYPE_CODE_COMPLEX)
     {
       if (arm_return_in_memory (gdbarch, valtype))
        return RETURN_VALUE_STRUCT_CONVENTION;
@@ -8263,17 +8286,67 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   CORE_ADDR jb_addr;
-  gdb_byte buf[INT_REGISTER_SIZE];
+  gdb_byte buf[ARM_INT_REGISTER_SIZE];
   
   jb_addr = get_frame_register_unsigned (frame, ARM_A1_REGNUM);
 
   if (target_read_memory (jb_addr + tdep->jb_pc * tdep->jb_elt_size, buf,
-                         INT_REGISTER_SIZE))
+                         ARM_INT_REGISTER_SIZE))
     return 0;
 
-  *pc = extract_unsigned_integer (buf, INT_REGISTER_SIZE, byte_order);
+  *pc = extract_unsigned_integer (buf, ARM_INT_REGISTER_SIZE, byte_order);
   return 1;
 }
+/* A call to cmse secure entry function "foo" at "a" is modified by
+     GNU ld as "b".
+     a) bl xxxx <foo>
+
+     <foo>
+     xxxx:
+
+     b) bl yyyy <__acle_se_foo>
+
+     section .gnu.sgstubs:
+     <foo>
+     yyyy: sg   // secure gateway
+          b.w xxxx <__acle_se_foo>  // original_branch_dest
+
+     <__acle_se_foo>
+     xxxx:
+
+  When the control at "b", the pc contains "yyyy" (sg address) which is a
+  trampoline and does not exist in source code.  This function returns the
+  target pc "xxxx".  For more details please refer to section 5.4
+  (Entry functions) and section 3.4.4 (C level development flow of secure code)
+  of "armv8-m-security-extensions-requirements-on-development-tools-engineering-specification"
+  document on www.developer.arm.com.  */
+
+static CORE_ADDR
+arm_skip_cmse_entry (CORE_ADDR pc, const char *name, struct objfile *objfile)
+{
+  int target_len = strlen (name) + strlen ("__acle_se_") + 1;
+  char *target_name = (char *) alloca (target_len);
+  xsnprintf (target_name, target_len, "%s%s", "__acle_se_", name);
+
+  struct bound_minimal_symbol minsym
+   = lookup_minimal_symbol (target_name, NULL, objfile);
+
+  if (minsym.minsym != nullptr)
+    return BMSYMBOL_VALUE_ADDRESS (minsym);
+
+  return 0;
+}
+
+/* Return true when SEC points to ".gnu.sgstubs" section.  */
+
+static bool
+arm_is_sgstubs_section (struct obj_section *sec)
+{
+  return (sec != nullptr
+         && sec->the_bfd_section != nullptr
+         && sec->the_bfd_section->name != nullptr
+         && streq (sec->the_bfd_section->name, ".gnu.sgstubs"));
+}
 
 /* Recognize GCC and GNU ld's trampolines.  If we are in a trampoline,
    return the target PC.  Otherwise return 0.  */
@@ -8353,21 +8426,13 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
        return 0;
     }
 
-  return 0;                    /* not a stub */
-}
+  struct obj_section *section = find_pc_section (pc);
 
-static void
-set_arm_command (const char *args, int from_tty)
-{
-  printf_unfiltered (_("\
-\"set arm\" must be followed by an apporpriate subcommand.\n"));
-  help_list (setarmcmdlist, "set arm ", all_commands, gdb_stdout);
-}
+  /* Check whether SECTION points to the ".gnu.sgstubs" section.  */
+  if (arm_is_sgstubs_section (section))
+    return arm_skip_cmse_entry (pc, name, section->objfile);
 
-static void
-show_arm_command (const char *args, int from_tty)
-{
-  cmd_show_list (showarmcmdlist, from_tty, "");
+  return 0;                    /* not a stub */
 }
 
 static void
@@ -8589,64 +8654,30 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
     MSYMBOL_SET_SPECIAL (msym);
 }
 
-static void
-arm_objfile_data_free (struct objfile *objfile, void *arg)
-{
-  struct arm_per_objfile *data = (struct arm_per_objfile *) arg;
-  unsigned int i;
-
-  for (i = 0; i < objfile->obfd->section_count; i++)
-    VEC_free (arm_mapping_symbol_s, data->section_maps[i]);
-}
-
 static void
 arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
                           asymbol *sym)
 {
   const char *name = bfd_asymbol_name (sym);
-  struct arm_per_objfile *data;
-  VEC(arm_mapping_symbol_s) **map_p;
+  struct arm_per_bfd *data;
   struct arm_mapping_symbol new_map_sym;
 
   gdb_assert (name[0] == '$');
   if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
     return;
 
-  data = (struct arm_per_objfile *) objfile_data (objfile,
-                                                 arm_objfile_data_key);
+  data = arm_bfd_data_key.get (objfile->obfd);
   if (data == NULL)
-    {
-      data = OBSTACK_ZALLOC (&objfile->objfile_obstack,
-                            struct arm_per_objfile);
-      set_objfile_data (objfile, arm_objfile_data_key, data);
-      data->section_maps = OBSTACK_CALLOC (&objfile->objfile_obstack,
-                                          objfile->obfd->section_count,
-                                          VEC(arm_mapping_symbol_s) *);
-    }
-  map_p = &data->section_maps[bfd_get_section (sym)->index];
+    data = arm_bfd_data_key.emplace (objfile->obfd,
+                                    objfile->obfd->section_count);
+  arm_mapping_symbol_vec &map
+    = data->section_maps[bfd_asymbol_section (sym)->index];
 
   new_map_sym.value = sym->value;
   new_map_sym.type = name[1];
 
-  /* Assume that most mapping symbols appear in order of increasing
-     value.  If they were randomly distributed, it would be faster to
-     always push here and then sort at first use.  */
-  if (!VEC_empty (arm_mapping_symbol_s, *map_p))
-    {
-      struct arm_mapping_symbol *prev_map_sym;
-
-      prev_map_sym = VEC_last (arm_mapping_symbol_s, *map_p);
-      if (prev_map_sym->value >= sym->value)
-       {
-         unsigned int idx;
-         idx = VEC_lower_bound (arm_mapping_symbol_s, *map_p, &new_map_sym,
-                                arm_compare_mapping_symbols);
-         VEC_safe_insert (arm_mapping_symbol_s, *map_p, idx, &new_map_sym);
-         return;
-       }
-    }
-
-  VEC_safe_push (arm_mapping_symbol_s, *map_p, &new_map_sym);
+  /* Insert at the end, the vector will be sorted on first use.  */
+  map.push_back (new_map_sym);
 }
 
 static void
@@ -8678,7 +8709,7 @@ arm_write_pc (struct regcache *regcache, CORE_ADDR pc)
    the quad register, in [0, 15].  */
 
 static enum register_status
-arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_neon_quad_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                    int regnum, gdb_byte *buf)
 {
   char name_buf[4];
@@ -8696,13 +8727,13 @@ arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     offset = 0;
 
-  status = regcache_raw_read (regcache, double_regnum, reg_buf);
+  status = regcache->raw_read (double_regnum, reg_buf);
   if (status != REG_VALID)
     return status;
   memcpy (buf + offset, reg_buf, 8);
 
   offset = 8 - offset;
-  status = regcache_raw_read (regcache, double_regnum + 1, reg_buf);
+  status = regcache->raw_read (double_regnum + 1, reg_buf);
   if (status != REG_VALID)
     return status;
   memcpy (buf + offset, reg_buf, 8);
@@ -8711,7 +8742,7 @@ arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
 }
 
 static enum register_status
-arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
+arm_pseudo_read (struct gdbarch *gdbarch, readable_regcache *regcache,
                 int regnum, gdb_byte *buf)
 {
   const int num_regs = gdbarch_num_regs (gdbarch);
@@ -8742,7 +8773,7 @@ arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                   strlen (name_buf));
 
-      status = regcache_raw_read (regcache, double_regnum, reg_buf);
+      status = regcache->raw_read (double_regnum, reg_buf);
       if (status == REG_VALID)
        memcpy (buf, reg_buf + offset, 4);
       return status;
@@ -8773,9 +8804,9 @@ arm_neon_quad_write (struct gdbarch *gdbarch, struct regcache *regcache,
   else
     offset = 0;
 
-  regcache_raw_write (regcache, double_regnum, buf + offset);
+  regcache->raw_write (double_regnum, buf + offset);
   offset = 8 - offset;
-  regcache_raw_write (regcache, double_regnum + 1, buf + offset);
+  regcache->raw_write (double_regnum + 1, buf + offset);
 }
 
 static void
@@ -8808,9 +8839,9 @@ arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                   strlen (name_buf));
 
-      regcache_raw_read (regcache, double_regnum, reg_buf);
+      regcache->raw_read (double_regnum, reg_buf);
       memcpy (reg_buf + offset, buf, 4);
-      regcache_raw_write (regcache, double_regnum, reg_buf);
+      regcache->raw_write (double_regnum, reg_buf);
     }
 }
 
@@ -8856,7 +8887,6 @@ arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
-\f
 /* For backward-compatibility we allow two 'g' packet lengths with
    the remote protocol depending on whether FPA registers are
    supplied.  M-profile targets do not have FPA registers, but some
@@ -8870,30 +8900,26 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch)
 {
   if (gdbarch_tdep (gdbarch)->is_m)
     {
+      const target_desc *tdesc;
+
       /* If we know from the executable this is an M-profile target,
         cater for remote targets whose register set layout is the
         same as the FPA layout.  */
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_WITH_FPA);
       register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; f0-f7; fps,xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + (8 * FP_REGISTER_SIZE)
-                                     + (2 * INT_REGISTER_SIZE),
-                                     tdesc_arm_with_m_fpa_layout);
+                                     ARM_CORE_REGS_SIZE + ARM_FP_REGS_SIZE,
+                                     tdesc);
 
       /* The regular M-profile layout.  */
-      register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + INT_REGISTER_SIZE,
-                                     tdesc_arm_with_m);
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_M_PROFILE);
+      register_remote_g_packet_guess (gdbarch, ARM_CORE_REGS_SIZE,
+                                     tdesc);
 
       /* M-profile plus M4F VFP.  */
+      tdesc = arm_read_mprofile_description (ARM_M_TYPE_VFP_D16);
       register_remote_g_packet_guess (gdbarch,
-                                     /* r0-r12,sp,lr,pc; d0-d15; fpscr,xpsr */
-                                     (16 * INT_REGISTER_SIZE)
-                                     + (16 * VFP_REGISTER_SIZE)
-                                     + (2 * INT_REGISTER_SIZE),
-                                     tdesc_arm_with_m_vfp_d16);
+                                     ARM_CORE_REGS_SIZE + ARM_VFP2_REGS_SIZE,
+                                     tdesc);
     }
 
   /* Otherwise we don't have a useful guess.  */
@@ -8915,7 +8941,17 @@ arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame)
     return 1;
 }
 
-\f
+/* Implement gdbarch_gnu_triplet_regexp.  If the arch name is arm then allow it
+   to be postfixed by a version (eg armv7hl).  */
+
+static const char *
+arm_gnu_triplet_regexp (struct gdbarch *gdbarch)
+{
+  if (strcmp (gdbarch_bfd_arch_info (gdbarch)->arch_name, "arm") == 0)
+    return "arm(v[^- ]*)?";
+  return gdbarch_bfd_arch_info (gdbarch)->arch_name;
+}
+
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
    architectures already created during this debugging session.
@@ -8932,11 +8968,13 @@ 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, is_m = 0;
-  int vfp_register_count = 0, have_vfp_pseudos = 0, have_neon_pseudos = 0;
-  int have_wmmx_registers = 0;
-  int have_neon = 0;
-  int have_fpa_registers = 1;
+  int i;
+  bool is_m = false;
+  int vfp_register_count = 0;
+  bool have_vfp_pseudos = false, have_neon_pseudos = false;
+  bool have_wmmx_registers = false;
+  bool have_neon = false;
+  bool have_fpa_registers = true;
   const struct target_desc *tdesc = info.target_desc;
 
   /* If we have an object to base this architecture on, try to determine
@@ -8968,7 +9006,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          else if (ei_osabi == ELFOSABI_NONE || ei_osabi == ELFOSABI_GNU)
            {
              int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
-             int attr_arch, attr_profile;
 
              switch (eabi_ver)
                {
@@ -9039,11 +9076,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                 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);
+             int attr_arch
+               = bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
+                                           Tag_CPU_arch);
+             int 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
@@ -9052,14 +9091,12 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                  && (attr_arch == TAG_CPU_ARCH_V6_M
                      || attr_arch == TAG_CPU_ARCH_V6S_M
                      || attr_profile == 'M'))
-               is_m = 1;
+               is_m = true;
 #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:
@@ -9112,7 +9149,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
          if (feature == NULL)
            return NULL;
          else
-           is_m = 1;
+           is_m = true;
        }
 
       tdesc_data = tdesc_data_alloc ();
@@ -9158,7 +9195,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
            }
        }
       else
-       have_fpa_registers = 0;
+       have_fpa_registers = false;
 
       feature = tdesc_find_feature (tdesc,
                                    "org.gnu.gdb.xscale.iwmmxt");
@@ -9194,7 +9231,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
              return NULL;
            }
 
-         have_wmmx_registers = 1;
+         have_wmmx_registers = true;
        }
 
       /* If we have a VFP unit, check whether the single precision registers
@@ -9235,7 +9272,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
            }
 
          if (tdesc_unnumbered_register (feature, "s0") == 0)
-           have_vfp_pseudos = 1;
+           have_vfp_pseudos = true;
 
          vfp_register_count = i;
 
@@ -9257,9 +9294,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                 their type; otherwise (normally) provide them with
                 the default type.  */
              if (tdesc_unnumbered_register (feature, "q0") == 0)
-               have_neon_pseudos = 1;
+               have_neon_pseudos = true;
 
-             have_neon = 1;
+             have_neon = true;
            }
        }
     }
@@ -9350,10 +9387,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   else
     set_gdbarch_wchar_signed (gdbarch, 1);
 
+  /* Compute type alignment.  */
+  set_gdbarch_type_align (gdbarch, arm_type_align);
+
   /* Note: for displaced stepping, this includes the breakpoint, and one word
      of additional scratch space.  This setting isn't used for anything beside
      displaced stepping at present.  */
-  set_gdbarch_max_insn_length (gdbarch, 4 * DISPLACED_MODIFIED_INSNS);
+  set_gdbarch_max_insn_length (gdbarch, 4 * ARM_DISPLACED_MODIFIED_INSNS);
 
   /* This should be low enough for everything.  */
   tdep->lowest_pc = 0x20;
@@ -9371,11 +9411,6 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_write_pc (gdbarch, arm_write_pc);
 
-  /* Frame handling.  */
-  set_gdbarch_dummy_id (gdbarch, arm_dummy_id);
-  set_gdbarch_unwind_pc (gdbarch, arm_unwind_pc);
-  set_gdbarch_unwind_sp (gdbarch, arm_unwind_sp);
-
   frame_base_set_default (gdbarch, &arm_normal_base);
 
   /* Address manipulation.  */
@@ -9511,7 +9546,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
     }
 
   /* Add standard register aliases.  We add aliases even for those
-     nanes which are used by the current architecture - it's simpler,
+     names which are used by the current architecture - it's simpler,
      and does no harm, since nothing ever lists user registers.  */
   for (i = 0; i < ARRAY_SIZE (arm_register_aliases); i++)
     user_reg_add (gdbarch, arm_register_aliases[i].name,
@@ -9520,6 +9555,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_disassembler_options (gdbarch, &arm_disassembler_options);
   set_gdbarch_valid_disassembler_options (gdbarch, disassembler_options_arm ());
 
+  set_gdbarch_gnu_triplet_regexp (gdbarch, arm_gnu_triplet_regexp);
+
   return gdbarch;
 }
 
@@ -9531,7 +9568,21 @@ arm_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
   if (tdep == NULL)
     return;
 
-  fprintf_unfiltered (file, _("arm_dump_tdep: Lowest pc = 0x%lx"),
+  fprintf_unfiltered (file, _("arm_dump_tdep: fp_model = %i\n"),
+                     (int) tdep->fp_model);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_fpa_registers = %i\n"),
+                     (int) tdep->have_fpa_registers);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_wmmx_registers = %i\n"),
+                     (int) tdep->have_wmmx_registers);
+  fprintf_unfiltered (file, _("arm_dump_tdep: vfp_register_count = %i\n"),
+                     (int) tdep->vfp_register_count);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_vfp_pseudos = %i\n"),
+                     (int) tdep->have_vfp_pseudos);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_neon_pseudos = %i\n"),
+                     (int) tdep->have_neon_pseudos);
+  fprintf_unfiltered (file, _("arm_dump_tdep: have_neon = %i\n"),
+                     (int) tdep->have_neon);
+  fprintf_unfiltered (file, _("arm_dump_tdep: Lowest pc = 0x%lx\n"),
                      (unsigned long) tdep->lowest_pc);
 }
 
@@ -9542,8 +9593,9 @@ static void arm_record_test (void);
 }
 #endif
 
+void _initialize_arm_tdep ();
 void
-_initialize_arm_tdep (void)
+_initialize_arm_tdep ()
 {
   long length;
   int i, j;
@@ -9552,40 +9604,27 @@ _initialize_arm_tdep (void)
 
   gdbarch_register (bfd_arch_arm, arm_gdbarch_init, arm_dump_tdep);
 
-  arm_objfile_data_key
-    = register_objfile_data_with_cleanup (NULL, arm_objfile_data_free);
-
   /* Add ourselves to objfile event chain.  */
-  observer_attach_new_objfile (arm_exidx_new_objfile);
-  arm_exidx_data_key
-    = register_objfile_data_with_cleanup (NULL, arm_exidx_data_free);
+  gdb::observers::new_objfile.attach (arm_exidx_new_objfile);
 
   /* Register an ELF OS ABI sniffer for ARM binaries.  */
   gdbarch_register_osabi_sniffer (bfd_arch_arm,
                                  bfd_target_elf_flavour,
                                  arm_elf_osabi_sniffer);
 
-  /* Initialize the standard target descriptions.  */
-  initialize_tdesc_arm_with_m ();
-  initialize_tdesc_arm_with_m_fpa_layout ();
-  initialize_tdesc_arm_with_m_vfp_d16 ();
-  initialize_tdesc_arm_with_iwmmxt ();
-  initialize_tdesc_arm_with_vfpv2 ();
-  initialize_tdesc_arm_with_vfpv3 ();
-  initialize_tdesc_arm_with_neon ();
-
   /* Add root prefix command for all "set arm"/"show arm" commands.  */
-  add_prefix_cmd ("arm", no_class, set_arm_command,
-                 _("Various ARM-specific commands."),
-                 &setarmcmdlist, "set arm ", 0, &setlist);
+  add_basic_prefix_cmd ("arm", no_class,
+                       _("Various ARM-specific commands."),
+                       &setarmcmdlist, "set arm ", 0, &setlist);
 
-  add_prefix_cmd ("arm", no_class, show_arm_command,
-                 _("Various ARM-specific commands."),
-                 &showarmcmdlist, "show arm ", 0, &showlist);
+  add_show_prefix_cmd ("arm", no_class,
+                      _("Various ARM-specific commands."),
+                      &showarmcmdlist, "show arm ", 0, &showlist);
 
 
   arm_disassembler_options = xstrdup ("reg-names-std");
-  const disasm_options_t *disasm_options = disassembler_options_arm ();
+  const disasm_options_t *disasm_options
+    = &disassembler_options_arm ()->options;
   int num_disassembly_styles = 0;
   for (i = 0; disasm_options->name[i] != NULL; i++)
     if (CONST_STRNEQ (disasm_options->name[i], "reg-names-"))
@@ -9964,7 +10003,7 @@ arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
 static int
 arm_record_extension_space (insn_decode_record *arm_insn_r)
 {
-  uint32_t ret = 0;  /* Return value: -1:record failure ;  0:success  */
+  int ret = 0;  /* Return value: -1:record failure ;  0:success  */
   uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
   uint32_t record_buf[8], record_buf_mem[8];
   uint32_t reg_src1 = 0;
@@ -10231,82 +10270,108 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
   uint32_t record_buf[8], record_buf_mem[8];
   ULONGEST u_regval[2] = {0};
 
-  uint32_t reg_src1 = 0, reg_dest = 0;
+  uint32_t reg_src1 = 0;
   uint32_t opcode1 = 0;
 
   arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
   arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
   opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
 
-  /* Data processing insn /multiply insn.  */
-  if (9 == arm_insn_r->decode
-      && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
-      ||  (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+  if (!((opcode1 & 0x19) == 0x10))
     {
-      /* Handle multiply instructions.  */
-      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
-        if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
-          {
-            /* Handle MLA and MUL.  */
-            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
-            record_buf[1] = ARM_PS_REGNUM;
-            arm_insn_r->reg_rec_count = 2;
-          }
-        else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
-          {
-            /* Handle SMLAL, SMULL, UMLAL, UMULL.  */
-            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
-            record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
-            record_buf[2] = ARM_PS_REGNUM;
-            arm_insn_r->reg_rec_count = 3;
-          }
+      /* Data-processing (register) and Data-processing (register-shifted
+        register */
+      /* Out of 11 shifter operands mode, all the insn modifies destination
+        register, which is specified by 13-16 decode.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      record_buf[1] = ARM_PS_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
     }
-  else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
-           && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+  else if ((arm_insn_r->decode < 8) && ((opcode1 & 0x19) == 0x10))
     {
-      /* Handle misc load insns, as 20th bit  (L = 1).  */
-      /* LDR insn has a capability to do branching, if
-         MOV LR, PC is precceded by LDR insn having Rn as R15
-         in that case, it emulates branch and link insn, and hence we 
-         need to save CSPR and PC as well. I am not sure this is right
-         place; as opcode = 010 LDR insn make this happen, if R15 was
-         used.  */
-      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
-      if (15 != reg_dest)
-        {
-          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
-          arm_insn_r->reg_rec_count = 1;
-        }
-      else
-        {
-          record_buf[0] = reg_dest;
-          record_buf[1] = ARM_PS_REGNUM;
-          arm_insn_r->reg_rec_count = 2;
-        }
+      /* Miscellaneous instructions */
+
+      if (3 == arm_insn_r->decode && 0x12 == opcode1
+         && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+       {
+         /* Handle BLX, branch and link/exchange.  */
+         if (9 == arm_insn_r->opcode)
+           {
+             /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+                and R14 stores the return address.  */
+             record_buf[0] = ARM_PS_REGNUM;
+             record_buf[1] = ARM_LR_REGNUM;
+             arm_insn_r->reg_rec_count = 2;
+           }
+       }
+      else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+       {
+         /* Handle enhanced software breakpoint insn, BKPT.  */
+         /* CPSR is changed to be executed in ARM state,  disabling normal
+            interrupts, entering abort mode.  */
+         /* According to high vector configuration PC is set.  */
+         /* user hit breakpoint and type reverse, in
+            that case, we need to go back with previous CPSR and
+            Program Counter.  */
+         record_buf[0] = ARM_PS_REGNUM;
+         record_buf[1] = ARM_LR_REGNUM;
+         arm_insn_r->reg_rec_count = 2;
+
+         /* Save SPSR also; how?  */
+         return -1;
+       }
+      else if (1 == arm_insn_r->decode && 0x12 == opcode1
+              && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+       {
+         /* Handle BX, branch and link/exchange.  */
+         /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
+         record_buf[0] = ARM_PS_REGNUM;
+         arm_insn_r->reg_rec_count = 1;
+       }
+      else if (1 == arm_insn_r->decode && 0x16 == opcode1
+              && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+              && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+       {
+         /* Count leading zeros: CLZ.  */
+         record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+         arm_insn_r->reg_rec_count = 1;
+       }
+      else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+              && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+              && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+              && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+       {
+         /* Handle MRS insn.  */
+         record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+         arm_insn_r->reg_rec_count = 1;
+       }
     }
-  else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
-           && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
-           && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
-           && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+  else if (9 == arm_insn_r->decode && opcode1 < 0x10)
     {
-      /* Handle MSR insn.  */
-      if (9 == arm_insn_r->opcode)
-        {
-          /* CSPR is going to be changed.  */
-          record_buf[0] = ARM_PS_REGNUM;
-          arm_insn_r->reg_rec_count = 1;
-        }
-      else
-        {
-          /* SPSR is going to be changed.  */
-          /* How to read SPSR value?  */
-          return -1;
-        }
+      /* Multiply and multiply-accumulate */
+
+      /* Handle multiply instructions.  */
+      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
+      if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+         {
+           /* Handle MLA and MUL.  */
+           record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+           record_buf[1] = ARM_PS_REGNUM;
+           arm_insn_r->reg_rec_count = 2;
+         }
+       else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+         {
+           /* Handle SMLAL, SMULL, UMLAL, UMULL.  */
+           record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+           record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+           record_buf[2] = ARM_PS_REGNUM;
+           arm_insn_r->reg_rec_count = 3;
+         }
     }
-  else if (9 == arm_insn_r->decode
-           && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
-           && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+  else if (9 == arm_insn_r->decode  && opcode1 > 0x10)
     {
+      /* Synchronization primitives */
+
       /* Handling SWP, SWPB.  */
       /* These insn, changes register and memory as well.  */
       /* SWP or SWPB insn.  */
@@ -10315,91 +10380,169 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
       regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
       /* SWP insn ?, swaps word.  */
       if (8 == arm_insn_r->opcode)
-        {
-          record_buf_mem[0] = 4;
-        }
-        else
-        {
-          /* SWPB insn, swaps only byte.  */
-          record_buf_mem[0] = 1;
-        }
+       {
+         record_buf_mem[0] = 4;
+       }
+      else
+       {
+         /* SWPB insn, swaps only byte.  */
+         record_buf_mem[0] = 1;
+       }
       record_buf_mem[1] = u_regval[0];
       arm_insn_r->mem_rec_count = 1;
       record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
       arm_insn_r->reg_rec_count = 1;
     }
-  else if (3 == arm_insn_r->decode && 0x12 == opcode1
-           && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+  else if (11 == arm_insn_r->decode || 13 == arm_insn_r->decode
+          || 15 == arm_insn_r->decode)
     {
-      /* Handle BLX, branch and link/exchange.  */
-      if (9 == arm_insn_r->opcode)
-      {
-        /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
-           and R14 stores the return address.  */
-        record_buf[0] = ARM_PS_REGNUM;
-        record_buf[1] = ARM_LR_REGNUM;
-        arm_insn_r->reg_rec_count = 2;
-      }
-    }
-  else if (7 == arm_insn_r->decode && 0x12 == opcode1)
-    {
-      /* Handle enhanced software breakpoint insn, BKPT.  */
-      /* CPSR is changed to be executed in ARM state,  disabling normal
-         interrupts, entering abort mode.  */
-      /* According to high vector configuration PC is set.  */
-      /* user hit breakpoint and type reverse, in
-         that case, we need to go back with previous CPSR and
-         Program Counter.  */
-      record_buf[0] = ARM_PS_REGNUM;
-      record_buf[1] = ARM_LR_REGNUM;
-      arm_insn_r->reg_rec_count = 2;
+      if ((opcode1 & 0x12) == 2)
+       {
+         /* Extra load/store (unprivileged) */
+         return -1;
+       }
+      else
+       {
+         /* Extra load/store */
+         switch (bits (arm_insn_r->arm_insn, 5, 6))
+           {
+           case 1:
+             if ((opcode1 & 0x05) == 0x0 || (opcode1 & 0x05) == 0x4)
+               {
+                 /* STRH (register), STRH (immediate) */
+                 arm_record_strx (arm_insn_r, &record_buf[0],
+                                  &record_buf_mem[0], ARM_RECORD_STRH);
+               }
+             else if ((opcode1 & 0x05) == 0x1)
+               {
+                 /* LDRH (register) */
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
 
-      /* Save SPSR also; how?  */
-      return -1;
-    }
-  else if (11 == arm_insn_r->decode
-           && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
-  {
-    /* Handle enhanced store insns and DSP insns (e.g. LDRD).  */
+                 if (bit (arm_insn_r->arm_insn, 21))
+                   {
+                     /* Write back to Rn.  */
+                     record_buf[arm_insn_r->reg_rec_count++]
+                       = bits (arm_insn_r->arm_insn, 16, 19);
+                   }
+               }
+             else if ((opcode1 & 0x05) == 0x5)
+               {
+                 /* LDRH (immediate), LDRH (literal) */
+                 int rn = bits (arm_insn_r->arm_insn, 16, 19);
 
-    /* Handle str(x) insn */
-    arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
-                    ARM_RECORD_STRH);
-  }
-  else if (1 == arm_insn_r->decode && 0x12 == opcode1
-           && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
-    {
-      /* Handle BX, branch and link/exchange.  */
-      /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
-      record_buf[0] = ARM_PS_REGNUM;
-      arm_insn_r->reg_rec_count = 1;
-    }
-  else if (1 == arm_insn_r->decode && 0x16 == opcode1
-           && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
-           && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
-    {
-      /* Count leading zeros: CLZ.  */
-      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
-      arm_insn_r->reg_rec_count = 1;
-    }
-  else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
-           && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
-           && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
-           && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
-          )
-    {
-      /* Handle MRS insn.  */
-      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
-      arm_insn_r->reg_rec_count = 1;
-    }
-  else if (arm_insn_r->opcode <= 15)
-    {
-      /* Normal data processing insns.  */
-      /* Out of 11 shifter operands mode, all the insn modifies destination
-         register, which is specified by 13-16 decode.  */
-      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
-      record_buf[1] = ARM_PS_REGNUM;
-      arm_insn_r->reg_rec_count = 2;
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
+
+                 if (rn != 15)
+                   {
+                     /*LDRH (immediate) */
+                     if (bit (arm_insn_r->arm_insn, 21))
+                       {
+                         /* Write back to Rn.  */
+                         record_buf[arm_insn_r->reg_rec_count++] = rn;
+                       }
+                   }
+               }
+             else
+               return -1;
+             break;
+           case 2:
+             if ((opcode1 & 0x05) == 0x0)
+               {
+                 /* LDRD (register) */
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 record_buf[1] = record_buf[0] + 1;
+                 arm_insn_r->reg_rec_count = 2;
+
+                 if (bit (arm_insn_r->arm_insn, 21))
+                   {
+                     /* Write back to Rn.  */
+                     record_buf[arm_insn_r->reg_rec_count++]
+                       = bits (arm_insn_r->arm_insn, 16, 19);
+                   }
+               }
+             else if ((opcode1 & 0x05) == 0x1)
+               {
+                 /* LDRSB (register) */
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
+
+                 if (bit (arm_insn_r->arm_insn, 21))
+                   {
+                     /* Write back to Rn.  */
+                     record_buf[arm_insn_r->reg_rec_count++]
+                       = bits (arm_insn_r->arm_insn, 16, 19);
+                   }
+               }
+             else if ((opcode1 & 0x05) == 0x4 || (opcode1 & 0x05) == 0x5)
+               {
+                 /* LDRD (immediate), LDRD (literal), LDRSB (immediate),
+                    LDRSB (literal) */
+                 int rn = bits (arm_insn_r->arm_insn, 16, 19);
+
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
+
+                 if (rn != 15)
+                   {
+                     /*LDRD (immediate), LDRSB (immediate) */
+                     if (bit (arm_insn_r->arm_insn, 21))
+                       {
+                         /* Write back to Rn.  */
+                         record_buf[arm_insn_r->reg_rec_count++] = rn;
+                       }
+                   }
+               }
+             else
+               return -1;
+             break;
+           case 3:
+             if ((opcode1 & 0x05) == 0x0)
+               {
+                 /* STRD (register) */
+                 arm_record_strx (arm_insn_r, &record_buf[0],
+                                  &record_buf_mem[0], ARM_RECORD_STRD);
+               }
+             else if ((opcode1 & 0x05) == 0x1)
+               {
+                 /* LDRSH (register) */
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
+
+                 if (bit (arm_insn_r->arm_insn, 21))
+                   {
+                     /* Write back to Rn.  */
+                     record_buf[arm_insn_r->reg_rec_count++]
+                       = bits (arm_insn_r->arm_insn, 16, 19);
+                   }
+               }
+             else if ((opcode1 & 0x05) == 0x4)
+               {
+                 /* STRD (immediate) */
+                 arm_record_strx (arm_insn_r, &record_buf[0],
+                                  &record_buf_mem[0], ARM_RECORD_STRD);
+               }
+             else if ((opcode1 & 0x05) == 0x5)
+               {
+                 /* LDRSH (immediate), LDRSH (literal) */
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 arm_insn_r->reg_rec_count = 1;
+
+                 if (bit (arm_insn_r->arm_insn, 21))
+                   {
+                     /* Write back to Rn.  */
+                     record_buf[arm_insn_r->reg_rec_count++]
+                       = bits (arm_insn_r->arm_insn, 16, 19);
+                   }
+               }
+             else
+               return -1;
+             break;
+           default:
+             return -1;
+           }
+       }
     }
   else
     {
@@ -10660,7 +10803,7 @@ arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
     {
       reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
       /* LDR insn has a capability to do branching, if
-         MOV LR, PC is precedded by LDR insn having Rn as R15
+         MOV LR, PC is preceded by LDR insn having Rn as R15
          in that case, it emulates branch and link insn, and hence we
          need to save CSPR and PC as well.  */
       if (15 != reg_dest)
@@ -10962,7 +11105,7 @@ arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
          /* STMDA (STMED): Decrement after.  */
          case 0:
          record_buf_mem[1] = (uint32_t) u_regval
-                             - register_count * INT_REGISTER_SIZE + 4;
+                             - register_count * ARM_INT_REGISTER_SIZE + 4;
          break;
          /* STM (STMIA, STMEA): Increment after.  */
          case 1:
@@ -10971,18 +11114,18 @@ arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
          /* STMDB (STMFD): Decrement before.  */
          case 2:
          record_buf_mem[1] = (uint32_t) u_regval
-                             - register_count * INT_REGISTER_SIZE;
+                             - register_count * ARM_INT_REGISTER_SIZE;
          break;
          /* STMIB (STMFA): Increment before.  */
          case 3:
-         record_buf_mem[1] = (uint32_t) u_regval + INT_REGISTER_SIZE;
+         record_buf_mem[1] = (uint32_t) u_regval + ARM_INT_REGISTER_SIZE;
          break;
          default:
            gdb_assert_not_reached ("no decoding pattern found");
          break;
        }
 
-      record_buf_mem[0] = register_count * INT_REGISTER_SIZE;
+      record_buf_mem[0] = register_count * ARM_INT_REGISTER_SIZE;
       arm_insn_r->mem_rec_count = 1;
 
       /* If wback is true, also save the base register, which is going to be
@@ -11325,7 +11468,8 @@ arm_record_vfp_data_proc_insn (insn_decode_record *arm_insn_r)
   opc3 = bits (arm_insn_r->arm_insn, 6, 7);
   dp_op_sz = bit (arm_insn_r->arm_insn, 8);
   bit_d = bit (arm_insn_r->arm_insn, 22);
-  opc1 = opc1 & 0x04;
+  /* Mask off the "D" bit.  */
+  opc1 = opc1 & ~0x04;
 
   /* Handle VMLA, VMLS.  */
   if (opc1 == 0x00)
@@ -11390,7 +11534,7 @@ arm_record_vfp_data_proc_insn (insn_decode_record *arm_insn_r)
         }
     }
   /* Handle VDIV.  */
-  else if (opc1 == 0x0b)
+  else if (opc1 == 0x08)
     {
       if (dp_op_sz)
         curr_insn_type = INSN_T1;
@@ -11579,18 +11723,18 @@ arm_record_asimd_vfp_coproc (insn_decode_record *arm_insn_r)
 static int
 arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
 {
-  uint32_t op, op1_sbit, op1_ebit, coproc;
+  uint32_t op, op1_ebit, coproc, bits_24_25;
   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
   struct regcache *reg_cache = arm_insn_r->regcache;
 
   arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
   coproc = bits (arm_insn_r->arm_insn, 8, 11);
-  op1_sbit = bit (arm_insn_r->arm_insn, 24);
   op1_ebit = bit (arm_insn_r->arm_insn, 20);
   op = bit (arm_insn_r->arm_insn, 4);
+  bits_24_25 = bits (arm_insn_r->arm_insn, 24, 25);
 
   /* Handle arm SWI/SVC system call instructions.  */
-  if (op1_sbit)
+  if (bits_24_25 == 0x3)
     {
       if (tdep->arm_syscall_record != NULL)
         {
@@ -11611,44 +11755,97 @@ arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
           return -1;
         }
     }
-
-  if ((coproc & 0x0e) == 0x0a)
+  else if (bits_24_25 == 0x02)
     {
-      /* VFP data-processing instructions.  */
-      if (!op1_sbit && !op)
-        return arm_record_vfp_data_proc_insn (arm_insn_r);
+      if (op)
+       {
+         if ((coproc & 0x0e) == 0x0a)
+           {
+             /* 8, 16, and 32-bit transfer */
+             return arm_record_vdata_transfer_insn (arm_insn_r);
+           }
+         else
+           {
+             if (op1_ebit)
+               {
+                 /* MRC, MRC2 */
+                 uint32_t record_buf[1];
+
+                 record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                 if (record_buf[0] == 15)
+                   record_buf[0] = ARM_PS_REGNUM;
 
-      /* Advanced SIMD, VFP instructions.  */
-      if (!op1_sbit && op)
-        return arm_record_vdata_transfer_insn (arm_insn_r);
+                 arm_insn_r->reg_rec_count = 1;
+                 REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
+                            record_buf);
+                 return 0;
+               }
+             else
+               {
+                 /* MCR, MCR2 */
+                 return -1;
+               }
+           }
+       }
+      else
+       {
+         if ((coproc & 0x0e) == 0x0a)
+           {
+             /* VFP data-processing instructions.  */
+             return arm_record_vfp_data_proc_insn (arm_insn_r);
+           }
+         else
+           {
+             /* CDP, CDP2 */
+             return -1;
+           }
+       }
     }
   else
     {
-      /* Coprocessor data operations.  */
-      if (!op1_sbit && !op)
-        return arm_record_unsupported_insn (arm_insn_r);
-
-      /* Move to Coprocessor from ARM core register.  */
-      if (!op1_sbit && !op1_ebit && op)
-        return arm_record_unsupported_insn (arm_insn_r);
-
-      /* Move to arm core register from coprocessor.  */
-      if (!op1_sbit && op1_ebit && op)
-        {
-          uint32_t record_buf[1];
-
-          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
-          if (record_buf[0] == 15)
-            record_buf[0] = ARM_PS_REGNUM;
+      unsigned int op1 = bits (arm_insn_r->arm_insn, 20, 25);
 
-          arm_insn_r->reg_rec_count = 1;
-          REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
-                     record_buf);
-          return 0;
-        }
+      if (op1 == 5)
+       {
+         if ((coproc & 0x0e) != 0x0a)
+           {
+             /* MRRC, MRRC2 */
+             return -1;
+           }
+       }
+      else if (op1 == 4 || op1 == 5)
+       {
+         if ((coproc & 0x0e) == 0x0a)
+           {
+             /* 64-bit transfers between ARM core and extension */
+             return -1;
+           }
+         else if (op1 == 4)
+           {
+             /* MCRR, MCRR2 */
+             return -1;
+           }
+       }
+      else if (op1 == 0 || op1 == 1)
+       {
+         /* UNDEFINED */
+         return -1;
+       }
+      else
+       {
+         if ((coproc & 0x0e) == 0x0a)
+           {
+             /* Extension register load/store */
+           }
+         else
+           {
+             /* STC, STC2, LDC, LDC2 */
+           }
+         return -1;
+       }
     }
 
-  return arm_record_unsupported_insn (arm_insn_r);
+  return -1;
 }
 
 /* Handling opcode 000 insns.  */
@@ -12913,7 +13110,7 @@ public:
 class instruction_reader : public abstract_memory_reader
 {
  public:
-  bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len)
+  bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len) override
   {
     if (target_read_memory (memaddr, buf, len))
       return false;
@@ -12925,7 +13122,7 @@ class instruction_reader : public abstract_memory_reader
 } // namespace
 
 /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success 
-and positive val on fauilure.  */
+and positive val on failure.  */
 
 static int
 extract_arm_insn (abstract_memory_reader& reader,
@@ -13066,7 +13263,7 @@ public:
     : m_endian (endian), m_insns (insns), m_insns_size (SIZE)
   {}
 
-  bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len)
+  bool read (CORE_ADDR memaddr, gdb_byte *buf, const size_t len) override
   {
     SELF_CHECK (len == 4 || len == 2);
     SELF_CHECK (memaddr % 2 == 0);
@@ -13273,3 +13470,35 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
 
   return ret;
 }
+
+/* See arm-tdep.h.  */
+
+const target_desc *
+arm_read_description (arm_fp_type fp_type)
+{
+  struct target_desc *tdesc = tdesc_arm_list[fp_type];
+
+  if (tdesc == nullptr)
+    {
+      tdesc = arm_create_target_description (fp_type);
+      tdesc_arm_list[fp_type] = tdesc;
+    }
+
+  return tdesc;
+}
+
+/* See arm-tdep.h.  */
+
+const target_desc *
+arm_read_mprofile_description (arm_m_profile_type m_type)
+{
+  struct target_desc *tdesc = tdesc_arm_mprofile_list[m_type];
+
+  if (tdesc == nullptr)
+    {
+      tdesc = arm_create_mprofile_target_description (m_type);
+      tdesc_arm_mprofile_list[m_type] = tdesc;
+    }
+
+  return tdesc;
+}