Implement breakpoint_kind_from_pc and sw_breakpoint_from_kind for ARM in GDBServer.
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index b14b944122d229a74c4a328621c570cd3376cf59..3a6c6d86554a72a4801f942a302ff76d6d46779c 100644 (file)
@@ -1,7 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
 
-   Copyright (C) 1988-1989, 1991-1993, 1995-1996, 1998-2012 Free
-   Software Foundation, Inc.
+   Copyright (C) 1988-2015 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
+#include "defs.h"
+
 #include <ctype.h>             /* XXX for isupper ().  */
 
-#include "defs.h"
 #include "frame.h"
 #include "inferior.h"
+#include "infrun.h"
 #include "gdbcmd.h"
 #include "gdbcore.h"
-#include "gdb_string.h"
 #include "dis-asm.h"           /* For register styles.  */
 #include "regcache.h"
 #include "reggroups.h"
@@ -45,6 +45,7 @@
 #include "user-regs.h"
 #include "observer.h"
 
+#include "arch/arm.h"
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
 
 #include "coff/internal.h"
 #include "elf/arm.h"
 
-#include "gdb_assert.h"
 #include "vec.h"
 
 #include "record.h"
+#include "record-full.h"
 
 #include "features/arm-with-m.c"
 #include "features/arm-with-m-fpa-layout.c"
+#include "features/arm-with-m-vfp-d16.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
 #include "features/arm-with-vfpv3.c"
@@ -234,8 +236,6 @@ static void arm_neon_quad_write (struct gdbarch *gdbarch,
                                 struct regcache *regcache,
                                 int regnum, const gdb_byte *buf);
 
-static int thumb_insn_size (unsigned short inst1);
-
 struct arm_prologue_cache
 {
   /* The stack pointer at the time this frame was created; i.e. the
@@ -266,12 +266,6 @@ static CORE_ADDR arm_analyze_prologue (struct gdbarch *gdbarch,
 
 #define DISPLACED_STEPPING_ARCH_VERSION                5
 
-/* Addresses for calling Thumb functions have the bit 0 set.
-   Here are some macros to test, set, or clear bit 0 of addresses.  */
-#define IS_THUMB_ADDR(addr)    ((addr) & 1)
-#define MAKE_THUMB_ADDR(addr)  ((addr) | 1)
-#define UNMAKE_THUMB_ADDR(addr) ((addr) & ~1)
-
 /* Set to true if the 32-bit mode is in use.  */
 
 int arm_apcs_32 = 1;
@@ -332,7 +326,8 @@ arm_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
                                            0 };
       unsigned int idx;
 
-      data = objfile_data (sec->objfile, arm_objfile_data_key);
+      data = (struct arm_per_objfile *) objfile_data (sec->objfile,
+                                                     arm_objfile_data_key);
       if (data != NULL)
        {
          map = data->section_maps[sec->the_bfd_section->index];
@@ -379,8 +374,7 @@ arm_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start)
 int
 arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 {
-  struct obj_section *sec;
-  struct minimal_symbol *sym;
+  struct bound_minimal_symbol sym;
   char type;
   struct displaced_step_closure* dsc
     = get_displaced_step_closure_by_addr(memaddr);
@@ -422,8 +416,8 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 
   /* Thumb functions have a "special" bit set in minimal symbols.  */
   sym = lookup_minimal_symbol_by_pc (memaddr);
-  if (sym)
-    return (MSYMBOL_IS_SPECIAL (sym));
+  if (sym.minsym)
+    return (MSYMBOL_IS_SPECIAL (sym.minsym));
 
   /* If the user wants to override the fallback mode, let them.  */
   if (strcmp (arm_fallback_mode_string, "arm") == 0)
@@ -447,20 +441,18 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
 static CORE_ADDR
 arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
 {
+  /* On M-profile devices, do not strip the low bit from EXC_RETURN
+     (the magic exception return address).  */
+  if (gdbarch_tdep (gdbarch)->is_m
+      && (val & 0xfffffff0) == 0xfffffff0)
+    return val;
+
   if (arm_apcs_32)
     return UNMAKE_THUMB_ADDR (val);
   else
     return (val & 0x03fffffc);
 }
 
-/* When reading symbols, we need to zap the low bit of the address,
-   which may be set to 1 for Thumb functions.  */
-static CORE_ADDR
-arm_smash_text_address (struct gdbarch *gdbarch, CORE_ADDR val)
-{
-  return val & ~1;
-}
-
 /* Return 1 if PC is the start of a compiler helper function which
    can be safely ignored during prologue skipping.  IS_THUMB is true
    if the function is known to be a Thumb function due to the way it
@@ -469,14 +461,14 @@ static int
 skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
-  struct minimal_symbol *msym;
+  struct bound_minimal_symbol msym;
 
   msym = lookup_minimal_symbol_by_pc (pc);
-  if (msym != NULL
-      && SYMBOL_VALUE_ADDRESS (msym) == pc
-      && SYMBOL_LINKAGE_NAME (msym) != NULL)
+  if (msym.minsym != NULL
+      && BMSYMBOL_VALUE_ADDRESS (msym) == pc
+      && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL)
     {
-      const char *name = SYMBOL_LINKAGE_NAME (msym);
+      const char *name = MSYMBOL_LINKAGE_NAME (msym.minsym);
 
       /* The GNU linker's Thumb call stub to foo is named
         __foo_from_thumb.  */
@@ -486,15 +478,15 @@ skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
       /* On soft-float targets, __truncdfsf2 is called to convert promoted
         arguments to their argument types in non-prototyped
         functions.  */
-      if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
+      if (startswith (name, "__truncdfsf2"))
        return 1;
-      if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
+      if (startswith (name, "__aeabi_d2f"))
        return 1;
 
       /* Internal functions related to thread-local storage.  */
-      if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
+      if (startswith (name, "__tls_get_addr"))
        return 1;
-      if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
+      if (startswith (name, "__aeabi_read_tp"))
        return 1;
     }
   else
@@ -522,7 +514,7 @@ skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
 #define sbits(obj,st,fn) \
   ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
 #define BranchDest(addr,instr) \
-  ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
+  ((CORE_ADDR) (((unsigned long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
 
 /* Extract the immediate from instruction movw/movt of encoding T.  INSN1 is
    the first 16-bit of instruction, and INSN2 is the second 16-bit of
@@ -685,6 +677,17 @@ thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2)
   return 0;
 }
 
+/* Return 1 if the 16-bit Thumb instruction INSN restores SP in
+   epilogue, 0 otherwise.  */
+
+static int
+thumb_instruction_restores_sp (unsigned short insn)
+{
+  return (insn == 0x46bd  /* mov sp, r7 */
+         || (insn & 0xff80) == 0xb000  /* add sp, imm */
+         || (insn & 0xfe00) == 0xbc00);  /* pop <registers> */
+}
+
 /* Analyze a Thumb prologue, looking for a recognizable stack frame
    and frame pointer.  Scan until we encounter a store that could
    clobber the stack frame unexpectedly, or an unknown instruction.
@@ -737,16 +740,16 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
                pv_area_store (stack, regs[ARM_SP_REGNUM], 4, regs[regno]);
              }
        }
-      else if ((insn & 0xff00) == 0xb000)      /* add sp, #simm  OR  
-                                                  sub sp, #simm */
+      else if ((insn & 0xff80) == 0xb080)      /* sub sp, #imm */
        {
          offset = (insn & 0x7f) << 2;          /* get scaled offset */
-         if (insn & 0x80)                      /* Check for SUB.  */
-           regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
-                                                  -offset);
-         else
-           regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
-                                                  offset);
+         regs[ARM_SP_REGNUM] = pv_add_constant (regs[ARM_SP_REGNUM],
+                                                -offset);
+       }
+      else if (thumb_instruction_restores_sp (insn))
+       {
+         /* Don't scan past the epilogue.  */
+         break;
        }
       else if ((insn & 0xf800) == 0xa800)      /* add Rd, sp, #imm */
        regs[bits (insn, 8, 10)] = pv_add_constant (regs[ARM_SP_REGNUM],
@@ -1072,7 +1075,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
              unsigned int constant;
              CORE_ADDR loc;
 
-             offset = bits (insn, 0, 11);
+             offset = bits (inst2, 0, 11);
              if (insn & 0x0080)
                loc = start + 4 + offset;
              else
@@ -1088,7 +1091,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
              unsigned int constant;
              CORE_ADDR loc;
 
-             offset = bits (insn, 0, 7) << 2;
+             offset = bits (inst2, 0, 7) << 2;
              if (insn & 0x0080)
                loc = start + 4 + offset;
              else
@@ -1195,7 +1198,9 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
        {
          *destreg = bits (insn1, 8, 10);
          *offset = 2;
-         address = bits (insn1, 0, 7);
+         address = (pc & 0xfffffffc) + 4 + (bits (insn1, 0, 7) << 2);
+         address = read_memory_unsigned_integer (address, 4,
+                                                 byte_order_for_code);
        }
       else if ((insn1 & 0xfbf0) == 0xf240) /* movw Rd, #const */
        {
@@ -1224,9 +1229,12 @@ arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
       unsigned int insn
        = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
 
-      if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, #immed */
+      if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, [PC, #immed] */
        {
-         address = bits (insn, 0, 11);
+         address = bits (insn, 0, 11) + pc + 8;
+         address = read_memory_unsigned_integer (address, 4,
+                                                 byte_order_for_code);
+
          *destreg = bits (insn, 12, 15);
          *offset = 4;
        }
@@ -1284,8 +1292,8 @@ static CORE_ADDR
 arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
-  unsigned int address, basereg;
-  struct minimal_symbol *stack_chk_guard;
+  unsigned int basereg;
+  struct bound_minimal_symbol stack_chk_guard;
   int offset;
   int is_thumb = arm_pc_is_thumb (gdbarch, pc);
   CORE_ADDR addr;
@@ -1297,12 +1305,10 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
     return pc;
 
   stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
-  /* If name of symbol doesn't start with '__stack_chk_guard', this
-     instruction sequence is not for stack protector.  If symbol is
-     removed, we conservatively think this sequence is for stack protector.  */
-  if (stack_chk_guard
-      && strncmp (SYMBOL_LINKAGE_NAME (stack_chk_guard), "__stack_chk_guard",
-                 strlen ("__stack_chk_guard")) != 0)
+  /* 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"))
    return pc;
 
   if (is_thumb)
@@ -1374,9 +1380,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned long inst;
-  CORE_ADDR skip_pc;
   CORE_ADDR func_addr, limit_pc;
-  struct symtab_and_line sal;
 
   /* See if we can determine the end of the prologue via the symbol table.
      If so, then return either PC, or the PC after the prologue, whichever
@@ -1385,7 +1389,7 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
     {
       CORE_ADDR post_prologue_pc
        = skip_prologue_using_sal (gdbarch, func_addr);
-      struct symtab *s = find_pc_symtab (func_addr);
+      struct compunit_symtab *cust = find_pc_compunit_symtab (func_addr);
 
       if (post_prologue_pc)
        post_prologue_pc
@@ -1399,9 +1403,10 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
         will have producer information for most binaries; if it is
         missing (e.g. for -gstabs), assuming the GNU tools.  */
       if (post_prologue_pc
-         && (s == NULL
-             || s->producer == NULL
-             || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0))
+         && (cust == NULL
+             || COMPUNIT_PRODUCER (cust) == NULL
+             || startswith (COMPUNIT_PRODUCER (cust), "GNU ")
+             || startswith (COMPUNIT_PRODUCER (cust), "clang ")))
        return post_prologue_pc;
 
       if (post_prologue_pc != 0)
@@ -1446,65 +1451,8 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   /* Check if this is Thumb code.  */
   if (arm_pc_is_thumb (gdbarch, pc))
     return thumb_analyze_prologue (gdbarch, pc, limit_pc, NULL);
-
-  for (skip_pc = pc; skip_pc < limit_pc; skip_pc += 4)
-    {
-      inst = read_memory_unsigned_integer (skip_pc, 4, byte_order_for_code);
-
-      /* "mov ip, sp" is no longer a required part of the prologue.  */
-      if (inst == 0xe1a0c00d)                  /* mov ip, sp */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe28dc000)    /* add ip, sp #n */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24dc000)    /* sub ip, sp #n */
-       continue;
-
-      /* Some prologues begin with "str lr, [sp, #-4]!".  */
-      if (inst == 0xe52de004)                  /* str lr, [sp, #-4]! */
-       continue;
-
-      if ((inst & 0xfffffff0) == 0xe92d0000)   /* stmfd sp!,{a1,a2,a3,a4} */
-       continue;
-
-      if ((inst & 0xfffff800) == 0xe92dd800)   /* stmfd sp!,{fp,ip,lr,pc} */
-       continue;
-
-      /* Any insns after this point may float into the code, if it makes
-        for better instruction scheduling, so we skip them only if we
-        find them, but still consider the function to be frame-ful.  */
-
-      /* We may have either one sfmfd instruction here, or several stfe
-        insns, depending on the version of floating point code we
-        support.  */
-      if ((inst & 0xffbf0fff) == 0xec2d0200)   /* sfmfd fn, <cnt>, [sp]! */
-       continue;
-
-      if ((inst & 0xffff8fff) == 0xed6d0103)   /* stfe fn, [sp, #-12]! */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24cb000)   /* sub fp, ip, #nn */
-       continue;
-
-      if ((inst & 0xfffff000) == 0xe24dd000)   /* sub sp, sp, #nn */
-       continue;
-
-      if ((inst & 0xffffc000) == 0xe54b0000    /* strb r(0123),[r11,#-nn] */
-         || (inst & 0xffffc0f0) == 0xe14b00b0  /* strh r(0123),[r11,#-nn] */
-         || (inst & 0xffffc000) == 0xe50b0000) /* str  r(0123),[r11,#-nn] */
-       continue;
-
-      if ((inst & 0xffffc000) == 0xe5cd0000    /* strb r(0123),[sp,#nn] */
-         || (inst & 0xffffc0f0) == 0xe1cd00b0  /* strh r(0123),[sp,#nn] */
-         || (inst & 0xffffc000) == 0xe58d0000) /* str  r(0123),[sp,#nn] */
-       continue;
-
-      /* Un-recognized instruction; stop scanning.  */
-      break;
-    }
-
-  return skip_pc;              /* End of prologue.  */
+  else
+    return arm_analyze_prologue (gdbarch, pc, limit_pc, NULL);
 }
 
 /* *INDENT-OFF* */
@@ -1535,7 +1483,6 @@ thumb_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR prev_pc,
 {
   CORE_ADDR prologue_start;
   CORE_ADDR prologue_end;
-  CORE_ADDR current_pc;
 
   if (find_pc_partial_function (block_addr, NULL, &prologue_start,
                                &prologue_end))
@@ -1649,6 +1596,30 @@ arm_instruction_changes_pc (uint32_t this_instr)
       }
 }
 
+/* Return 1 if the ARM instruction INSN restores SP in epilogue, 0
+   otherwise.  */
+
+static int
+arm_instruction_restores_sp (unsigned int insn)
+{
+  if (bits (insn, 28, 31) != INST_NV)
+    {
+      if ((insn & 0x0df0f000) == 0x0080d000
+         /* ADD SP (register or immediate).  */
+         || (insn & 0x0df0f000) == 0x0040d000
+         /* SUB SP (register or immediate).  */
+         || (insn & 0x0ffffff0) == 0x01a0d000
+         /* MOV SP.  */
+         || (insn & 0x0fff0000) == 0x08bd0000
+         /* POP (LDMIA).  */
+         || (insn & 0x0fff0000) == 0x049d0000)
+         /* POP of a single register.  */
+       return 1;
+    }
+
+  return 0;
+}
+
 /* Analyze an ARM mode prologue starting at PROLOGUE_START and
    continuing no further than PROLOGUE_END.  If CACHE is non-NULL,
    fill it in.  Return the first address not recognized as a prologue
@@ -1671,7 +1642,6 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
   pv_t regs[ARM_FPS_REGNUM];
   struct pv_area *stack;
   struct cleanup *back_to;
-  int framereg, framesize;
   CORE_ADDR unrecognized_pc = 0;
 
   /* Search the prologue looking for instructions that set up the
@@ -1847,6 +1817,11 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
       else if (arm_instruction_changes_pc (insn))
        /* Don't scan past anything that might change control flow.  */
        break;
+      else if (arm_instruction_restores_sp (insn))
+       {
+         /* Don't scan past the epilogue.  */
+         break;
+       }
       else if ((insn & 0xfe500000) == 0xe8100000       /* ldm */
               && pv_is_register (regs[bits (insn, 16, 19)], ARM_SP_REGNUM))
        /* Ignore block loads from the stack, potentially copying
@@ -1862,33 +1837,42 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
        continue;
       else
        {
-         /* The optimizer might shove anything into the prologue,
-            so we just skip what we don't recognize.  */
+         /* The optimizer might shove anything into the prologue, if
+            we build up cache (cache != NULL) from scanning prologue,
+            we just skip what we don't recognize and scan further to
+            make cache as complete as possible.  However, if we skip
+            prologue, we'll stop immediately on unrecognized
+            instruction.  */
          unrecognized_pc = current_pc;
-         continue;
+         if (cache != NULL)
+           continue;
+         else
+           break;
        }
     }
 
   if (unrecognized_pc == 0)
     unrecognized_pc = current_pc;
 
-  /* The frame size is just the distance from the frame register
-     to the original stack pointer.  */
-  if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
-    {
-      /* Frame pointer is fp.  */
-      framereg = ARM_FP_REGNUM;
-      framesize = -regs[ARM_FP_REGNUM].k;
-    }
-  else
-    {
-      /* Try the stack pointer... this is a bit desperate.  */
-      framereg = ARM_SP_REGNUM;
-      framesize = -regs[ARM_SP_REGNUM].k;
-    }
-
   if (cache)
     {
+      int framereg, framesize;
+
+      /* The frame size is just the distance from the frame register
+        to the original stack pointer.  */
+      if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
+       {
+         /* Frame pointer is fp.  */
+         framereg = ARM_FP_REGNUM;
+         framesize = -regs[ARM_FP_REGNUM].k;
+       }
+      else
+       {
+         /* Try the stack pointer... this is a bit desperate.  */
+         framereg = ARM_SP_REGNUM;
+         framesize = -regs[ARM_SP_REGNUM].k;
+       }
+
       cache->framereg = framereg;
       cache->framesize = framesize;
 
@@ -2027,6 +2011,31 @@ arm_make_prologue_cache (struct frame_info *this_frame)
   return cache;
 }
 
+/* Implementation of the stop_reason hook for arm_prologue frames.  */
+
+static enum unwind_stop_reason
+arm_prologue_unwind_stop_reason (struct frame_info *this_frame,
+                                void **this_cache)
+{
+  struct arm_prologue_cache *cache;
+  CORE_ADDR pc;
+
+  if (*this_cache == NULL)
+    *this_cache = arm_make_prologue_cache (this_frame);
+  cache = (struct arm_prologue_cache *) *this_cache;
+
+  /* This is meant to halt the backtrace at "_start".  */
+  pc = get_frame_pc (this_frame);
+  if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
+    return UNWIND_OUTERMOST;
+
+  /* If we've hit a wall, stop.  */
+  if (cache->prev_sp == 0)
+    return UNWIND_OUTERMOST;
+
+  return UNWIND_NO_REASON;
+}
+
 /* Our frame ID for a normal frame is the current function's starting PC
    and the caller's SP when we were called.  */
 
@@ -2041,20 +2050,12 @@ arm_prologue_this_id (struct frame_info *this_frame,
 
   if (*this_cache == NULL)
     *this_cache = arm_make_prologue_cache (this_frame);
-  cache = *this_cache;
-
-  /* This is meant to halt the backtrace at "_start".  */
-  pc = get_frame_pc (this_frame);
-  if (pc <= gdbarch_tdep (get_frame_arch (this_frame))->lowest_pc)
-    return;
-
-  /* If we've hit a wall, stop.  */
-  if (cache->prev_sp == 0)
-    return;
+  cache = (struct arm_prologue_cache *) *this_cache;
 
   /* Use function start address as part of the frame ID.  If we cannot
      identify the start address (due to missing symbol information),
      fall back to just using the current PC.  */
+  pc = get_frame_pc (this_frame);
   func = get_frame_func (this_frame);
   if (!func)
     func = pc;
@@ -2073,7 +2074,7 @@ arm_prologue_prev_register (struct frame_info *this_frame,
 
   if (*this_cache == NULL)
     *this_cache = arm_make_prologue_cache (this_frame);
-  cache = *this_cache;
+  cache = (struct arm_prologue_cache *) *this_cache;
 
   /* If we are asked to unwind the PC, then we need to return the LR
      instead.  The prologue may save PC, but it will point into this
@@ -2123,7 +2124,7 @@ arm_prologue_prev_register (struct frame_info *this_frame,
 
 struct frame_unwind arm_prologue_unwind = {
   NORMAL_FRAME,
-  default_frame_unwind_stop_reason,
+  arm_prologue_unwind_stop_reason,
   arm_prologue_this_id,
   arm_prologue_prev_register,
   NULL,
@@ -2153,7 +2154,7 @@ struct arm_exidx_data
 static void
 arm_exidx_data_free (struct objfile *objfile, void *arg)
 {
-  struct arm_exidx_data *data = arg;
+  struct arm_exidx_data *data = (struct arm_exidx_data *) arg;
   unsigned int i;
 
   for (i = 0; i < objfile->obfd->section_count; i++)
@@ -2223,7 +2224,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
     {
       exidx_vma = bfd_section_vma (objfile->obfd, exidx);
       exidx_size = bfd_get_section_size (exidx);
-      exidx_data = xmalloc (exidx_size);
+      exidx_data = (gdb_byte *) xmalloc (exidx_size);
       make_cleanup (xfree, exidx_data);
 
       if (!bfd_get_section_contents (objfile->obfd, exidx,
@@ -2239,7 +2240,7 @@ arm_exidx_new_objfile (struct objfile *objfile)
     {
       extab_vma = bfd_section_vma (objfile->obfd, extab);
       extab_size = bfd_get_section_size (extab);
-      extab_data = xmalloc (extab_size);
+      extab_data = (gdb_byte *) xmalloc (extab_size);
       make_cleanup (xfree, extab_data);
 
       if (!bfd_get_section_contents (objfile->obfd, extab,
@@ -2376,8 +2377,9 @@ arm_exidx_new_objfile (struct objfile *objfile)
         extab section starting at ADDR.  */
       if (n_bytes || n_words)
        {
-         gdb_byte *p = entry = obstack_alloc (&objfile->objfile_obstack,
-                                              n_bytes + n_words * 4 + 1);
+         gdb_byte *p = entry
+           = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack,
+                                         n_bytes + n_words * 4 + 1);
 
          while (n_bytes--)
            *p++ = (gdb_byte) ((word >> (8 * n_bytes)) & 0xff);
@@ -2427,7 +2429,8 @@ arm_find_exidx_entry (CORE_ADDR memaddr, CORE_ADDR *start)
       struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
       unsigned int idx;
 
-      data = objfile_data (sec->objfile, arm_exidx_data_key);
+      data = ((struct arm_exidx_data *)
+             objfile_data (sec->objfile, arm_exidx_data_key));
       if (data != NULL)
        {
          map = data->section_maps[sec->the_bfd_section->index];
@@ -2870,6 +2873,64 @@ struct frame_unwind arm_exidx_unwind = {
   arm_exidx_unwind_sniffer
 };
 
+/* Recognize GCC's trampoline for thumb call-indirect.  If we are in a
+   trampoline, return the target PC.  Otherwise return 0.
+
+   void call0a (char c, short s, int i, long l) {}
+
+   int main (void)
+   {
+     (*pointer_to_call0a) (c, s, i, l);
+   }
+
+   Instead of calling a stub library function  _call_via_xx (xx is
+   the register name), GCC may inline the trampoline in the object
+   file as below (register r2 has the address of call0a).
+
+   .global main
+   .type main, %function
+   ...
+   bl .L1
+   ...
+   .size main, .-main
+
+   .L1:
+   bx r2
+
+   The trampoline 'bx r2' doesn't belong to main.  */
+
+static CORE_ADDR
+arm_skip_bx_reg (struct frame_info *frame, CORE_ADDR pc)
+{
+  /* The heuristics of recognizing such trampoline is that FRAME is
+     executing in Thumb mode and the instruction on PC is 'bx Rm'.  */
+  if (arm_frame_is_thumb (frame))
+    {
+      gdb_byte buf[2];
+
+      if (target_read_memory (pc, buf, 2) == 0)
+       {
+         struct gdbarch *gdbarch = get_frame_arch (frame);
+         enum bfd_endian byte_order_for_code
+           = gdbarch_byte_order_for_code (gdbarch);
+         uint16_t insn
+           = extract_unsigned_integer (buf, 2, byte_order_for_code);
+
+         if ((insn & 0xff80) == 0x4700)  /* bx <Rm> */
+           {
+             CORE_ADDR dest
+               = get_frame_register_unsigned (frame, bits (insn, 3, 6));
+
+             /* Clear the LSB so that gdb core sets step-resume
+                breakpoint at the right address.  */
+             return UNMAKE_THUMB_ADDR (dest);
+           }
+       }
+    }
+
+  return 0;
+}
+
 static struct arm_prologue_cache *
 arm_make_stub_cache (struct frame_info *this_frame)
 {
@@ -2894,7 +2955,7 @@ arm_stub_this_id (struct frame_info *this_frame,
 
   if (*this_cache == NULL)
     *this_cache = arm_make_stub_cache (this_frame);
-  cache = *this_cache;
+  cache = (struct arm_prologue_cache *) *this_cache;
 
   *this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
 }
@@ -2905,13 +2966,20 @@ arm_stub_unwind_sniffer (const struct frame_unwind *self,
                         void **this_prologue_cache)
 {
   CORE_ADDR addr_in_block;
-  char dummy[4];
+  gdb_byte dummy[4];
+  CORE_ADDR pc, start_addr;
+  const char *name;
 
   addr_in_block = get_frame_address_in_block (this_frame);
-  if (in_plt_section (addr_in_block, NULL)
+  pc = get_frame_pc (this_frame);
+  if (in_plt_section (addr_in_block)
       /* We also use the stub winder if the target memory is unreadable
         to avoid having the prologue unwinder trying to read it.  */
-      || target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
+      || target_read_memory (pc, dummy, 4) != 0)
+    return 1;
+
+  if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0
+      && arm_skip_bx_reg (this_frame, pc) != 0)
     return 1;
 
   return 0;
@@ -2926,6 +2994,127 @@ struct frame_unwind arm_stub_unwind = {
   arm_stub_unwind_sniffer
 };
 
+/* Put here the code to store, into CACHE->saved_regs, the addresses
+   of the saved registers of frame described by THIS_FRAME.  CACHE is
+   returned.  */
+
+static struct arm_prologue_cache *
+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 unwound_sp;
+  LONGEST xpsr;
+
+  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);
+
+  /* The hardware saves eight 32-bit words, comprising xPSR,
+     ReturnAddress, LR (R14), R12, R3, R2, R1, R0.  See details in
+     "B1.5.6 Exception entry behavior" in
+     "ARMv7-M Architecture Reference Manual".  */
+  cache->saved_regs[0].addr = unwound_sp;
+  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_PS_REGNUM].addr = unwound_sp + 28;
+
+  /* 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;
+
+  return cache;
+}
+
+/* Implementation of function hook 'this_id' in
+   'struct frame_uwnind'.  */
+
+static void
+arm_m_exception_this_id (struct frame_info *this_frame,
+                        void **this_cache,
+                        struct frame_id *this_id)
+{
+  struct arm_prologue_cache *cache;
+
+  if (*this_cache == NULL)
+    *this_cache = arm_m_exception_cache (this_frame);
+  cache = (struct arm_prologue_cache *) *this_cache;
+
+  /* Our frame ID for a stub frame is the current SP and LR.  */
+  *this_id = frame_id_build (cache->prev_sp,
+                            get_frame_pc (this_frame));
+}
+
+/* Implementation of function hook 'prev_register' in
+   'struct frame_uwnind'.  */
+
+static struct value *
+arm_m_exception_prev_register (struct frame_info *this_frame,
+                              void **this_cache,
+                              int prev_regnum)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  struct arm_prologue_cache *cache;
+
+  if (*this_cache == NULL)
+    *this_cache = arm_m_exception_cache (this_frame);
+  cache = (struct arm_prologue_cache *) *this_cache;
+
+  /* The value was already reconstructed into PREV_SP.  */
+  if (prev_regnum == ARM_SP_REGNUM)
+    return frame_unwind_got_constant (this_frame, prev_regnum,
+                                     cache->prev_sp);
+
+  return trad_frame_get_prev_register (this_frame, cache->saved_regs,
+                                      prev_regnum);
+}
+
+/* Implementation of function hook 'sniffer' in
+   'struct frame_uwnind'.  */
+
+static int
+arm_m_exception_unwind_sniffer (const struct frame_unwind *self,
+                               struct frame_info *this_frame,
+                               void **this_prologue_cache)
+{
+  CORE_ADDR this_pc = get_frame_pc (this_frame);
+
+  /* No need to check is_m; this sniffer is only registered for
+     M-profile architectures.  */
+
+  /* Exception frames return to one of these magic PCs.  Other values
+     are not defined as of v7-M.  See details in "B1.5.8 Exception
+     return behavior" in "ARMv7-M Architecture Reference Manual".  */
+  if (this_pc == 0xfffffff1 || this_pc == 0xfffffff9
+      || this_pc == 0xfffffffd)
+    return 1;
+
+  return 0;
+}
+
+/* Frame unwinder for M-profile exceptions.  */
+
+struct frame_unwind arm_m_exception_unwind =
+{
+  SIGTRAMP_FRAME,
+  default_frame_unwind_stop_reason,
+  arm_m_exception_this_id,
+  arm_m_exception_prev_register,
+  NULL,
+  arm_m_exception_unwind_sniffer
+};
+
 static CORE_ADDR
 arm_normal_frame_base (struct frame_info *this_frame, void **this_cache)
 {
@@ -2933,7 +3122,7 @@ arm_normal_frame_base (struct frame_info *this_frame, void **this_cache)
 
   if (*this_cache == NULL)
     *this_cache = arm_make_prologue_cache (this_frame);
-  cache = *this_cache;
+  cache = (struct arm_prologue_cache *) *this_cache;
 
   return cache->prev_sp - cache->framesize;
 }
@@ -3030,11 +3219,10 @@ arm_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
     }
 }
 
-/* Return true if we are in the function's epilogue, i.e. after the
-   instruction that destroyed the function's stack frame.  */
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
 
 static int
-thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned int insn, insn2;
@@ -3076,14 +3264,9 @@ thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
        found_return = 1;
       else if (insn == 0x46f7)  /* mov pc, lr */
        found_return = 1;
-      else if (insn == 0x46bd)  /* mov sp, r7 */
-       found_stack_adjust = 1;
-      else if ((insn & 0xff00) == 0xb000)  /* add sp, imm or sub sp, imm  */
-       found_stack_adjust = 1;
-      else if ((insn & 0xfe00) == 0xbc00)  /* pop <registers> */
-       {
-         found_stack_adjust = 1;
-         if (insn & 0x0100)  /* <registers> include PC.  */
+      else if (thumb_instruction_restores_sp (insn))
+       {
+         if ((insn & 0xff00) == 0xbd00)  /* pop <registers, PC> */
            found_return = 1;
        }
       else if (thumb_insn_size (insn) == 4)  /* 32-bit Thumb-2 instruction */
@@ -3096,20 +3279,18 @@ thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 
          if (insn == 0xe8bd)  /* ldm.w sp!, <registers> */
            {
-             found_stack_adjust = 1;
              if (insn2 & 0x8000)  /* <registers> include PC.  */
                found_return = 1;
            }
          else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
                   && (insn2 & 0x0fff) == 0x0b04)
            {
-             found_stack_adjust = 1;
              if ((insn2 & 0xf000) == 0xf000) /* <Rt> is PC.  */
                found_return = 1;
            }
          else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
                   && (insn2 & 0x0e00) == 0x0a00)
-           found_stack_adjust = 1;
+           ;
          else
            break;
        }
@@ -3126,48 +3307,40 @@ thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
      a 32-bit instruction.  This is just a heuristic, so we do not worry
      too much about false positives.  */
 
-  if (!found_stack_adjust)
-    {
-      if (pc - 4 < func_start)
-       return 0;
-      if (target_read_memory (pc - 4, buf, 4))
-       return 0;
+  if (pc - 4 < func_start)
+    return 0;
+  if (target_read_memory (pc - 4, buf, 4))
+    return 0;
 
-      insn = extract_unsigned_integer (buf, 2, byte_order_for_code);
-      insn2 = extract_unsigned_integer (buf + 2, 2, byte_order_for_code);
-
-      if (insn2 == 0x46bd)  /* mov sp, r7 */
-       found_stack_adjust = 1;
-      else if ((insn2 & 0xff00) == 0xb000)  /* add sp, imm or sub sp, imm  */
-       found_stack_adjust = 1;
-      else if ((insn2 & 0xff00) == 0xbc00)  /* pop <registers> without PC */
-       found_stack_adjust = 1;
-      else if (insn == 0xe8bd)  /* ldm.w sp!, <registers> */
-       found_stack_adjust = 1;
-      else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
-              && (insn2 & 0x0fff) == 0x0b04)
-       found_stack_adjust = 1;
-      else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
-              && (insn2 & 0x0e00) == 0x0a00)
-       found_stack_adjust = 1;
-    }
+  insn = extract_unsigned_integer (buf, 2, byte_order_for_code);
+  insn2 = extract_unsigned_integer (buf + 2, 2, byte_order_for_code);
+
+  if (thumb_instruction_restores_sp (insn2))
+    found_stack_adjust = 1;
+  else if (insn == 0xe8bd)  /* ldm.w sp!, <registers> */
+    found_stack_adjust = 1;
+  else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
+          && (insn2 & 0x0fff) == 0x0b04)
+    found_stack_adjust = 1;
+  else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
+          && (insn2 & 0x0e00) == 0x0a00)
+    found_stack_adjust = 1;
 
   return found_stack_adjust;
 }
 
-/* Return true if we are in the function's epilogue, i.e. after the
-   instruction that destroyed the function's stack frame.  */
+/* Implement the stack_frame_destroyed_p gdbarch method.  */
 
 static int
-arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc)
 {
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   unsigned int insn;
-  int found_return, found_stack_adjust;
+  int found_return;
   CORE_ADDR func_start, func_end;
 
   if (arm_pc_is_thumb (gdbarch, pc))
-    return thumb_in_function_epilogue_p (gdbarch, pc);
+    return thumb_stack_frame_destroyed_p (gdbarch, pc);
 
   if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
     return 0;
@@ -3203,25 +3376,8 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
   if (pc < func_start + 4)
     return 0;
 
-  found_stack_adjust = 0;
   insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
-  if (bits (insn, 28, 31) != INST_NV)
-    {
-      if ((insn & 0x0df0f000) == 0x0080d000)
-       /* ADD SP (register or immediate).  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0df0f000) == 0x0040d000)
-       /* SUB SP (register or immediate).  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0ffffff0) == 0x01a0d000)
-       /* MOV SP.  */
-       found_stack_adjust = 1;
-      else if ((insn & 0x0fff0000) == 0x08bd0000)
-       /* POP (LDMIA).  */
-       found_stack_adjust = 1;
-    }
-
-  if (found_stack_adjust)
+  if (arm_instruction_restores_sp (insn))
     return 1;
 
   return 0;
@@ -3235,15 +3391,15 @@ struct stack_item
 {
   int len;
   struct stack_item *prev;
-  void *data;
+  gdb_byte *data;
 };
 
 static struct stack_item *
 push_stack_item (struct stack_item *prev, const void *contents, int len)
 {
   struct stack_item *si;
-  si = xmalloc (sizeof (struct stack_item));
-  si->data = xmalloc (len);
+  si = XNEW (struct stack_item);
+  si->data = (gdb_byte *) xmalloc (len);
   si->len = len;
   si->prev = prev;
   memcpy (si->data, contents, len);
@@ -3284,7 +3440,6 @@ arm_type_align (struct type *t)
     case TYPE_CODE_FLT:
     case TYPE_CODE_SET:
     case TYPE_CODE_RANGE:
-    case TYPE_CODE_BITSTRING:
     case TYPE_CODE_REF:
     case TYPE_CODE_CHAR:
     case TYPE_CODE_BOOL:
@@ -3373,8 +3528,8 @@ arm_vfp_cprc_reg_char (enum arm_vfp_cprc_base_type b)
    classified from *BASE_TYPE, or two types differently classified
    from each other, return -1, otherwise return the total number of
    base-type elements found (possibly 0 in an empty structure or
-   array).  Vectors and complex types are not currently supported,
-   matching the generic AAPCS support.  */
+   array).  Vector types are not currently supported, matching the
+   generic AAPCS support.  */
 
 static int
 arm_vfp_cprc_sub_candidate (struct type *t,
@@ -3405,6 +3560,38 @@ arm_vfp_cprc_sub_candidate (struct type *t,
        }
       break;
 
+    case TYPE_CODE_COMPLEX:
+      /* Arguments of complex T where T is one of the types float or
+        double get treated as if they are implemented as:
+
+        struct complexT
+        {
+          T real;
+          T imag;
+        };
+
+      */
+      switch (TYPE_LENGTH (t))
+       {
+       case 8:
+         if (*base_type == VFP_CPRC_UNKNOWN)
+           *base_type = VFP_CPRC_SINGLE;
+         else if (*base_type != VFP_CPRC_SINGLE)
+           return -1;
+         return 2;
+
+       case 16:
+         if (*base_type == VFP_CPRC_UNKNOWN)
+           *base_type = VFP_CPRC_DOUBLE;
+         else if (*base_type != VFP_CPRC_DOUBLE)
+           return -1;
+         return 2;
+
+       default:
+         return -1;
+       }
+      break;
+
     case TYPE_CODE_ARRAY:
       {
        int count;
@@ -3650,7 +3837,8 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                                         val + i * unit_length);
                  else
                    {
-                     sprintf (name_buf, "%c%d", reg_char, reg_scaled + i);
+                     xsnprintf (name_buf, sizeof (name_buf), "%c%d",
+                                reg_char, reg_scaled + i);
                      regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                            strlen (name_buf));
                      regcache_cooked_write (regcache, regnum,
@@ -3691,7 +3879,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
          CORE_ADDR regval = extract_unsigned_integer (val, len, byte_order);
          if (arm_pc_is_thumb (gdbarch, regval))
            {
-             bfd_byte *copy = alloca (len);
+             bfd_byte *copy = (bfd_byte *) alloca (len);
              store_unsigned_integer (copy, len, byte_order,
                                      MAKE_THUMB_ADDR (regval));
              val = copy;
@@ -3766,19 +3954,19 @@ arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
 }
 
 static void
-print_fpu_flags (int flags)
+print_fpu_flags (struct ui_file *file, int flags)
 {
   if (flags & (1 << 0))
-    fputs ("IVO ", stdout);
+    fputs_filtered ("IVO ", file);
   if (flags & (1 << 1))
-    fputs ("DVZ ", stdout);
+    fputs_filtered ("DVZ ", file);
   if (flags & (1 << 2))
-    fputs ("OFL ", stdout);
+    fputs_filtered ("OFL ", file);
   if (flags & (1 << 3))
-    fputs ("UFL ", stdout);
+    fputs_filtered ("UFL ", file);
   if (flags & (1 << 4))
-    fputs ("INX ", stdout);
-  putchar ('\n');
+    fputs_filtered ("INX ", file);
+  fputc_filtered ('\n', file);
 }
 
 /* Print interesting information about the floating point processor
@@ -3792,15 +3980,15 @@ arm_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
 
   type = (status >> 24) & 127;
   if (status & (1 << 31))
-    printf (_("Hardware FPU type %d\n"), type);
+    fprintf_filtered (file, _("Hardware FPU type %d\n"), type);
   else
-    printf (_("Software FPU type %d\n"), type);
+    fprintf_filtered (file, _("Software FPU type %d\n"), type);
   /* i18n: [floating point unit] mask */
-  fputs (_("mask: "), stdout);
-  print_fpu_flags (status >> 16);
+  fputs_filtered (_("mask: "), file);
+  print_fpu_flags (file, status >> 16);
   /* i18n: [floating point unit] flags */
-  fputs (_("flags: "), stdout);
-  print_fpu_flags (status);
+  fputs_filtered (_("flags: "), file);
+  print_fpu_flags (file, status);
 }
 
 /* Construct the ARM extended floating point type.  */
@@ -3981,7 +4169,7 @@ arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
     {
       char name_buf[4];
 
-      sprintf (name_buf, "s%d", reg - 64);
+      xsnprintf (name_buf, sizeof (name_buf), "s%d", reg - 64);
       return user_reg_map_name_to_regnum (gdbarch, name_buf,
                                          strlen (name_buf));
     }
@@ -3992,7 +4180,7 @@ arm_dwarf_reg_to_regnum (struct gdbarch *gdbarch, int reg)
     {
       char name_buf[4];
 
-      sprintf (name_buf, "d%d", reg - 256);
+      xsnprintf (name_buf, sizeof (name_buf), "d%d", reg - 256);
       return user_reg_map_name_to_regnum (gdbarch, name_buf,
                                          strlen (name_buf));
     }
@@ -4169,18 +4357,6 @@ bitcount (unsigned long val)
   return nbits;
 }
 
-/* Return the size in bytes of the complete Thumb instruction whose
-   first halfword is INST1.  */
-
-static int
-thumb_insn_size (unsigned short inst1)
-{
-  if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
-    return 4;
-  else
-    return 2;
-}
-
 static int
 thumb_advance_itstate (unsigned int itstate)
 {
@@ -4540,7 +4716,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
   else if ((inst1 & 0xff00) == 0x4700) /* bx REG, blx REG */
     {
       if (bits (inst1, 3, 6) == 0x0f)
-       nextpc = pc_val;
+       nextpc = UNMAKE_THUMB_ADDR (pc_val);
       else
        nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
     }
@@ -4735,6 +4911,13 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
        case 0x5:               /* data transfer */
        case 0x6:
        case 0x7:
+         if (bits (this_instr, 25, 27) == 0x3 && bit (this_instr, 4) == 1)
+           {
+             /* Media instructions and architecturally undefined
+                instructions.  */
+             break;
+           }
+
          if (bit (this_instr, 20))
            {
              /* load */
@@ -4847,17 +5030,9 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
   CORE_ADDR nextpc;
 
   if (arm_frame_is_thumb (frame))
-    {
-      nextpc = thumb_get_next_pc_raw (frame, pc);
-      if (nextpc == MAKE_THUMB_ADDR (pc))
-       error (_("Infinite loop detected"));
-    }
+    nextpc = thumb_get_next_pc_raw (frame, pc);
   else
-    {
-      nextpc = arm_get_next_pc_raw (frame, pc);
-      if (nextpc == pc)
-       error (_("Infinite loop detected"));
-    }
+    nextpc = arm_get_next_pc_raw (frame, pc);
 
   return nextpc;
 }
@@ -5131,10 +5306,10 @@ static gdb_byte *
 extend_buffer_earlier (gdb_byte *buf, CORE_ADDR endaddr,
                       int old_len, int new_len)
 {
-  gdb_byte *new_buf, *middle;
+  gdb_byte *new_buf;
   int bytes_to_read = new_len - old_len;
 
-  new_buf = xmalloc (new_len);
+  new_buf = (gdb_byte *) xmalloc (new_len);
   memcpy (new_buf + bytes_to_read, buf, old_len);
   xfree (buf);
   if (target_read_memory (endaddr - new_len, new_buf, bytes_to_read) != 0)
@@ -5164,7 +5339,7 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
   gdb_byte *buf;
   char map_type;
   CORE_ADDR boundary, func_start;
-  int buf_len, buf2_len;
+  int buf_len;
   enum bfd_endian order = gdbarch_byte_order_for_code (gdbarch);
   int i, any, last_it, last_it_count;
 
@@ -5200,7 +5375,7 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
     /* No room for an IT instruction.  */
     return bpaddr;
 
-  buf = xmalloc (buf_len);
+  buf = (gdb_byte *) xmalloc (buf_len);
   if (target_read_memory (bpaddr - buf_len, buf, buf_len) != 0)
     return bpaddr;
   any = 0;
@@ -6221,7 +6396,7 @@ install_alu_reg (struct gdbarch *gdbarch, struct regcache *regs,
 
      Preparation: tmp1, tmp2, tmp3 <- r0, r1, r2;
                  r0, r1, r2 <- rd, rn, rm
-     Insn: <op><cond> r0, r1, r2 [, <shift>]
+     Insn: <op><cond> r0, [r1,] r2 [, <shift>]
      Cleanup: rd <- r0; r0, r1, r2 <- tmp1, tmp2, tmp3
   */
 
@@ -6268,22 +6443,21 @@ thumb_copy_alu_reg (struct gdbarch *gdbarch, uint16_t insn,
                    struct regcache *regs,
                    struct displaced_step_closure *dsc)
 {
-  unsigned rn, rm, rd;
+  unsigned rm, rd;
 
-  rd = bits (insn, 3, 6);
-  rn = (bit (insn, 7) << 3) | bits (insn, 0, 2);
-  rm = 2;
+  rm = bits (insn, 3, 6);
+  rd = (bit (insn, 7) << 3) | bits (insn, 0, 2);
 
-  if (rd != ARM_PC_REGNUM && rn != ARM_PC_REGNUM)
+  if (rd != ARM_PC_REGNUM && rm != ARM_PC_REGNUM)
     return thumb_copy_unmodified_16bit (gdbarch, insn, "ALU reg", dsc);
 
   if (debug_displaced)
-    fprintf_unfiltered (gdb_stdlog, "displaced: copying reg %s insn %.4x\n",
-                       "ALU", (unsigned short) insn);
+    fprintf_unfiltered (gdb_stdlog, "displaced: copying ALU reg insn %.4x\n",
+                       (unsigned short) insn);
 
-  dsc->modinsn[0] = ((insn & 0xff00) | 0x08);
+  dsc->modinsn[0] = ((insn & 0xff00) | 0x10);
 
-  install_alu_reg (gdbarch, regs, dsc, rd, rn, rm);
+  install_alu_reg (gdbarch, regs, dsc, rd, rd, rm);
 
   return 0;
 }
@@ -6864,7 +7038,7 @@ cleanup_block_load_pc (struct gdbarch *gdbarch,
                       struct displaced_step_closure *dsc)
 {
   uint32_t status = displaced_read_reg (regs, dsc, ARM_PS_REGNUM);
-  int load_executed = condition_true (dsc->u.block.cond, status), i;
+  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 num_to_shuffle = regs_loaded, clobbered;
@@ -8493,7 +8667,7 @@ arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
   unsigned int i, len, offset;
   enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   int size = dsc->is_thumb? 2 : 4;
-  const unsigned char *bkp_insn;
+  const gdb_byte *bkp_insn;
 
   offset = 0;
   /* Poke modified instruction(s).  */
@@ -8547,8 +8721,8 @@ arm_displaced_step_copy_insn (struct gdbarch *gdbarch,
                              CORE_ADDR from, CORE_ADDR to,
                              struct regcache *regs)
 {
-  struct displaced_step_closure *dsc
-    = xmalloc (sizeof (struct displaced_step_closure));
+  struct displaced_step_closure *dsc = XNEW (struct displaced_step_closure);
+
   arm_process_displaced_insn (gdbarch, from, to, regs, dsc);
   arm_displaced_init_closure (gdbarch, from, to, dsc);
 
@@ -8579,7 +8753,7 @@ arm_displaced_step_fixup (struct gdbarch *gdbarch,
 static int
 gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
 {
-  struct gdbarch *gdbarch = info->application_data;
+  struct gdbarch *gdbarch = (struct gdbarch *) info->application_data;
 
   if (arm_pc_is_thumb (gdbarch, memaddr))
     {
@@ -8652,10 +8826,10 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info)
 #define THUMB_LE_BREAKPOINT {0xbe,0xbe}
 #define THUMB_BE_BREAKPOINT {0xbe,0xbe}
 
-static const char arm_default_arm_le_breakpoint[] = ARM_LE_BREAKPOINT;
-static const char arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
-static const char arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT;
-static const char arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
+static const gdb_byte arm_default_arm_le_breakpoint[] = ARM_LE_BREAKPOINT;
+static const gdb_byte arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
+static const gdb_byte arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT;
+static const gdb_byte arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
 
 /* Determine the type and size of breakpoint to insert at PCPTR.  Uses
    the program counter value to determine whether a 16-bit or 32-bit
@@ -8706,8 +8880,6 @@ static void
 arm_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
                               int *kindptr)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
   arm_breakpoint_from_pc (gdbarch, pcptr, kindptr);
 
   if (arm_pc_is_thumb (gdbarch, *pcptr) && *kindptr == 4)
@@ -8820,7 +8992,7 @@ arm_return_in_memory (struct gdbarch *gdbarch, struct type *type)
   int nRc;
   enum type_code code;
 
-  CHECK_TYPEDEF (type);
+  type = check_typedef (type);
 
   /* In the ARM ABI, "integer" like aggregate types are returned in
      registers.  For an aggregate type to be integer like, its size
@@ -8924,7 +9096,7 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 
   if (TYPE_CODE (type) == TYPE_CODE_FLT)
     {
-      char buf[MAX_REGISTER_SIZE];
+      gdb_byte buf[MAX_REGISTER_SIZE];
 
       switch (gdbarch_tdep (gdbarch)->fp_model)
        {
@@ -9010,11 +9182,12 @@ arm_store_return_value (struct type *type, struct regcache *regs,
 /* Handle function return values.  */
 
 static enum return_value_convention
-arm_return_value (struct gdbarch *gdbarch, struct type *func_type,
+arm_return_value (struct gdbarch *gdbarch, struct value *function,
                  struct type *valtype, struct regcache *regcache,
                  gdb_byte *readbuf, const gdb_byte *writebuf)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  struct type *func_type = function ? value_type (function) : NULL;
   enum arm_vfp_cprc_base_type vfp_base_type;
   int vfp_base_count;
 
@@ -9041,7 +9214,7 @@ arm_return_value (struct gdbarch *gdbarch, struct type *func_type,
              char name_buf[4];
              int regnum;
 
-             sprintf (name_buf, "%c%d", reg_char, i);
+             xsnprintf (name_buf, sizeof (name_buf), "%c%d", reg_char, i);
              regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                    strlen (name_buf));
              if (writebuf)
@@ -9087,7 +9260,7 @@ 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;
-  char buf[INT_REGISTER_SIZE];
+  gdb_byte buf[INT_REGISTER_SIZE];
   
   jb_addr = get_frame_register_unsigned (frame, ARM_A1_REGNUM);
 
@@ -9111,15 +9284,23 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
 
   /* Find the starting address and name of the function containing the PC.  */
   if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
-    return 0;
+    {
+      /* Trampoline 'bx reg' doesn't belong to any functions.  Do the
+        check here.  */
+      start_addr = arm_skip_bx_reg (frame, pc);
+      if (start_addr != 0)
+       return start_addr;
+
+      return 0;
+    }
 
   /* If PC is in a Thumb call or return stub, return the address of the
      target PC, which is in a register.  The thunk functions are called
      _call_via_xx, where x is the register name.  The possible names
      are r0-r9, sl, fp, ip, sp, and lr.  ARM RealView has similar
      functions, named __ARM_call_via_r[0-7].  */
-  if (strncmp (name, "_call_via_", 10) == 0
-      || strncmp (name, "__ARM_call_via_", strlen ("__ARM_call_via_")) == 0)
+  if (startswith (name, "_call_via_")
+      || startswith (name, "__ARM_call_via_"))
     {
       /* Use the name suffix to determine which register contains the
          target PC.  */
@@ -9141,15 +9322,13 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
   namelen = strlen (name);
   if (name[0] == '_' && name[1] == '_'
       && ((namelen > 2 + strlen ("_from_thumb")
-          && strncmp (name + namelen - strlen ("_from_thumb"), "_from_thumb",
-                      strlen ("_from_thumb")) == 0)
+          && startswith (name + namelen - strlen ("_from_thumb"), "_from_thumb"))
          || (namelen > 2 + strlen ("_from_arm")
-             && strncmp (name + namelen - strlen ("_from_arm"), "_from_arm",
-                         strlen ("_from_arm")) == 0)))
+             && startswith (name + namelen - strlen ("_from_arm"), "_from_arm"))))
     {
       char *target_name;
       int target_len = namelen - 2;
-      struct minimal_symbol *minsym;
+      struct bound_minimal_symbol minsym;
       struct objfile *objfile;
       struct obj_section *sec;
 
@@ -9158,15 +9337,15 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
       else
        target_len -= strlen ("_from_arm");
 
-      target_name = alloca (target_len + 1);
+      target_name = (char *) alloca (target_len + 1);
       memcpy (target_name, name + 2, target_len);
       target_name[target_len] = '\0';
 
       sec = find_pc_section (pc);
       objfile = (sec == NULL) ? NULL : sec->objfile;
       minsym = lookup_minimal_symbol (target_name, NULL, objfile);
-      if (minsym != NULL)
-       return SYMBOL_VALUE_ADDRESS (minsym);
+      if (minsym.minsym != NULL)
+       return BMSYMBOL_VALUE_ADDRESS (minsym);
       else
        return 0;
     }
@@ -9194,7 +9373,7 @@ arm_update_current_architecture (void)
   struct gdbarch_info info;
 
   /* If the current architecture is not ARM, we have nothing to do.  */
-  if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_arm)
+  if (gdbarch_bfd_arch_info (target_gdbarch ())->arch != bfd_arch_arm)
     return;
 
   /* Update the architecture.  */
@@ -9208,12 +9387,12 @@ static void
 set_fp_model_sfunc (char *args, int from_tty,
                    struct cmd_list_element *c)
 {
-  enum arm_float_model fp_model;
+  int fp_model;
 
   for (fp_model = ARM_FLOAT_AUTO; fp_model != ARM_FLOAT_LAST; fp_model++)
     if (strcmp (current_fp_model, fp_model_strings[fp_model]) == 0)
       {
-       arm_fp_model = fp_model;
+       arm_fp_model = (enum arm_float_model) fp_model;
        break;
       }
 
@@ -9228,10 +9407,10 @@ static void
 show_fp_model (struct ui_file *file, int from_tty,
               struct cmd_list_element *c, const char *value)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
 
   if (arm_fp_model == ARM_FLOAT_AUTO
-      && gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_arm)
+      && gdbarch_bfd_arch_info (target_gdbarch ())->arch == bfd_arch_arm)
     fprintf_filtered (file, _("\
 The current ARM floating point model is \"auto\" (currently \"%s\").\n"),
                      fp_model_strings[tdep->fp_model]);
@@ -9245,12 +9424,12 @@ static void
 arm_set_abi (char *args, int from_tty,
             struct cmd_list_element *c)
 {
-  enum arm_abi_kind arm_abi;
+  int arm_abi;
 
   for (arm_abi = ARM_ABI_AUTO; arm_abi != ARM_ABI_LAST; arm_abi++)
     if (strcmp (arm_abi_string, arm_abi_strings[arm_abi]) == 0)
       {
-       arm_abi_global = arm_abi;
+       arm_abi_global = (enum arm_abi_kind) arm_abi;
        break;
       }
 
@@ -9265,10 +9444,10 @@ static void
 arm_show_abi (struct ui_file *file, int from_tty,
             struct cmd_list_element *c, const char *value)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
 
   if (arm_abi_global == ARM_ABI_AUTO
-      && gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_arm)
+      && gdbarch_bfd_arch_info (target_gdbarch ())->arch == bfd_arch_arm)
     fprintf_filtered (file, _("\
 The current ARM ABI is \"auto\" (currently \"%s\").\n"),
                      arm_abi_strings[tdep->arm_abi]);
@@ -9281,8 +9460,6 @@ static void
 arm_show_fallback_mode (struct ui_file *file, int from_tty,
                        struct cmd_list_element *c, const char *value)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
-
   fprintf_filtered (file,
                    _("The current execution mode assumed "
                      "(when symbols are unavailable) is \"%s\".\n"),
@@ -9293,7 +9470,7 @@ static void
 arm_show_force_mode (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (target_gdbarch ());
 
   fprintf_filtered (file,
                    _("The current execution mode assumed "
@@ -9404,7 +9581,7 @@ arm_coff_make_msymbol_special(int val, struct minimal_symbol *msym)
 static void
 arm_objfile_data_free (struct objfile *objfile, void *arg)
 {
-  struct arm_per_objfile *data = arg;
+  struct arm_per_objfile *data = (struct arm_per_objfile *) arg;
   unsigned int i;
 
   for (i = 0; i < objfile->obfd->section_count; i++)
@@ -9424,7 +9601,8 @@ arm_record_special_symbol (struct gdbarch *gdbarch, struct objfile *objfile,
   if (name[1] != 'a' && name[1] != 't' && name[1] != 'd')
     return;
 
-  data = objfile_data (objfile, arm_objfile_data_key);
+  data = (struct arm_per_objfile *) objfile_data (objfile,
+                                                 arm_objfile_data_key);
   if (data == NULL)
     {
       data = OBSTACK_ZALLOC (&objfile->objfile_obstack,
@@ -9497,7 +9675,7 @@ arm_neon_quad_read (struct gdbarch *gdbarch, struct regcache *regcache,
   int offset, double_regnum;
   enum register_status status;
 
-  sprintf (name_buf, "d%d", regnum << 1);
+  xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum << 1);
   double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                               strlen (name_buf));
 
@@ -9549,7 +9727,7 @@ arm_pseudo_read (struct gdbarch *gdbarch, struct regcache *regcache,
       else
        offset = (regnum & 1) ? 4 : 0;
 
-      sprintf (name_buf, "d%d", regnum >> 1);
+      xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum >> 1);
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                   strlen (name_buf));
 
@@ -9572,10 +9750,9 @@ arm_neon_quad_write (struct gdbarch *gdbarch, struct regcache *regcache,
                     int regnum, const gdb_byte *buf)
 {
   char name_buf[4];
-  gdb_byte reg_buf[8];
   int offset, double_regnum;
 
-  sprintf (name_buf, "d%d", regnum << 1);
+  xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum << 1);
   double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                               strlen (name_buf));
 
@@ -9616,7 +9793,7 @@ arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       else
        offset = (regnum & 1) ? 4 : 0;
 
-      sprintf (name_buf, "d%d", regnum >> 1);
+      xsnprintf (name_buf, sizeof (name_buf), "d%d", regnum >> 1);
       double_regnum = user_reg_map_name_to_regnum (gdbarch, name_buf,
                                                   strlen (name_buf));
 
@@ -9629,7 +9806,7 @@ arm_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
 static struct value *
 value_of_arm_user_reg (struct frame_info *frame, const void *baton)
 {
-  const int *reg_p = baton;
+  const int *reg_p = (const int *) baton;
   return value_of_register (*reg_p, frame);
 }
 \f
@@ -9698,6 +9875,14 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch)
                                      (16 * INT_REGISTER_SIZE)
                                      + INT_REGISTER_SIZE,
                                      tdesc_arm_with_m);
+
+      /* M-profile plus M4F VFP.  */
+      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);
     }
 
   /* Otherwise we don't have a useful guess.  */
@@ -9721,7 +9906,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   enum arm_float_model fp_model = arm_fp_model;
   struct tdesc_arch_data *tdesc_data = NULL;
   int i, is_m = 0;
-  int have_vfp_registers = 0, have_vfp_pseudos = 0, have_neon_pseudos = 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;
   const struct target_desc *tdesc = info.target_desc;
@@ -9757,7 +9943,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                 anyway, so assume APCS.  */
              arm_abi = ARM_ABI_APCS;
            }
-         else if (ei_osabi == ELFOSABI_NONE)
+         else if (ei_osabi == ELFOSABI_NONE || ei_osabi == ELFOSABI_GNU)
            {
              int eabi_ver = EF_ARM_EABI_VERSION (e_flags);
              int attr_arch, attr_profile;
@@ -9783,27 +9969,34 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                                                        OBJ_ATTR_PROC,
                                                        Tag_ABI_VFP_args))
                        {
-                       case 0:
+                       case AEABI_VFP_args_base:
                          /* "The user intended FP parameter/result
                             passing to conform to AAPCS, base
                             variant".  */
                          fp_model = ARM_FLOAT_SOFT_VFP;
                          break;
-                       case 1:
+                       case AEABI_VFP_args_vfp:
                          /* "The user intended FP parameter/result
                             passing to conform to AAPCS, VFP
                             variant".  */
                          fp_model = ARM_FLOAT_VFP;
                          break;
-                       case 2:
+                       case AEABI_VFP_args_toolchain:
                          /* "The user intended FP parameter/result
                             passing to conform to tool chain-specific
                             conventions" - we don't know any such
                             conventions, so leave it as "auto".  */
                          break;
+                       case AEABI_VFP_args_compatible:
+                         /* "Code is compatible with both the base
+                            and VFP variants; the user did not permit
+                            non-variadic functions to pass FP
+                            parameters/results" - leave it as
+                            "auto".  */
+                         break;
                        default:
                          /* Attribute value not mentioned in the
-                            October 2008 ABI, so leave it as
+                            November 2012 ABI, so leave it as
                             "auto".  */
                          break;
                        }
@@ -9978,6 +10171,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
              tdesc_data_cleanup (tdesc_data);
              return NULL;
            }
+
+         have_wmmx_registers = 1;
        }
 
       /* If we have a VFP unit, check whether the single precision registers
@@ -10020,7 +10215,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_registers = 1;
+         vfp_register_count = i;
 
          /* If we have VFP, also check for NEON.  The architecture allows
             NEON without VFP (integer vector operations only), but GDB
@@ -10080,7 +10275,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
       return best_arch->gdbarch;
     }
 
-  tdep = xcalloc (1, sizeof (struct gdbarch_tdep));
+  tdep = XCNEW (struct gdbarch_tdep);
   gdbarch = gdbarch_alloc (&info, tdep);
 
   /* Record additional information about the architecture we are defining.
@@ -10089,7 +10284,11 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->fp_model = fp_model;
   tdep->is_m = is_m;
   tdep->have_fpa_registers = have_fpa_registers;
-  tdep->have_vfp_registers = have_vfp_registers;
+  tdep->have_wmmx_registers = have_wmmx_registers;
+  gdb_assert (vfp_register_count == 0
+             || vfp_register_count == 16
+             || vfp_register_count == 32);
+  tdep->vfp_register_count = vfp_register_count;
   tdep->have_vfp_pseudos = have_vfp_pseudos;
   tdep->have_neon_pseudos = have_neon_pseudos;
   tdep->have_neon = have_neon;
@@ -10149,14 +10348,13 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   frame_base_set_default (gdbarch, &arm_normal_base);
 
   /* Address manipulation.  */
-  set_gdbarch_smash_text_address (gdbarch, arm_smash_text_address);
   set_gdbarch_addr_bits_remove (gdbarch, arm_addr_bits_remove);
 
   /* Advance PC across function entry code.  */
   set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
 
-  /* Detect whether PC is in function epilogue.  */
-  set_gdbarch_in_function_epilogue_p (gdbarch, arm_in_function_epilogue_p);
+  /* Detect whether PC is at a point where the stack has been destroyed.  */
+  set_gdbarch_stack_frame_destroyed_p (gdbarch, arm_stack_frame_destroyed_p);
 
   /* Skip trampolines.  */
   set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
@@ -10212,6 +10410,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   dwarf2_frame_set_init_reg (gdbarch, arm_dwarf2_frame_init_reg);
 
   /* Add some default predicates.  */
+  if (is_m)
+    frame_unwind_append_unwinder (gdbarch, &arm_m_exception_unwind);
   frame_unwind_append_unwinder (gdbarch, &arm_stub_unwind);
   dwarf2_append_unwinders (gdbarch);
   frame_unwind_append_unwinder (gdbarch, &arm_exidx_unwind);
@@ -10333,6 +10533,7 @@ _initialize_arm_tdep (void)
   /* 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 ();
@@ -10355,8 +10556,8 @@ _initialize_arm_tdep (void)
 
   /* Initialize the array that will be passed to
      add_setshow_enum_cmd().  */
-  valid_disassembly_styles
-    = xmalloc ((num_disassembly_options + 1) * sizeof (char *));
+  valid_disassembly_styles = XNEWVEC (const char *,
+                                     num_disassembly_options + 1);
   for (i = 0; i < num_disassembly_options; i++)
     {
       numregs = get_arm_regnames (i, &setname, &setdesc, &regnames);
@@ -10454,6 +10655,8 @@ vfp - VFP co-processor."),
 #define THUMB2_INSN_SIZE_BYTES 4
 
 
+/* Position of the bit within a 32-bit ARM instruction
+   that defines whether the instruction is a load or store.  */
 #define INSN_S_L_BIT_NUM 20
 
 #define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
@@ -10489,7 +10692,7 @@ vfp - VFP co-processor."),
 struct arm_mem_r
 {
   uint32_t len;    /* Record length.  */
-  CORE_ADDR addr;  /* Memory address.  */
+  uint32_t addr;   /* Memory address.  */
 };
 
 /* ARM instruction record contains opcode of current insn
@@ -10537,6 +10740,12 @@ sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
   return 1;
 }
 
+enum arm_record_result
+{
+  ARM_RECORD_SUCCESS = 0,
+  ARM_RECORD_FAILURE = 1
+};
+
 typedef enum
 {
   ARM_RECORD_STRH=1,
@@ -11245,110 +11454,90 @@ arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
   return 0;
 }
 
-/* Handling opcode 010 insns.  */
+/* Handle ARM mode instructions with opcode 010.  */
 
 static int
 arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
 {
   struct regcache *reg_cache = arm_insn_r->regcache;
 
-  uint32_t reg_src1 = 0 , reg_dest = 0;
-  uint32_t offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t reg_base , reg_dest;
+  uint32_t offset_12, tgt_mem_addr;
   uint32_t record_buf[8], record_buf_mem[8];
+  unsigned char wback;
+  ULONGEST u_regval;
 
-  ULONGEST u_regval = 0;
+  /* Calculate wback.  */
+  wback = (bit (arm_insn_r->arm_insn, 24) == 0)
+         || (bit (arm_insn_r->arm_insn, 21) == 1);
 
-  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
-  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  arm_insn_r->reg_rec_count = 0;
+  reg_base = bits (arm_insn_r->arm_insn, 16, 19);
 
   if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
     {
+      /* LDR (immediate), LDR (literal), LDRB (immediate), LDRB (literal), LDRBT
+        and LDRT.  */
+
       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
-         in that case, it emulates branch and link insn, and hence we
-         need to save CSPR and PC as well.  */
-      if (ARM_PC_REGNUM != 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;
-        }
+      record_buf[arm_insn_r->reg_rec_count++] = reg_dest;
+
+      /* The LDR instruction is capable of doing branching.  If MOV LR, PC
+        preceeds a LDR instruction having R15 as reg_base, it
+        emulates a branch and link instruction, and hence we need to save
+        CPSR and PC as well.  */
+      if (ARM_PC_REGNUM == reg_dest)
+       record_buf[arm_insn_r->reg_rec_count++] = ARM_PS_REGNUM;
+
+      /* If wback is true, also save the base register, which is going to be
+        written to.  */
+      if (wback)
+       record_buf[arm_insn_r->reg_rec_count++] = reg_base;
     }
   else
     {
-      /* Store, immediate offset, immediate pre-indexed,
-         immediate post-indexed.  */
-      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      /* STR (immediate), STRB (immediate), STRBT and STRT.  */
+
       offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
-      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
-      /* U == 1 */
+      regcache_raw_read_unsigned (reg_cache, reg_base, &u_regval);
+
+      /* Handle bit U.  */
       if (bit (arm_insn_r->arm_insn, 23))
-        {
-          tgt_mem_addr = u_regval + offset_12;
-        }
+       {
+         /* U == 1: Add the offset. */
+         tgt_mem_addr = (uint32_t) u_regval + offset_12;
+       }
       else
-        {
-          tgt_mem_addr = u_regval - offset_12;
-        }
+       {
+         /* U == 0: subtract the offset. */
+         tgt_mem_addr = (uint32_t) u_regval - offset_12;
+       }
+
+      /* Bit 22 tells us whether the store instruction writes 1 byte or 4
+        bytes.  */
+      if (bit (arm_insn_r->arm_insn, 22))
+       {
+         /* STRB and STRBT: 1 byte.  */
+         record_buf_mem[0] = 1;
+       }
+      else
+       {
+         /* STR and STRT: 4 bytes.  */
+         record_buf_mem[0] = 4;
+       }
+
+      /* Handle bit P.  */
+      if (bit (arm_insn_r->arm_insn, 24))
+       record_buf_mem[1] = tgt_mem_addr;
+      else
+       record_buf_mem[1] = (uint32_t) u_regval;
 
-      switch (arm_insn_r->opcode)
-        {
-          /* STR.  */
-          case 8:
-          case 12:
-          /* STR.  */
-          case 9:
-          case 13:
-          /* STRT.  */    
-          case 1:
-          case 5:
-          /* STR.  */    
-          case 4:
-          case 0:
-            record_buf_mem[0] = 4;
-          break;
-
-          /* STRB.  */
-          case 10:
-          case 14:
-          /* STRB.  */    
-          case 11:
-          case 15:
-          /* STRBT.  */    
-          case 3:
-          case 7:
-          /* STRB.  */    
-          case 2:
-          case 6:
-            record_buf_mem[0] = 1;
-          break;
-
-          default:
-            gdb_assert_not_reached ("no decoding pattern found");
-          break;
-        }
-      record_buf_mem[1] = tgt_mem_addr;
       arm_insn_r->mem_rec_count = 1;
 
-      if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
-          || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
-          || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
-          || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
-          || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
-          || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
-         )
-        {
-          /* We are handling pre-indexed mode; post-indexed mode;
-             where Rn is going to be changed.  */
-          record_buf[0] = reg_src1;
-          arm_insn_r->reg_rec_count = 1;
-        }
+      /* If wback is true, also save the base register, which is going to be
+        written to.  */
+      if (wback)
+       record_buf[arm_insn_r->reg_rec_count++] = reg_base;
     }
 
   REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
@@ -11619,145 +11808,99 @@ arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
   return 0;
 }
 
-/* Handling opcode 100 insns.  */
+/* Handle ARM mode instructions with opcode 100.  */
 
 static int
 arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
 {
   struct regcache *reg_cache = arm_insn_r->regcache;
-
-  uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
-  uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
-  uint32_t start_address = 0, index = 0;
+  uint32_t register_count = 0, register_bits;
+  uint32_t reg_base, addr_mode;
   uint32_t record_buf[24], record_buf_mem[48];
+  uint32_t wback;
+  ULONGEST u_regval;
 
-  ULONGEST u_regval[2] = {0};
+  /* Fetch the list of registers.  */
+  register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+  arm_insn_r->reg_rec_count = 0;
+
+  /* Fetch the base register that contains the address we are loading data
+     to.  */
+  reg_base = bits (arm_insn_r->arm_insn, 16, 19);
 
-  /* This mode is exclusively for load and store multiple.  */
-  /* Handle incremenrt after/before and decrment after.before mode;
-     Rn is changing depending on W bit, but as of now we store Rn too
-     without optimization.  */
+  /* Calculate wback.  */
+  wback = (bit (arm_insn_r->arm_insn, 21) == 1);
 
   if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
     {
-      /* LDM  (1,2,3) where LDM  (3) changes CPSR too.  */
+      /* LDM/LDMIA/LDMFD, LDMDA/LDMFA, LDMDB and LDMIB.  */
 
-      if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
-        {
-          register_bits = bits (arm_insn_r->arm_insn, 0, 15);
-          no_of_regs = 15;
-        }
-      else
-        {
-          register_bits = bits (arm_insn_r->arm_insn, 0, 14);
-          no_of_regs = 14;
-        }
-      /* Get Rn.  */
-      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      /* Find out which registers are going to be loaded from memory.  */
       while (register_bits)
-      {
-        if (register_bits & 0x00000001)
-          register_list[register_count++] = 1;
-        register_bits = register_bits >> 1;
-      }
-
-        /* Extra space for Base Register and CPSR; wihtout optimization.  */
-        record_buf[register_count] = reg_src1;
-        record_buf[register_count + 1] = ARM_PS_REGNUM;
-        arm_insn_r->reg_rec_count = register_count + 2;
+       {
+         if (register_bits & 0x00000001)
+           record_buf[arm_insn_r->reg_rec_count++] = register_count;
+         register_bits = register_bits >> 1;
+         register_count++;
+       }
 
-        for (register_count = 0; register_count < no_of_regs; register_count++)
-          {
-            if  (register_list[register_count])
-              {
-                /* Register_count gives total no of registers
-                and dually working as reg number.  */
-                record_buf[index] = register_count;
-                index++;
-              }
-          }
+  
+      /* If wback is true, also save the base register, which is going to be
+        written to.  */
+      if (wback)
+       record_buf[arm_insn_r->reg_rec_count++] = reg_base;
 
+      /* Save the CPSR register.  */
+      record_buf[arm_insn_r->reg_rec_count++] = ARM_PS_REGNUM;
     }
   else
     {
-      /* It handles both STM(1) and STM(2).  */
-      addr_mode = bits (arm_insn_r->arm_insn, 23, 24);    
+      /* STM (STMIA, STMEA), STMDA (STMED), STMDB (STMFD) and STMIB (STMFA).  */
 
-      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
-      /* Get Rn.  */
-      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
-      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+      addr_mode = bits (arm_insn_r->arm_insn, 23, 24); 
+
+      regcache_raw_read_unsigned (reg_cache, reg_base, &u_regval);
+
+      /* Find out how many registers are going to be stored to memory.  */
       while (register_bits)
-        {
-          if (register_bits & 0x00000001)
-            register_count++;
-          register_bits = register_bits >> 1;
-        }
+       {
+         if (register_bits & 0x00000001)
+           register_count++;
+         register_bits = register_bits >> 1;
+       }
 
       switch (addr_mode)
-        {
-          /* Decrement after.  */
-          case 0:                          
-            start_address = (u_regval[0]) - (register_count * 4) + 4;
-            arm_insn_r->mem_rec_count = register_count;
-            while (register_count)
-              {
-                record_buf_mem[(register_count * 2) - 1] = start_address;
-                record_buf_mem[(register_count * 2) - 2] = 4;
-                start_address = start_address + 4;
-                register_count--;
-              }
-          break;    
-
-          /* Increment after.  */
-          case 1:
-            start_address = u_regval[0];
-            arm_insn_r->mem_rec_count = register_count;
-            while (register_count)
-              {
-                record_buf_mem[(register_count * 2) - 1] = start_address;
-                record_buf_mem[(register_count * 2) - 2] = 4;
-                start_address = start_address + 4;
-                register_count--;
-              }
-          break;    
-
-          /* Decrement before.  */
-          case 2:
-
-            start_address = (u_regval[0]) - (register_count * 4);
-            arm_insn_r->mem_rec_count = register_count;
-            while (register_count)
-              {
-                record_buf_mem[(register_count * 2) - 1] = start_address;
-                record_buf_mem[(register_count * 2) - 2] = 4;
-                start_address = start_address + 4;
-                register_count--;
-              }
-          break;    
-
-          /* Increment before.  */
-          case 3:
-            start_address = u_regval[0] + 4;
-            arm_insn_r->mem_rec_count = register_count;
-            while (register_count)
-              {
-                record_buf_mem[(register_count * 2) - 1] = start_address;
-                record_buf_mem[(register_count * 2) - 2] = 4;
-                start_address = start_address + 4;
-                register_count--;
-              }
-          break;    
-
-          default:
-            gdb_assert_not_reached ("no decoding pattern found");
-          break;    
-        }
+       {
+         /* STMDA (STMED): Decrement after.  */
+         case 0:
+         record_buf_mem[1] = (uint32_t) u_regval
+                             - register_count * INT_REGISTER_SIZE + 4;
+         break;
+         /* STM (STMIA, STMEA): Increment after.  */
+         case 1:
+         record_buf_mem[1] = (uint32_t) u_regval;
+         break;
+         /* STMDB (STMFD): Decrement before.  */
+         case 2:
+         record_buf_mem[1] = (uint32_t) u_regval
+                             - register_count * INT_REGISTER_SIZE;
+         break;
+         /* STMIB (STMFA): Increment before.  */
+         case 3:
+         record_buf_mem[1] = (uint32_t) u_regval + INT_REGISTER_SIZE;
+         break;
+         default:
+           gdb_assert_not_reached ("no decoding pattern found");
+         break;
+       }
 
-      /* Base register also changes; based on condition and W bit.  */
-      /* We save it anyway without optimization.  */
-      record_buf[0] = reg_src1;
-      arm_insn_r->reg_rec_count = 1;
+      record_buf_mem[0] = register_count * INT_REGISTER_SIZE;
+      arm_insn_r->mem_rec_count = 1;
+
+      /* If wback is true, also save the base register, which is going to be
+        written to.  */
+      if (wback)
+       record_buf[arm_insn_r->reg_rec_count++] = reg_base;
     }
 
   REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
@@ -11790,7 +11933,7 @@ arm_record_b_bl (insn_decode_record *arm_insn_r)
 /* Handling opcode 110 insns.  */
 
 static int
-arm_record_coproc (insn_decode_record *arm_insn_r)
+arm_record_unsupported_insn (insn_decode_record *arm_insn_r)
 {
   printf_unfiltered (_("Process record does not support instruction "
                     "0x%0x at address %s.\n"),arm_insn_r->arm_insn,
@@ -11799,107 +11942,688 @@ arm_record_coproc (insn_decode_record *arm_insn_r)
   return -1;
 }
 
-/* Handling opcode 111 insns.  */
+/* Record handler for vector data transfer instructions.  */
 
 static int
-arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r)
 {
-  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
-  struct regcache *reg_cache = arm_insn_r->regcache;
-  uint32_t ret = 0; /* function return value: -1:record failure ;  0:success  */
+  uint32_t bits_a, bit_c, bit_l, reg_t, reg_v;
+  uint32_t record_buf[4];
 
-  /* Handle SWI insn; system call would be handled over here.  */
+  const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch);
+  reg_t = bits (arm_insn_r->arm_insn, 12, 15);
+  reg_v = bits (arm_insn_r->arm_insn, 21, 23);
+  bits_a = bits (arm_insn_r->arm_insn, 21, 23);
+  bit_l = bit (arm_insn_r->arm_insn, 20);
+  bit_c = bit (arm_insn_r->arm_insn, 8);
 
-  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
-  if (15 == arm_insn_r->opcode)
-  {
-    /* Handle arm syscall insn.  */
-    if (tdep->arm_swi_record != NULL)
-      {
-        ret = tdep->arm_swi_record(reg_cache);
-      }
-    else
-      {
-        printf_unfiltered (_("no syscall record support\n"));
-        ret = -1;
-      }
-  }
+  /* Handle VMOV instruction.  */
+  if (bit_l && bit_c)
+    {
+      record_buf[0] = reg_t;
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (bit_l && !bit_c)
+    {
+      /* Handle VMOV instruction.  */
+      if (bits_a == 0x00)
+        {
+          if (bit (arm_insn_r->arm_insn, 20))
+            record_buf[0] = reg_t;
+          else
+            record_buf[0] = num_regs + (bit (arm_insn_r->arm_insn, 7) |
+                            (reg_v << 1));
 
-  printf_unfiltered (_("Process record does not support instruction "
-                        "0x%0x at address %s.\n"),arm_insn_r->arm_insn,
-                        paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
-  return ret;
+          arm_insn_r->reg_rec_count = 1;
+        }
+      /* Handle VMRS instruction.  */
+      else if (bits_a == 0x07)
+        {
+          if (reg_t == 15)
+            reg_t = ARM_PS_REGNUM;
+
+          record_buf[0] = reg_t;
+          arm_insn_r->reg_rec_count = 1;
+        }
+    }
+  else if (!bit_l && !bit_c)
+    {
+      /* Handle VMOV instruction.  */
+      if (bits_a == 0x00)
+        {
+          if (bit (arm_insn_r->arm_insn, 20))
+            record_buf[0] = reg_t;
+          else
+            record_buf[0] = num_regs + (bit (arm_insn_r->arm_insn, 7) |
+                            (reg_v << 1));
+
+          arm_insn_r->reg_rec_count = 1;
+        }
+      /* Handle VMSR instruction.  */
+      else if (bits_a == 0x07)
+        {
+          record_buf[0] = ARM_FPSCR_REGNUM;
+          arm_insn_r->reg_rec_count = 1;
+        }
+    }
+  else if (!bit_l && bit_c)
+    {
+      /* Handle VMOV instruction.  */
+      if (!(bits_a & 0x04))
+        {
+          record_buf[0] = (reg_v | (bit (arm_insn_r->arm_insn, 7) << 4))
+                          + ARM_D0_REGNUM;
+          arm_insn_r->reg_rec_count = 1;
+        }
+      /* Handle VDUP instruction.  */
+      else
+        {
+          if (bit (arm_insn_r->arm_insn, 21))
+            {
+              reg_v = reg_v | (bit (arm_insn_r->arm_insn, 7) << 4);
+              record_buf[0] = reg_v + ARM_D0_REGNUM;
+              record_buf[1] = reg_v + ARM_D0_REGNUM + 1;
+              arm_insn_r->reg_rec_count = 2;
+            }
+          else
+            {
+              reg_v = reg_v | (bit (arm_insn_r->arm_insn, 7) << 4);
+              record_buf[0] = reg_v + ARM_D0_REGNUM;
+              arm_insn_r->reg_rec_count = 1;
+            }
+        }
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  return 0;
 }
 
-/* Handling opcode 000 insns.  */
+/* Record handler for extension register load/store instructions.  */
 
 static int
-thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r)
 {
-  uint32_t record_buf[8];
-  uint32_t reg_src1 = 0;
-
-  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+  uint32_t opcode, single_reg;
+  uint8_t op_vldm_vstm;
+  uint32_t record_buf[8], record_buf_mem[128];
+  ULONGEST u_regval = 0;
 
-  record_buf[0] = ARM_PS_REGNUM;
-  record_buf[1] = reg_src1;
-  thumb_insn_r->reg_rec_count = 2;
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch);
 
-  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  opcode = bits (arm_insn_r->arm_insn, 20, 24);
+  single_reg = bit (arm_insn_r->arm_insn, 8);
+  op_vldm_vstm = opcode & 0x1b;
 
-  return 0;
-}
+  /* Handle VMOV instructions.  */
+  if ((opcode & 0x1e) == 0x04)
+    {
+      if (bit (arm_insn_r->arm_insn, 4))
+        {
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+          arm_insn_r->reg_rec_count = 2;
+        }
+      else
+        {
+          uint8_t reg_m = (bits (arm_insn_r->arm_insn, 0, 3) << 1)
+                          | bit (arm_insn_r->arm_insn, 5);
 
+          if (!single_reg)
+            {
+              record_buf[0] = num_regs + reg_m;
+              record_buf[1] = num_regs + reg_m + 1;
+              arm_insn_r->reg_rec_count = 2;
+            }
+          else
+            {
+              record_buf[0] = reg_m + ARM_D0_REGNUM;
+              arm_insn_r->reg_rec_count = 1;
+            }
+        }
+    }
+  /* Handle VSTM and VPUSH instructions.  */
+  else if (op_vldm_vstm == 0x08 || op_vldm_vstm == 0x0a
+          || op_vldm_vstm == 0x12)
+    {
+      uint32_t start_address, reg_rn, imm_off32, imm_off8, memory_count;
+      uint32_t memory_index = 0;
 
-/* Handling opcode 001 insns.  */
+      reg_rn = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval);
+      imm_off8 = bits (arm_insn_r->arm_insn, 0, 7);
+      imm_off32 = imm_off8 << 24;
+      memory_count = imm_off8;
 
-static int
-thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
-{
-  uint32_t record_buf[8];
-  uint32_t reg_src1 = 0;
+      if (bit (arm_insn_r->arm_insn, 23))
+        start_address = u_regval;
+      else
+        start_address = u_regval - imm_off32;
 
-  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      if (bit (arm_insn_r->arm_insn, 21))
+        {
+          record_buf[0] = reg_rn;
+          arm_insn_r->reg_rec_count = 1;
+        }
 
-  record_buf[0] = ARM_PS_REGNUM;
-  record_buf[1] = reg_src1;
-  thumb_insn_r->reg_rec_count = 2;
+      while (memory_count > 0)
+        {
+          if (!single_reg)
+            {
+              record_buf_mem[memory_index] = start_address;
+              record_buf_mem[memory_index + 1] = 4;
+              start_address = start_address + 4;
+              memory_index = memory_index + 2;
+            }
+          else
+            {
+              record_buf_mem[memory_index] = start_address;
+              record_buf_mem[memory_index + 1] = 4;
+              record_buf_mem[memory_index + 2] = start_address + 4;
+              record_buf_mem[memory_index + 3] = 4;
+              start_address = start_address + 8;
+              memory_index = memory_index + 4;
+            }
+          memory_count--;
+        }
+      arm_insn_r->mem_rec_count = (memory_index >> 1);
+    }
+  /* Handle VLDM instructions.  */
+  else if (op_vldm_vstm == 0x09 || op_vldm_vstm == 0x0b
+          || op_vldm_vstm == 0x13)
+    {
+      uint32_t reg_count, reg_vd;
+      uint32_t reg_index = 0;
 
-  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+      reg_vd = bits (arm_insn_r->arm_insn, 12, 15);
+      reg_count = bits (arm_insn_r->arm_insn, 0, 7);
 
-  return 0;
-}
+      if (single_reg)
+        reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4);
+      else
+        reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22);
 
-/* Handling opcode 010 insns.  */
+      if (bit (arm_insn_r->arm_insn, 21))
+        record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19);
 
-static int
-thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
-{
-  struct regcache *reg_cache =  thumb_insn_r->regcache;
-  uint32_t record_buf[8], record_buf_mem[8];
+      while (reg_count > 0)
+        {
+          if (single_reg)
+              record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1;
+          else
+              record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1;
 
-  uint32_t reg_src1 = 0, reg_src2 = 0;
-  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+          reg_count--;
+        }
+      arm_insn_r->reg_rec_count = reg_index;
+    }
+  /* VSTR Vector store register.  */
+  else if ((opcode & 0x13) == 0x10)
+    {
+      uint32_t start_address, reg_rn, imm_off32, imm_off8, memory_count;
+      uint32_t memory_index = 0;
 
-  ULONGEST u_regval[2] = {0};
+      reg_rn = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval);
+      imm_off8 = bits (arm_insn_r->arm_insn, 0, 7);
+      imm_off32 = imm_off8 << 24;
+      memory_count = imm_off8;
 
-  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+      if (bit (arm_insn_r->arm_insn, 23))
+        start_address = u_regval + imm_off32;
+      else
+        start_address = u_regval - imm_off32;
 
-  if (bit (thumb_insn_r->arm_insn, 12))
-    {
-      /* Handle load/store register offset.  */
-      opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
-      if (opcode2 >= 12 && opcode2 <= 15)
+      if (single_reg)
         {
-          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
-          reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
-          record_buf[0] = reg_src1;
-          thumb_insn_r->reg_rec_count = 1;
+          record_buf_mem[memory_index] = start_address;
+          record_buf_mem[memory_index + 1] = 4;
+          arm_insn_r->mem_rec_count = 1;
         }
-      else if (opcode2 >= 8 && opcode2 <= 10)
+      else
         {
-          /* STR(2), STRB(2), STRH(2) .  */
-          reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+          record_buf_mem[memory_index] = start_address;
+          record_buf_mem[memory_index + 1] = 4;
+          record_buf_mem[memory_index + 2] = start_address + 4;
+          record_buf_mem[memory_index + 3] = 4;
+          arm_insn_r->mem_rec_count = 2;
+        }
+    }
+  /* VLDR Vector load register.  */
+  else if ((opcode & 0x13) == 0x11)
+    {
+      uint32_t reg_vd = bits (arm_insn_r->arm_insn, 12, 15);
+
+      if (!single_reg)
+        {
+          reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4);
+          record_buf[0] = ARM_D0_REGNUM + reg_vd;
+        }
+      else
+        {
+          reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22);
+          record_buf[0] = num_regs + reg_vd;
+        }
+      arm_insn_r->reg_rec_count = 1;
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;
+}
+
+/* Record handler for arm/thumb mode VFP data processing instructions.  */
+
+static int
+arm_record_vfp_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+  uint32_t opc1, opc2, opc3, dp_op_sz, bit_d, reg_vd;
+  uint32_t record_buf[4];
+  enum insn_types {INSN_T0, INSN_T1, INSN_T2, INSN_T3, INSN_INV};
+  enum insn_types curr_insn_type = INSN_INV;
+
+  reg_vd = bits (arm_insn_r->arm_insn, 12, 15);
+  opc1 = bits (arm_insn_r->arm_insn, 20, 23);
+  opc2 = bits (arm_insn_r->arm_insn, 16, 19);
+  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;
+
+  /* Handle VMLA, VMLS.  */
+  if (opc1 == 0x00)
+    {
+      if (bit (arm_insn_r->arm_insn, 10))
+        {
+          if (bit (arm_insn_r->arm_insn, 6))
+            curr_insn_type = INSN_T0;
+          else
+            curr_insn_type = INSN_T1;
+        }
+      else
+        {
+          if (dp_op_sz)
+            curr_insn_type = INSN_T1;
+          else
+            curr_insn_type = INSN_T2;
+        }
+    }
+  /* Handle VNMLA, VNMLS, VNMUL.  */
+  else if (opc1 == 0x01)
+    {
+      if (dp_op_sz)
+        curr_insn_type = INSN_T1;
+      else
+        curr_insn_type = INSN_T2;
+    }
+  /* Handle VMUL.  */
+  else if (opc1 == 0x02 && !(opc3 & 0x01))
+    {
+      if (bit (arm_insn_r->arm_insn, 10))
+        {
+          if (bit (arm_insn_r->arm_insn, 6))
+            curr_insn_type = INSN_T0;
+          else
+            curr_insn_type = INSN_T1;
+        }
+      else
+        {
+          if (dp_op_sz)
+            curr_insn_type = INSN_T1;
+          else
+            curr_insn_type = INSN_T2;
+        }
+    }
+  /* Handle VADD, VSUB.  */
+  else if (opc1 == 0x03)
+    {
+      if (!bit (arm_insn_r->arm_insn, 9))
+        {
+          if (bit (arm_insn_r->arm_insn, 6))
+            curr_insn_type = INSN_T0;
+          else
+            curr_insn_type = INSN_T1;
+        }
+      else
+        {
+          if (dp_op_sz)
+            curr_insn_type = INSN_T1;
+          else
+            curr_insn_type = INSN_T2;
+        }
+    }
+  /* Handle VDIV.  */
+  else if (opc1 == 0x0b)
+    {
+      if (dp_op_sz)
+        curr_insn_type = INSN_T1;
+      else
+        curr_insn_type = INSN_T2;
+    }
+  /* Handle all other vfp data processing instructions.  */
+  else if (opc1 == 0x0b)
+    {
+      /* Handle VMOV.  */
+      if (!(opc3 & 0x01) || (opc2 == 0x00 && opc3 == 0x01))
+        {
+          if (bit (arm_insn_r->arm_insn, 4))
+            {
+              if (bit (arm_insn_r->arm_insn, 6))
+                curr_insn_type = INSN_T0;
+              else
+                curr_insn_type = INSN_T1;
+            }
+          else
+            {
+              if (dp_op_sz)
+                curr_insn_type = INSN_T1;
+              else
+                curr_insn_type = INSN_T2;
+            }
+        }
+      /* Handle VNEG and VABS.  */
+      else if ((opc2 == 0x01 && opc3 == 0x01)
+              || (opc2 == 0x00 && opc3 == 0x03))
+        {
+          if (!bit (arm_insn_r->arm_insn, 11))
+            {
+              if (bit (arm_insn_r->arm_insn, 6))
+                curr_insn_type = INSN_T0;
+              else
+                curr_insn_type = INSN_T1;
+            }
+          else
+            {
+              if (dp_op_sz)
+                curr_insn_type = INSN_T1;
+              else
+                curr_insn_type = INSN_T2;
+            }
+        }
+      /* Handle VSQRT.  */
+      else if (opc2 == 0x01 && opc3 == 0x03)
+        {
+          if (dp_op_sz)
+            curr_insn_type = INSN_T1;
+          else
+            curr_insn_type = INSN_T2;
+        }
+      /* Handle VCVT.  */
+      else if (opc2 == 0x07 && opc3 == 0x03)
+        {
+          if (!dp_op_sz)
+            curr_insn_type = INSN_T1;
+          else
+            curr_insn_type = INSN_T2;
+        }
+      else if (opc3 & 0x01)
+        {
+          /* Handle VCVT.  */
+          if ((opc2 == 0x08) || (opc2 & 0x0e) == 0x0c)
+            {
+              if (!bit (arm_insn_r->arm_insn, 18))
+                curr_insn_type = INSN_T2;
+              else
+                {
+                  if (dp_op_sz)
+                    curr_insn_type = INSN_T1;
+                  else
+                    curr_insn_type = INSN_T2;
+                }
+            }
+          /* Handle VCVT.  */
+          else if ((opc2 & 0x0e) == 0x0a || (opc2 & 0x0e) == 0x0e)
+            {
+              if (dp_op_sz)
+                curr_insn_type = INSN_T1;
+              else
+                curr_insn_type = INSN_T2;
+            }
+          /* Handle VCVTB, VCVTT.  */
+          else if ((opc2 & 0x0e) == 0x02)
+            curr_insn_type = INSN_T2;
+          /* Handle VCMP, VCMPE.  */
+          else if ((opc2 & 0x0e) == 0x04)
+            curr_insn_type = INSN_T3;
+        }
+    }
+
+  switch (curr_insn_type)
+    {
+      case INSN_T0:
+        reg_vd = reg_vd | (bit_d << 4);
+        record_buf[0] = reg_vd + ARM_D0_REGNUM;
+        record_buf[1] = reg_vd + ARM_D0_REGNUM + 1;
+        arm_insn_r->reg_rec_count = 2;
+        break;
+
+      case INSN_T1:
+        reg_vd = reg_vd | (bit_d << 4);
+        record_buf[0] = reg_vd + ARM_D0_REGNUM;
+        arm_insn_r->reg_rec_count = 1;
+        break;
+
+      case INSN_T2:
+        reg_vd = (reg_vd << 1) | bit_d;
+        record_buf[0] = reg_vd + ARM_D0_REGNUM;
+        arm_insn_r->reg_rec_count = 1;
+        break;
+
+      case INSN_T3:
+        record_buf[0] = ARM_FPSCR_REGNUM;
+        arm_insn_r->reg_rec_count = 1;
+        break;
+
+      default:
+        gdb_assert_not_reached ("no decoding pattern found");
+        break;
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  return 0;
+}
+
+/* Handling opcode 110 insns.  */
+
+static int
+arm_record_asimd_vfp_coproc (insn_decode_record *arm_insn_r)
+{
+  uint32_t op, op1, op1_sbit, op1_ebit, coproc;
+
+  coproc = bits (arm_insn_r->arm_insn, 8, 11);
+  op1 = bits (arm_insn_r->arm_insn, 20, 25);
+  op1_ebit = bit (arm_insn_r->arm_insn, 20);
+
+  if ((coproc & 0x0e) == 0x0a)
+    {
+      /* Handle extension register ld/st instructions.  */
+      if (!(op1 & 0x20))
+        return arm_record_exreg_ld_st_insn (arm_insn_r);
+
+      /* 64-bit transfers between arm core and extension registers.  */
+      if ((op1 & 0x3e) == 0x04)
+        return arm_record_exreg_ld_st_insn (arm_insn_r);
+    }
+  else
+    {
+      /* Handle coprocessor ld/st instructions.  */
+      if (!(op1 & 0x3a))
+        {
+          /* Store.  */
+          if (!op1_ebit)
+            return arm_record_unsupported_insn (arm_insn_r);
+          else
+            /* Load.  */
+            return arm_record_unsupported_insn (arm_insn_r);
+        }
+
+      /* Move to coprocessor from two arm core registers.  */
+      if (op1 == 0x4)
+        return arm_record_unsupported_insn (arm_insn_r);
+
+      /* Move to two arm core registers from coprocessor.  */
+      if (op1 == 0x5)
+        {
+          uint32_t reg_t[2];
+
+          reg_t[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          reg_t[1] = bits (arm_insn_r->arm_insn, 16, 19);
+          arm_insn_r->reg_rec_count = 2;
+
+          REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, reg_t);
+          return 0;
+       }
+    }
+  return arm_record_unsupported_insn (arm_insn_r);
+}
+
+/* Handling opcode 111 insns.  */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+  uint32_t op, op1_sbit, op1_ebit, coproc;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  ULONGEST u_regval = 0;
+
+  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);
+
+  /* Handle arm SWI/SVC system call instructions.  */
+  if (op1_sbit)
+    {
+      if (tdep->arm_syscall_record != NULL)
+        {
+          ULONGEST svc_operand, svc_number;
+
+          svc_operand = (0x00ffffff & arm_insn_r->arm_insn);
+
+          if (svc_operand)  /* OABI.  */
+            svc_number = svc_operand - 0x900000;
+          else /* EABI.  */
+            regcache_raw_read_unsigned (reg_cache, 7, &svc_number);
+
+          return tdep->arm_syscall_record (reg_cache, svc_number);
+        }
+      else
+        {
+          printf_unfiltered (_("no syscall record support\n"));
+          return -1;
+        }
+    }
+
+  if ((coproc & 0x0e) == 0x0a)
+    {
+      /* VFP data-processing instructions.  */
+      if (!op1_sbit && !op)
+        return arm_record_vfp_data_proc_insn (arm_insn_r);
+
+      /* Advanced SIMD, VFP instructions.  */
+      if (!op1_sbit && op)
+        return arm_record_vdata_transfer_insn (arm_insn_r);
+    }
+  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;
+
+          arm_insn_r->reg_rec_count = 1;
+          REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count,
+                     record_buf);
+          return 0;
+        }
+    }
+
+  return arm_record_unsupported_insn (arm_insn_r);
+}
+
+/* Handling opcode 000 insns.  */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = reg_src1;
+  thumb_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+  return 0;
+}
+
+
+/* Handling opcode 001 insns.  */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = reg_src1;
+  thumb_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+  return 0;
+}
+
+/* Handling opcode 010 insns.  */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  ULONGEST u_regval[2] = {0};
+
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* Handle load/store register offset.  */
+      opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+      if (opcode2 >= 12 && opcode2 <= 15)
+        {
+          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+          record_buf[0] = reg_src1;
+          thumb_insn_r->reg_rec_count = 1;
+        }
+      else if (opcode2 >= 8 && opcode2 <= 10)
+        {
+          /* STR(2), STRB(2), STRH(2) .  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
           reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
           regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
           regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
@@ -12080,28 +12804,21 @@ thumb_record_misc (insn_decode_record *thumb_insn_r)
       /* POP.  */
       register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
       while (register_bits)
-        {
-          if (register_bits & 0x00000001)
-            register_list[register_count++] = 1;
-          register_bits = register_bits >> 1;
-        }
-      record_buf[register_count] = ARM_PS_REGNUM;
-      record_buf[register_count + 1] = ARM_SP_REGNUM;
-      thumb_insn_r->reg_rec_count = register_count + 2;
-      for (register_count = 0; register_count < 8; register_count++)
-        {
-          if  (register_list[register_count])
-            {
-              record_buf[index] = register_count;
-              index++;
-            }
-        }
+      {
+        if (register_bits & 0x00000001)
+          record_buf[index++] = register_count;
+        register_bits = register_bits >> 1;
+        register_count++;
+      }
+      record_buf[index++] = ARM_PS_REGNUM;
+      record_buf[index++] = ARM_SP_REGNUM;
+      thumb_insn_r->reg_rec_count = index;
     }
   else if (10 == opcode2)
     {
       /* PUSH.  */
       register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
-      regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+      regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
       while (register_bits)
         {
           if (register_bits & 0x00000001)
@@ -12192,19 +12909,12 @@ thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
       while (register_bits)
         {
           if (register_bits & 0x00000001)
-            register_list[register_count++] = 1;
+            record_buf[index++] = register_count;
           register_bits = register_bits >> 1;
+          register_count++;
         }
-      record_buf[register_count] = reg_src1;
-      thumb_insn_r->reg_rec_count = register_count + 1;
-      for (register_count = 0; register_count < 8; register_count++)
-        {
-          if (register_list[register_count])
-            {
-              record_buf[index] = register_count;
-              index++;
-            }
-        }
+      record_buf[index++] = reg_src1;
+      thumb_insn_r->reg_rec_count = index;
     }
   else if (0 == opcode2)
     {
@@ -12232,9 +12942,10 @@ thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
   else if (0x1F == opcode1)
     {
         /* Handle arm syscall insn.  */
-        if (tdep->arm_swi_record != NULL)
+        if (tdep->arm_syscall_record != NULL)
           {
-            ret = tdep->arm_swi_record(reg_cache);
+            regcache_raw_read_unsigned (reg_cache, 7, &u_regval);
+            ret = tdep->arm_syscall_record (reg_cache, u_regval);
           }
         else
           {
@@ -12285,14 +12996,789 @@ thumb_record_branch (insn_decode_record *thumb_insn_r)
   return 0;     
 }
 
-
-/* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success 
-and positive val on fauilure.  */
+/* Handler for thumb2 load/store multiple instructions.  */
 
 static int
-extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r)
 {
-  gdb_byte buf[insn_size];
+  struct regcache *reg_cache = thumb2_insn_r->regcache;
+
+  uint32_t reg_rn, op;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t index = 0, start_address = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  ULONGEST u_regval = 0;
+
+  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
+  op = bits (thumb2_insn_r->arm_insn, 23, 24);
+
+  if (0 == op || 3 == op)
+    {
+      if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+        {
+          /* Handle RFE instruction.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          thumb2_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          /* Handle SRS instruction after reading banked SP.  */
+          return arm_record_unsupported_insn (thumb2_insn_r);
+        }
+    }
+  else if (1 == op || 2 == op)
+    {
+      if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+        {
+          /* Handle LDM/LDMIA/LDMFD and LDMDB/LDMEA instructions.  */
+          register_bits = bits (thumb2_insn_r->arm_insn, 0, 15);
+          while (register_bits)
+            {
+              if (register_bits & 0x00000001)
+                record_buf[index++] = register_count;
+
+              register_count++;
+              register_bits = register_bits >> 1;
+            }
+          record_buf[index++] = reg_rn;
+          record_buf[index++] = ARM_PS_REGNUM;
+          thumb2_insn_r->reg_rec_count = index;
+        }
+      else
+        {
+          /* Handle STM/STMIA/STMEA and STMDB/STMFD.  */
+          register_bits = bits (thumb2_insn_r->arm_insn, 0, 15);
+          regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval);
+          while (register_bits)
+            {
+              if (register_bits & 0x00000001)
+                register_count++;
+
+              register_bits = register_bits >> 1;
+            }
+
+          if (1 == op)
+            {
+              /* Start address calculation for LDMDB/LDMEA.  */
+              start_address = u_regval;
+            }
+          else if (2 == op)
+            {
+              /* Start address calculation for LDMDB/LDMEA.  */
+              start_address = u_regval - register_count * 4;
+            }
+
+          thumb2_insn_r->mem_rec_count = register_count;
+          while (register_count)
+            {
+              record_buf_mem[register_count * 2 - 1] = start_address;
+              record_buf_mem[register_count * 2 - 2] = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+          record_buf[0] = reg_rn;
+          record_buf[1] = ARM_PS_REGNUM;
+          thumb2_insn_r->reg_rec_count = 2;
+        }
+    }
+
+  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
+            record_buf_mem);
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 load/store (dual/exclusive) and table branch
+   instructions.  */
+
+static int
+thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r)
+{
+  struct regcache *reg_cache = thumb2_insn_r->regcache;
+
+  uint32_t reg_rd, reg_rn, offset_imm;
+  uint32_t reg_dest1, reg_dest2;
+  uint32_t address, offset_addr;
+  uint32_t record_buf[8], record_buf_mem[8];
+  uint32_t op1, op2, op3;
+  LONGEST s_word;
+
+  ULONGEST u_regval[2];
+
+  op1 = bits (thumb2_insn_r->arm_insn, 23, 24);
+  op2 = bits (thumb2_insn_r->arm_insn, 20, 21);
+  op3 = bits (thumb2_insn_r->arm_insn, 4, 7);
+
+  if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      if(!(1 == op1 && 1 == op2 && (0 == op3 || 1 == op3)))
+        {
+          reg_dest1 = bits (thumb2_insn_r->arm_insn, 12, 15);
+          record_buf[0] = reg_dest1;
+          record_buf[1] = ARM_PS_REGNUM;
+          thumb2_insn_r->reg_rec_count = 2;
+        }
+
+      if (3 == op2 || (op1 & 2) || (1 == op1 && 1 == op2 && 7 == op3))
+        {
+          reg_dest2 = bits (thumb2_insn_r->arm_insn, 8, 11);
+          record_buf[2] = reg_dest2;
+          thumb2_insn_r->reg_rec_count = 3;
+        }
+    }
+  else
+    {
+      reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]);
+
+      if (0 == op1 && 0 == op2)
+        {
+          /* Handle STREX.  */
+          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
+          address = u_regval[0] + (offset_imm * 4);
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = address;
+          thumb2_insn_r->mem_rec_count = 1;
+          reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3);
+          record_buf[0] = reg_rd;
+          thumb2_insn_r->reg_rec_count = 1;
+        }
+      else if (1 == op1 && 0 == op2)
+        {
+          reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3);
+          record_buf[0] = reg_rd;
+          thumb2_insn_r->reg_rec_count = 1;
+          address = u_regval[0];
+          record_buf_mem[1] = address;
+
+          if (4 == op3)
+            {
+              /* Handle STREXB.  */
+              record_buf_mem[0] = 1;
+              thumb2_insn_r->mem_rec_count = 1;
+            }
+          else if (5 == op3)
+            {
+              /* Handle STREXH.  */
+              record_buf_mem[0] = 2 ;
+              thumb2_insn_r->mem_rec_count = 1;
+            }
+          else if (7 == op3)
+            {
+              /* Handle STREXD.  */
+              address = u_regval[0];
+              record_buf_mem[0] = 4;
+              record_buf_mem[2] = 4;
+              record_buf_mem[3] = address + 4;
+              thumb2_insn_r->mem_rec_count = 2;
+            }
+        }
+      else
+        {
+          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
+
+          if (bit (thumb2_insn_r->arm_insn, 24))
+            {
+              if (bit (thumb2_insn_r->arm_insn, 23))
+                offset_addr = u_regval[0] + (offset_imm * 4);
+              else
+                offset_addr = u_regval[0] - (offset_imm * 4);
+
+              address = offset_addr;
+            }
+          else
+            address = u_regval[0];
+
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = address;
+          record_buf_mem[2] = 4;
+          record_buf_mem[3] = address + 4;
+          thumb2_insn_r->mem_rec_count = 2;
+          record_buf[0] = reg_rn;
+          thumb2_insn_r->reg_rec_count = 1;
+        }
+    }
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
+            record_buf_mem);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 data processing (shift register and modified immediate)
+   instructions.  */
+
+static int
+thumb2_record_data_proc_sreg_mimm (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t reg_rd, op;
+  uint32_t record_buf[8];
+
+  op = bits (thumb2_insn_r->arm_insn, 21, 24);
+  reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11);
+
+  if ((0 == op || 4 == op || 8 == op || 13 == op) && 15 == reg_rd)
+    {
+      record_buf[0] = ARM_PS_REGNUM;
+      thumb2_insn_r->reg_rec_count = 1;
+    }
+  else
+    {
+      record_buf[0] = reg_rd;
+      record_buf[1] = ARM_PS_REGNUM;
+      thumb2_insn_r->reg_rec_count = 2;
+    }
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Generic handler for thumb2 instructions which effect destination and PS
+   registers.  */
+
+static int
+thumb2_record_ps_dest_generic (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t reg_rd;
+  uint32_t record_buf[8];
+
+  reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11);
+
+  record_buf[0] = reg_rd;
+  record_buf[1] = ARM_PS_REGNUM;
+  thumb2_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 branch and miscellaneous control instructions.  */
+
+static int
+thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t op, op1, op2;
+  uint32_t record_buf[8];
+
+  op = bits (thumb2_insn_r->arm_insn, 20, 26);
+  op1 = bits (thumb2_insn_r->arm_insn, 12, 14);
+  op2 = bits (thumb2_insn_r->arm_insn, 8, 11);
+
+  /* Handle MSR insn.  */
+  if (!(op1 & 0x2) && 0x38 == op)
+    {
+      if (!(op2 & 0x3))
+        {
+          /* CPSR is going to be changed.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          thumb2_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          arm_record_unsupported_insn(thumb2_insn_r);
+          return -1;
+        }
+    }
+  else if (4 == (op1 & 0x5) || 5 == (op1 & 0x5))
+    {
+      /* BLX.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      thumb2_insn_r->reg_rec_count = 2;
+    }
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 store single data item instructions.  */
+
+static int
+thumb2_record_str_single_data (insn_decode_record *thumb2_insn_r)
+{
+  struct regcache *reg_cache = thumb2_insn_r->regcache;
+
+  uint32_t reg_rn, reg_rm, offset_imm, shift_imm;
+  uint32_t address, offset_addr;
+  uint32_t record_buf[8], record_buf_mem[8];
+  uint32_t op1, op2;
+
+  ULONGEST u_regval[2];
+
+  op1 = bits (thumb2_insn_r->arm_insn, 21, 23);
+  op2 = bits (thumb2_insn_r->arm_insn, 6, 11);
+  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
+  regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]);
+
+  if (bit (thumb2_insn_r->arm_insn, 23))
+    {
+      /* T2 encoding.  */
+      offset_imm = bits (thumb2_insn_r->arm_insn, 0, 11);
+      offset_addr = u_regval[0] + offset_imm;
+      address = offset_addr;
+    }
+  else
+    {
+      /* T3 encoding.  */
+      if ((0 == op1 || 1 == op1 || 2 == op1) && !(op2 & 0x20))
+        {
+          /* Handle STRB (register).  */
+          reg_rm = bits (thumb2_insn_r->arm_insn, 0, 3);
+          regcache_raw_read_unsigned (reg_cache, reg_rm, &u_regval[1]);
+          shift_imm = bits (thumb2_insn_r->arm_insn, 4, 5);
+          offset_addr = u_regval[1] << shift_imm;
+          address = u_regval[0] + offset_addr;
+        }
+      else
+        {
+          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
+          if (bit (thumb2_insn_r->arm_insn, 10))
+            {
+              if (bit (thumb2_insn_r->arm_insn, 9))
+                offset_addr = u_regval[0] + offset_imm;
+              else
+                offset_addr = u_regval[0] - offset_imm;
+
+              address = offset_addr;
+            }
+          else
+            address = u_regval[0];
+        }
+    }
+
+  switch (op1)
+    {
+      /* Store byte instructions.  */
+      case 4:
+      case 0:
+        record_buf_mem[0] = 1;
+        break;
+      /* Store half word instructions.  */
+      case 1:
+      case 5:
+        record_buf_mem[0] = 2;
+        break;
+      /* Store word instructions.  */
+      case 2:
+      case 6:
+        record_buf_mem[0] = 4;
+        break;
+
+      default:
+        gdb_assert_not_reached ("no decoding pattern found");
+        break;
+    }
+
+  record_buf_mem[1] = address;
+  thumb2_insn_r->mem_rec_count = 1;
+  record_buf[0] = reg_rn;
+  thumb2_insn_r->reg_rec_count = 1;
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
+            record_buf_mem);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 load memory hints instructions.  */
+
+static int
+thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_rt, reg_rn;
+
+  reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15);
+  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
+
+  if (ARM_PC_REGNUM != reg_rt)
+    {
+      record_buf[0] = reg_rt;
+      record_buf[1] = reg_rn;
+      record_buf[2] = ARM_PS_REGNUM;
+      thumb2_insn_r->reg_rec_count = 3;
+
+      REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+                record_buf);
+      return ARM_RECORD_SUCCESS;
+    }
+
+  return ARM_RECORD_FAILURE;
+}
+
+/* Handler for thumb2 load word instructions.  */
+
+static int
+thumb2_record_ld_word (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t opcode1 = 0, opcode2 = 0;
+  uint32_t record_buf[8];
+
+  record_buf[0] = bits (thumb2_insn_r->arm_insn, 12, 15);
+  record_buf[1] = ARM_PS_REGNUM;
+  thumb2_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Handler for thumb2 long multiply, long multiply accumulate, and
+   divide instructions.  */
+
+static int
+thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t opcode1 = 0, opcode2 = 0;
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+  opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22);
+  opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7);
+
+  if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6))
+    {
+      /* Handle SMULL, UMULL, SMULAL.  */
+      /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S).  */
+      record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19);
+      record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15);
+      record_buf[2] = ARM_PS_REGNUM;
+      thumb2_insn_r->reg_rec_count = 3;
+    }
+  else if (1 == opcode1 || 3 == opcode2)
+    {
+      /* Handle SDIV and UDIV.  */
+      record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19);
+      record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15);
+      record_buf[2] = ARM_PS_REGNUM;
+      thumb2_insn_r->reg_rec_count = 3;
+    }
+  else
+    return ARM_RECORD_FAILURE;
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  return ARM_RECORD_SUCCESS;
+}
+
+/* Record handler for thumb32 coprocessor instructions.  */
+
+static int
+thumb2_record_coproc_insn (insn_decode_record *thumb2_insn_r)
+{
+  if (bit (thumb2_insn_r->arm_insn, 25))
+    return arm_record_coproc_data_proc (thumb2_insn_r);
+  else
+    return arm_record_asimd_vfp_coproc (thumb2_insn_r);
+}
+
+/* Record handler for advance SIMD structure load/store instructions.  */
+
+static int
+thumb2_record_asimd_struct_ld_st (insn_decode_record *thumb2_insn_r)
+{
+  struct regcache *reg_cache = thumb2_insn_r->regcache;
+  uint32_t l_bit, a_bit, b_bits;
+  uint32_t record_buf[128], record_buf_mem[128];
+  uint32_t reg_rn, reg_vd, address, f_esize, f_elem;
+  uint32_t index_r = 0, index_e = 0, bf_regs = 0, index_m = 0, loop_t = 0;
+  uint8_t f_ebytes;
+
+  l_bit = bit (thumb2_insn_r->arm_insn, 21);
+  a_bit = bit (thumb2_insn_r->arm_insn, 23);
+  b_bits = bits (thumb2_insn_r->arm_insn, 8, 11);
+  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
+  reg_vd = bits (thumb2_insn_r->arm_insn, 12, 15);
+  reg_vd = (bit (thumb2_insn_r->arm_insn, 22) << 4) | reg_vd;
+  f_ebytes = (1 << bits (thumb2_insn_r->arm_insn, 6, 7));
+  f_esize = 8 * f_ebytes;
+  f_elem = 8 / f_ebytes;
+
+  if (!l_bit)
+    {
+      ULONGEST u_regval = 0;
+      regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval);
+      address = u_regval;
+
+      if (!a_bit)
+        {
+          /* Handle VST1.  */
+          if (b_bits == 0x02 || b_bits == 0x0a || (b_bits & 0x0e) == 0x06)
+            {
+              if (b_bits == 0x07)
+                bf_regs = 1;
+              else if (b_bits == 0x0a)
+                bf_regs = 2;
+              else if (b_bits == 0x06)
+                bf_regs = 3;
+              else if (b_bits == 0x02)
+                bf_regs = 4;
+              else
+                bf_regs = 0;
+
+              for (index_r = 0; index_r < bf_regs; index_r++)
+                {
+                  for (index_e = 0; index_e < f_elem; index_e++)
+                    {
+                      record_buf_mem[index_m++] = f_ebytes;
+                      record_buf_mem[index_m++] = address;
+                      address = address + f_ebytes;
+                      thumb2_insn_r->mem_rec_count += 1;
+                    }
+                }
+            }
+          /* Handle VST2.  */
+          else if (b_bits == 0x03 || (b_bits & 0x0e) == 0x08)
+            {
+              if (b_bits == 0x09 || b_bits == 0x08)
+                bf_regs = 1;
+              else if (b_bits == 0x03)
+                bf_regs = 2;
+              else
+                bf_regs = 0;
+
+              for (index_r = 0; index_r < bf_regs; index_r++)
+                for (index_e = 0; index_e < f_elem; index_e++)
+                  {
+                    for (loop_t = 0; loop_t < 2; loop_t++)
+                      {
+                        record_buf_mem[index_m++] = f_ebytes;
+                        record_buf_mem[index_m++] = address + (loop_t * f_ebytes);
+                        thumb2_insn_r->mem_rec_count += 1;
+                      }
+                    address = address + (2 * f_ebytes);
+                  }
+            }
+          /* Handle VST3.  */
+          else if ((b_bits & 0x0e) == 0x04)
+            {
+              for (index_e = 0; index_e < f_elem; index_e++)
+                {
+                  for (loop_t = 0; loop_t < 3; loop_t++)
+                    {
+                      record_buf_mem[index_m++] = f_ebytes;
+                      record_buf_mem[index_m++] = address + (loop_t * f_ebytes);
+                      thumb2_insn_r->mem_rec_count += 1;
+                    }
+                  address = address + (3 * f_ebytes);
+                }
+            }
+          /* Handle VST4.  */
+          else if (!(b_bits & 0x0e))
+            {
+              for (index_e = 0; index_e < f_elem; index_e++)
+                {
+                  for (loop_t = 0; loop_t < 4; loop_t++)
+                    {
+                      record_buf_mem[index_m++] = f_ebytes;
+                      record_buf_mem[index_m++] = address + (loop_t * f_ebytes);
+                      thumb2_insn_r->mem_rec_count += 1;
+                    }
+                  address = address + (4 * f_ebytes);
+                }
+            }
+        }
+      else
+        {
+          uint8_t bft_size = bits (thumb2_insn_r->arm_insn, 10, 11);
+
+          if (bft_size == 0x00)
+            f_ebytes = 1;
+          else if (bft_size == 0x01)
+            f_ebytes = 2;
+          else if (bft_size == 0x02)
+            f_ebytes = 4;
+          else
+            f_ebytes = 0;
+
+          /* Handle VST1.  */
+          if (!(b_bits & 0x0b) || b_bits == 0x08)
+            thumb2_insn_r->mem_rec_count = 1;
+          /* Handle VST2.  */
+          else if ((b_bits & 0x0b) == 0x01 || b_bits == 0x09)
+            thumb2_insn_r->mem_rec_count = 2;
+          /* Handle VST3.  */
+          else if ((b_bits & 0x0b) == 0x02 || b_bits == 0x0a)
+            thumb2_insn_r->mem_rec_count = 3;
+          /* Handle VST4.  */
+          else if ((b_bits & 0x0b) == 0x03 || b_bits == 0x0b)
+            thumb2_insn_r->mem_rec_count = 4;
+
+          for (index_m = 0; index_m < thumb2_insn_r->mem_rec_count; index_m++)
+            {
+              record_buf_mem[index_m] = f_ebytes;
+              record_buf_mem[index_m] = address + (index_m * f_ebytes);
+            }
+        }
+    }
+  else
+    {
+      if (!a_bit)
+        {
+          /* Handle VLD1.  */
+          if (b_bits == 0x02 || b_bits == 0x0a || (b_bits & 0x0e) == 0x06)
+            thumb2_insn_r->reg_rec_count = 1;
+          /* Handle VLD2.  */
+          else if (b_bits == 0x03 || (b_bits & 0x0e) == 0x08)
+            thumb2_insn_r->reg_rec_count = 2;
+          /* Handle VLD3.  */
+          else if ((b_bits & 0x0e) == 0x04)
+            thumb2_insn_r->reg_rec_count = 3;
+          /* Handle VLD4.  */
+          else if (!(b_bits & 0x0e))
+            thumb2_insn_r->reg_rec_count = 4;
+        }
+      else
+        {
+          /* Handle VLD1.  */
+          if (!(b_bits & 0x0b) || b_bits == 0x08 || b_bits == 0x0c)
+            thumb2_insn_r->reg_rec_count = 1;
+          /* Handle VLD2.  */
+          else if ((b_bits & 0x0b) == 0x01 || b_bits == 0x09 || b_bits == 0x0d)
+            thumb2_insn_r->reg_rec_count = 2;
+          /* Handle VLD3.  */
+          else if ((b_bits & 0x0b) == 0x02 || b_bits == 0x0a || b_bits == 0x0e)
+            thumb2_insn_r->reg_rec_count = 3;
+          /* Handle VLD4.  */
+          else if ((b_bits & 0x0b) == 0x03 || b_bits == 0x0b || b_bits == 0x0f)
+            thumb2_insn_r->reg_rec_count = 4;
+
+          for (index_r = 0; index_r < thumb2_insn_r->reg_rec_count; index_r++)
+            record_buf[index_r] = reg_vd + ARM_D0_REGNUM + index_r;
+        }
+    }
+
+  if (bits (thumb2_insn_r->arm_insn, 0, 3) != 15)
+    {
+      record_buf[index_r] = reg_rn;
+      thumb2_insn_r->reg_rec_count += 1;
+    }
+
+  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
+            record_buf);
+  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
+            record_buf_mem);
+  return 0;
+}
+
+/* Decodes thumb2 instruction type and invokes its record handler.  */
+
+static unsigned int
+thumb2_record_decode_insn_handler (insn_decode_record *thumb2_insn_r)
+{
+  uint32_t op, op1, op2;
+
+  op = bit (thumb2_insn_r->arm_insn, 15);
+  op1 = bits (thumb2_insn_r->arm_insn, 27, 28);
+  op2 = bits (thumb2_insn_r->arm_insn, 20, 26);
+
+  if (op1 == 0x01)
+    {
+      if (!(op2 & 0x64 ))
+        {
+          /* Load/store multiple instruction.  */
+          return thumb2_record_ld_st_multiple (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x64) ^ 0x04))
+        {
+          /* Load/store (dual/exclusive) and table branch instruction.  */
+          return thumb2_record_ld_st_dual_ex_tbb (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x20) ^ 0x20))
+        {
+          /* Data-processing (shifted register).  */
+          return thumb2_record_data_proc_sreg_mimm (thumb2_insn_r);
+        }
+      else if (op2 & 0x40)
+        {
+          /* Co-processor instructions.  */
+          return thumb2_record_coproc_insn (thumb2_insn_r);
+        }
+    }
+  else if (op1 == 0x02)
+    {
+      if (op)
+        {
+          /* Branches and miscellaneous control instructions.  */
+          return thumb2_record_branch_misc_cntrl (thumb2_insn_r);
+        }
+      else if (op2 & 0x20)
+        {
+          /* Data-processing (plain binary immediate) instruction.  */
+          return thumb2_record_ps_dest_generic (thumb2_insn_r);
+        }
+      else
+        {
+          /* Data-processing (modified immediate).  */
+          return thumb2_record_data_proc_sreg_mimm (thumb2_insn_r);
+        }
+    }
+  else if (op1 == 0x03)
+    {
+      if (!(op2 & 0x71 ))
+        {
+          /* Store single data item.  */
+          return thumb2_record_str_single_data (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x71) ^ 0x10))
+        {
+          /* Advanced SIMD or structure load/store instructions.  */
+          return thumb2_record_asimd_struct_ld_st (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x67) ^ 0x01))
+        {
+          /* Load byte, memory hints instruction.  */
+          return thumb2_record_ld_mem_hints (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x67) ^ 0x03))
+        {
+          /* Load halfword, memory hints instruction.  */
+          return thumb2_record_ld_mem_hints (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x67) ^ 0x05))
+        {
+          /* Load word instruction.  */
+          return thumb2_record_ld_word (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x70) ^ 0x20))
+        {
+          /* Data-processing (register) instruction.  */
+          return thumb2_record_ps_dest_generic (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x78) ^ 0x30))
+        {
+          /* Multiply, multiply accumulate, abs diff instruction.  */
+          return thumb2_record_ps_dest_generic (thumb2_insn_r);
+        }
+      else if (!((op2 & 0x78) ^ 0x38))
+        {
+          /* Long multiply, long multiply accumulate, and divide.  */
+          return thumb2_record_lmul_lmla_div (thumb2_insn_r);
+        }
+      else if (op2 & 0x40)
+        {
+          /* Co-processor instructions.  */
+          return thumb2_record_coproc_insn (thumb2_insn_r);
+        }
+   }
+
+  return -1;
+}
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success 
+and positive val on fauilure.  */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+  gdb_byte buf[insn_size];
 
   memset (&buf[0], 0, insn_size);
   
@@ -12300,7 +13786,7 @@ extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
     return 1;
   insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
                            insn_size, 
-                           gdbarch_byte_order (insn_record->gdbarch));
+                          gdbarch_byte_order_for_code (insn_record->gdbarch));
   return 0;
 }
 
@@ -12315,7 +13801,7 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
 {
 
   /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
-  static const sti_arm_hdl_fp_t const arm_handle_insn[8] =                    
+  static const sti_arm_hdl_fp_t arm_handle_insn[8] =
   {
     arm_record_data_proc_misc_ld_str,   /* 000.  */
     arm_record_data_proc_imm,           /* 001.  */
@@ -12323,12 +13809,12 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
     arm_record_ld_st_reg_offset,        /* 011.  */
     arm_record_ld_st_multiple,          /* 100.  */
     arm_record_b_bl,                    /* 101.  */
-    arm_record_coproc,                  /* 110.  */
+    arm_record_asimd_vfp_coproc,        /* 110.  */
     arm_record_coproc_data_proc         /* 111.  */
   };
 
   /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
-  static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+  static const sti_arm_hdl_fp_t thumb_handle_insn[8] =
   { \
     thumb_record_shift_add_sub,        /* 000.  */
     thumb_record_add_sub_cmp_mov,      /* 001.  */
@@ -12374,11 +13860,20 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
     }
   else if (THUMB2_RECORD == record_type)
     {
-      printf_unfiltered (_("Process record doesnt support thumb32 instruction "
-                           "0x%0x at address %s.\n"),arm_record->arm_insn,
-                           paddress (arm_record->gdbarch, 
-                           arm_record->this_addr));
-      ret = -1;
+      /* As thumb does not have condition codes, we set negative.  */
+      arm_record->cond = -1;
+
+      /* Swap first half of 32bit thumb instruction with second half.  */
+      arm_record->arm_insn
+        = (arm_record->arm_insn >> 16) | (arm_record->arm_insn << 16);
+
+      insn_id = thumb2_record_decode_insn_handler (arm_record);
+
+      if (insn_id != ARM_RECORD_SUCCESS)
+        {
+          arm_record_unsupported_insn (arm_record);
+          ret = -1;
+        }
     }
   else
     {
@@ -12473,13 +13968,13 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
   if (0 == ret)
     {
       /* Record registers.  */
-      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      record_full_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
       if (arm_record.arm_regs)
         {
           for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
             {
-              if (record_arch_list_add_reg (arm_record.regcache , 
-                                            arm_record.arm_regs[no_of_rec]))
+              if (record_full_arch_list_add_reg
+                 (arm_record.regcache , arm_record.arm_regs[no_of_rec]))
               ret = -1;
             }
         }
@@ -12488,14 +13983,14 @@ arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
         {
           for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count; no_of_rec++)
             {
-              if (record_arch_list_add_mem 
+              if (record_full_arch_list_add_mem
                   ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
-                  arm_record.arm_mems[no_of_rec].len))
+                  arm_record.arm_mems[no_of_rec].len))
                 ret = -1;
             }
         }
 
-      if (record_arch_list_add_end ())
+      if (record_full_arch_list_add_end ())
         ret = -1;
     }
 
This page took 0.074484 seconds and 4 git commands to generate.