* objfiles.h (pc_in_section): New prototype.
[deliverable/binutils-gdb.git] / gdb / arm-tdep.c
index add6be871d729f72af920267cd94691784b56e72..7c78a617f3e8ccede3452dd78769e142676cc336 100644 (file)
@@ -1,8 +1,6 @@
 /* Common target dependent code for GDB on ARM systems.
 
-   Copyright (C) 1988, 1989, 1991, 1992, 1993, 1995, 1996, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1988-2013 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 "gdbcmd.h"
@@ -41,6 +40,7 @@
 #include "dwarf2-frame.h"
 #include "gdbtypes.h"
 #include "prologue-value.h"
+#include "remote.h"
 #include "target-descriptions.h"
 #include "user-regs.h"
 #include "observer.h"
 #include "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"
@@ -98,7 +103,7 @@ static struct cmd_list_element *showarmcmdlist = NULL;
 
 /* The type of floating-point to use.  Keep this in sync with enum
    arm_float_model, and the help string in _initialize_arm_tdep.  */
-static const char *fp_model_strings[] =
+static const char *const fp_model_strings[] =
 {
   "auto",
   "softfpa",
@@ -113,7 +118,7 @@ static enum arm_float_model arm_fp_model = ARM_FLOAT_AUTO;
 static const char *current_fp_model = "auto";
 
 /* The ABI to use.  Keep this in sync with arm_abi_kind.  */
-static const char *arm_abi_strings[] =
+static const char *const arm_abi_strings[] =
 {
   "auto",
   "APCS",
@@ -126,7 +131,7 @@ static enum arm_abi_kind arm_abi_global = ARM_ABI_AUTO;
 static const char *arm_abi_string = "auto";
 
 /* The execution mode to assume.  */
-static const char *arm_mode_strings[] =
+static const char *const arm_mode_strings[] =
   {
     "auto",
     "arm",
@@ -231,6 +236,8 @@ 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
@@ -374,8 +381,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);
@@ -417,8 +423,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)
@@ -442,20 +448,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
@@ -464,14 +468,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
+      && SYMBOL_VALUE_ADDRESS (msym.minsym) == pc
+      && SYMBOL_LINKAGE_NAME (msym.minsym) != NULL)
     {
-      const char *name = SYMBOL_LINKAGE_NAME (msym);
+      const char *name = SYMBOL_LINKAGE_NAME (msym.minsym);
 
       /* The GNU linker's Thumb call stub to foo is named
         __foo_from_thumb.  */
@@ -517,7 +521,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
@@ -836,7 +840,7 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
          constant = read_memory_unsigned_integer (loc, 4, byte_order);
          regs[bits (insn, 8, 10)] = pv_constant (constant);
        }
-      else if ((insn & 0xe000) == 0xe000)
+      else if (thumb_insn_size (insn) == 4) /* 32-bit Thumb-2 instructions.  */
        {
          unsigned short inst2;
 
@@ -1150,18 +1154,12 @@ thumb_analyze_prologue (struct gdbarch *gdbarch,
       cache->framereg = THUMB_FP_REGNUM;
       cache->framesize = -regs[THUMB_FP_REGNUM].k;
     }
-  else if (pv_is_register (regs[ARM_SP_REGNUM], ARM_SP_REGNUM))
+  else
     {
       /* Try the stack pointer... this is a bit desperate.  */
       cache->framereg = ARM_SP_REGNUM;
       cache->framesize = -regs[ARM_SP_REGNUM].k;
     }
-  else
-    {
-      /* We're just out of luck.  We don't know where the frame is.  */
-      cache->framereg = -1;
-      cache->framesize = 0;
-    }
 
   for (i = 0; i < 16; i++)
     if (pv_area_find_reg (stack, gdbarch, i, &offset))
@@ -1285,8 +1283,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;
@@ -1301,8 +1299,9 @@ arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
   /* 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",
+  if (stack_chk_guard.minsym
+      && strncmp (SYMBOL_LINKAGE_NAME (stack_chk_guard.minsym),
+                 "__stack_chk_guard",
                  strlen ("__stack_chk_guard")) != 0)
    return pc;
 
@@ -1377,7 +1376,6 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   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
@@ -1402,7 +1400,8 @@ arm_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
       if (post_prologue_pc
          && (s == NULL
              || s->producer == NULL
-             || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0))
+             || strncmp (s->producer, "GNU ", sizeof ("GNU ") - 1) == 0 
+             || strncmp (s->producer, "clang ", sizeof ("clang ") - 1) == 0))
        return post_prologue_pc;
 
       if (post_prologue_pc != 0)
@@ -1536,7 +1535,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))
@@ -1881,18 +1879,12 @@ arm_analyze_prologue (struct gdbarch *gdbarch,
       framereg = ARM_FP_REGNUM;
       framesize = -regs[ARM_FP_REGNUM].k;
     }
-  else if (pv_is_register (regs[ARM_SP_REGNUM], ARM_SP_REGNUM))
+  else
     {
       /* Try the stack pointer... this is a bit desperate.  */
       framereg = ARM_SP_REGNUM;
       framesize = -regs[ARM_SP_REGNUM].k;
     }
-  else
-    {
-      /* We're just out of luck.  We don't know where the frame is.  */
-      framereg = -1;
-      framesize = 0;
-    }
 
   if (cache)
     {
@@ -2912,10 +2904,10 @@ 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];
 
   addr_in_block = get_frame_address_in_block (this_frame);
-  if (in_plt_section (addr_in_block, NULL)
+  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)
@@ -2933,6 +2925,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 = *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 = *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)
 {
@@ -3093,7 +3206,7 @@ thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
          if (insn & 0x0100)  /* <registers> include PC.  */
            found_return = 1;
        }
-      else if ((insn & 0xe000) == 0xe000)  /* 32-bit Thumb-2 instruction */
+      else if (thumb_insn_size (insn) == 4)  /* 32-bit Thumb-2 instruction */
        {
          if (target_read_memory (scan_pc, buf, 2))
            break;
@@ -3226,6 +3339,9 @@ arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
       else if ((insn & 0x0fff0000) == 0x08bd0000)
        /* POP (LDMIA).  */
        found_stack_adjust = 1;
+      else if ((insn & 0x0fff0000) == 0x049d0000)
+       /* POP of a single register.  */
+       found_stack_adjust = 1;
     }
 
   if (found_stack_adjust)
@@ -3291,7 +3407,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:
@@ -3657,7 +3772,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,
@@ -3988,7 +4104,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));
     }
@@ -3999,7 +4115,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));
     }
@@ -4335,14 +4451,9 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
       int cond = itstate >> 4;
 
       if (! condition_true (cond, status))
-       {
-         /* Advance to the next instruction.  All the 32-bit
-            instructions share a common prefix.  */
-         if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
-           return MAKE_THUMB_ADDR (pc + 4);
-         else
-           return MAKE_THUMB_ADDR (pc + 2);
-       }
+       /* Advance to the next instruction.  All the 32-bit
+          instructions share a common prefix.  */
+       return MAKE_THUMB_ADDR (pc + thumb_insn_size (inst1));
 
       /* Otherwise, handle the instruction normally.  */
     }
@@ -4376,7 +4487,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
     {
       nextpc = pc_val + (sbits (inst1, 0, 10) << 1);
     }
-  else if ((inst1 & 0xe000) == 0xe000) /* 32-bit instruction */
+  else if (thumb_insn_size (inst1) == 4) /* 32-bit instruction */
     {
       unsigned short inst2;
       inst2 = read_memory_unsigned_integer (pc + 2, 2, byte_order_for_code);
@@ -4552,7 +4663,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));
     }
@@ -4894,6 +5005,226 @@ arm_insert_single_step_breakpoint (struct gdbarch *gdbarch,
   do_cleanups (old_chain);
 }
 
+/* Checks for an atomic sequence of instructions beginning with a LDREX{,B,H,D}
+   instruction and ending with a STREX{,B,H,D} instruction.  If such a sequence
+   is found, attempt to step through it.  A breakpoint is placed at the end of
+   the sequence.  */
+
+static int
+thumb_deal_with_atomic_sequence_raw (struct frame_info *frame)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct address_space *aspace = get_frame_address_space (frame);
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  CORE_ADDR pc = get_frame_pc (frame);
+  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR loc = pc;
+  unsigned short insn1, insn2;
+  int insn_count;
+  int index;
+  int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */
+  const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+  ULONGEST status, itstate;
+
+  /* We currently do not support atomic sequences within an IT block.  */
+  status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
+  itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3);
+  if (itstate & 0x0f)
+    return 0;
+
+  /* Assume all atomic sequences start with a ldrex{,b,h,d} instruction.  */
+  insn1 = read_memory_unsigned_integer (loc, 2, byte_order_for_code);
+  loc += 2;
+  if (thumb_insn_size (insn1) != 4)
+    return 0;
+
+  insn2 = read_memory_unsigned_integer (loc, 2, byte_order_for_code);
+  loc += 2;
+  if (!((insn1 & 0xfff0) == 0xe850
+        || ((insn1 & 0xfff0) == 0xe8d0 && (insn2 & 0x00c0) == 0x0040)))
+    return 0;
+
+  /* Assume that no atomic sequence is longer than "atomic_sequence_length"
+     instructions.  */
+  for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
+    {
+      insn1 = read_memory_unsigned_integer (loc, 2, byte_order_for_code);
+      loc += 2;
+
+      if (thumb_insn_size (insn1) != 4)
+       {
+         /* Assume that there is at most one conditional branch in the
+            atomic sequence.  If a conditional branch is found, put a
+            breakpoint in its destination address.  */
+         if ((insn1 & 0xf000) == 0xd000 && bits (insn1, 8, 11) != 0x0f)
+           {
+             if (last_breakpoint > 0)
+               return 0; /* More than one conditional branch found,
+                            fallback to the standard code.  */
+
+             breaks[1] = loc + 2 + (sbits (insn1, 0, 7) << 1);
+             last_breakpoint++;
+           }
+
+         /* We do not support atomic sequences that use any *other*
+            instructions but conditional branches to change the PC.
+            Fall back to standard code to avoid losing control of
+            execution.  */
+         else if (thumb_instruction_changes_pc (insn1))
+           return 0;
+       }
+      else
+       {
+         insn2 = read_memory_unsigned_integer (loc, 2, byte_order_for_code);
+         loc += 2;
+
+         /* Assume that there is at most one conditional branch in the
+            atomic sequence.  If a conditional branch is found, put a
+            breakpoint in its destination address.  */
+         if ((insn1 & 0xf800) == 0xf000
+             && (insn2 & 0xd000) == 0x8000
+             && (insn1 & 0x0380) != 0x0380)
+           {
+             int sign, j1, j2, imm1, imm2;
+             unsigned int offset;
+
+             sign = sbits (insn1, 10, 10);
+             imm1 = bits (insn1, 0, 5);
+             imm2 = bits (insn2, 0, 10);
+             j1 = bit (insn2, 13);
+             j2 = bit (insn2, 11);
+
+             offset = (sign << 20) + (j2 << 19) + (j1 << 18);
+             offset += (imm1 << 12) + (imm2 << 1);
+
+             if (last_breakpoint > 0)
+               return 0; /* More than one conditional branch found,
+                            fallback to the standard code.  */
+
+             breaks[1] = loc + offset;
+             last_breakpoint++;
+           }
+
+         /* We do not support atomic sequences that use any *other*
+            instructions but conditional branches to change the PC.
+            Fall back to standard code to avoid losing control of
+            execution.  */
+         else if (thumb2_instruction_changes_pc (insn1, insn2))
+           return 0;
+
+         /* If we find a strex{,b,h,d}, we're done.  */
+         if ((insn1 & 0xfff0) == 0xe840
+             || ((insn1 & 0xfff0) == 0xe8c0 && (insn2 & 0x00c0) == 0x0040))
+           break;
+       }
+    }
+
+  /* If we didn't find the strex{,b,h,d}, we cannot handle the sequence.  */
+  if (insn_count == atomic_sequence_length)
+    return 0;
+
+  /* Insert a breakpoint right after the end of the atomic sequence.  */
+  breaks[0] = loc;
+
+  /* Check for duplicated breakpoints.  Check also for a breakpoint
+     placed (branch instruction's destination) anywhere in sequence.  */
+  if (last_breakpoint
+      && (breaks[1] == breaks[0]
+         || (breaks[1] >= pc && breaks[1] < loc)))
+    last_breakpoint = 0;
+
+  /* Effectively inserts the breakpoints.  */
+  for (index = 0; index <= last_breakpoint; index++)
+    arm_insert_single_step_breakpoint (gdbarch, aspace,
+                                      MAKE_THUMB_ADDR (breaks[index]));
+
+  return 1;
+}
+
+static int
+arm_deal_with_atomic_sequence_raw (struct frame_info *frame)
+{
+  struct gdbarch *gdbarch = get_frame_arch (frame);
+  struct address_space *aspace = get_frame_address_space (frame);
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  CORE_ADDR pc = get_frame_pc (frame);
+  CORE_ADDR breaks[2] = {-1, -1};
+  CORE_ADDR loc = pc;
+  unsigned int insn;
+  int insn_count;
+  int index;
+  int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed).  */
+  const int atomic_sequence_length = 16; /* Instruction sequence length.  */
+
+  /* Assume all atomic sequences start with a ldrex{,b,h,d} instruction.
+     Note that we do not currently support conditionally executed atomic
+     instructions.  */
+  insn = read_memory_unsigned_integer (loc, 4, byte_order_for_code);
+  loc += 4;
+  if ((insn & 0xff9000f0) != 0xe1900090)
+    return 0;
+
+  /* Assume that no atomic sequence is longer than "atomic_sequence_length"
+     instructions.  */
+  for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
+    {
+      insn = read_memory_unsigned_integer (loc, 4, byte_order_for_code);
+      loc += 4;
+
+      /* Assume that there is at most one conditional branch in the atomic
+         sequence.  If a conditional branch is found, put a breakpoint in
+         its destination address.  */
+      if (bits (insn, 24, 27) == 0xa)
+       {
+          if (last_breakpoint > 0)
+            return 0; /* More than one conditional branch found, fallback
+                         to the standard single-step code.  */
+
+         breaks[1] = BranchDest (loc - 4, insn);
+         last_breakpoint++;
+        }
+
+      /* We do not support atomic sequences that use any *other* instructions
+         but conditional branches to change the PC.  Fall back to standard
+        code to avoid losing control of execution.  */
+      else if (arm_instruction_changes_pc (insn))
+       return 0;
+
+      /* If we find a strex{,b,h,d}, we're done.  */
+      if ((insn & 0xff9000f0) == 0xe1800090)
+       break;
+    }
+
+  /* If we didn't find the strex{,b,h,d}, we cannot handle the sequence.  */
+  if (insn_count == atomic_sequence_length)
+    return 0;
+
+  /* Insert a breakpoint right after the end of the atomic sequence.  */
+  breaks[0] = loc;
+
+  /* Check for duplicated breakpoints.  Check also for a breakpoint
+     placed (branch instruction's destination) anywhere in sequence.  */
+  if (last_breakpoint
+      && (breaks[1] == breaks[0]
+         || (breaks[1] >= pc && breaks[1] < loc)))
+    last_breakpoint = 0;
+
+  /* Effectively inserts the breakpoints.  */
+  for (index = 0; index <= last_breakpoint; index++)
+    arm_insert_single_step_breakpoint (gdbarch, aspace, breaks[index]);
+
+  return 1;
+}
+
+int
+arm_deal_with_atomic_sequence (struct frame_info *frame)
+{
+  if (arm_frame_is_thumb (frame))
+    return thumb_deal_with_atomic_sequence_raw (frame);
+  else
+    return arm_deal_with_atomic_sequence_raw (frame);
+}
+
 /* single_step() is called just before we want to resume the inferior,
    if we want to single-step it but there is no hardware or kernel
    single-step support.  We find the target of the coming instruction
@@ -4904,8 +5235,12 @@ arm_software_single_step (struct frame_info *frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
   struct address_space *aspace = get_frame_address_space (frame);
-  CORE_ADDR next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
+  CORE_ADDR next_pc;
+
+  if (arm_deal_with_atomic_sequence (frame))
+    return 1;
 
+  next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
   arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc);
 
   return 1;
@@ -4919,7 +5254,7 @@ 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);
@@ -4952,7 +5287,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;
 
@@ -6652,7 +6987,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;
@@ -8281,7 +8616,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).  */
@@ -8440,10 +8775,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
@@ -8472,7 +8807,7 @@ arm_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, int *lenptr)
            {
              unsigned short inst1;
              inst1 = extract_unsigned_integer (buf, 2, byte_order_for_code);
-             if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
+             if (thumb_insn_size (inst1) == 4)
                {
                  *lenptr = tdep->thumb2_breakpoint_size;
                  return tdep->thumb2_breakpoint;
@@ -8494,8 +8829,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)
@@ -8712,7 +9045,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)
        {
@@ -8798,11 +9131,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;
 
@@ -8829,7 +9163,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)
@@ -8852,6 +9186,12 @@ arm_return_value (struct gdbarch *gdbarch, struct type *func_type,
        return RETURN_VALUE_STRUCT_CONVENTION;
     }
 
+  /* AAPCS returns complex types longer than a register in memory.  */
+  if (tdep->arm_abi != ARM_ABI_APCS
+      && TYPE_CODE (valtype) == TYPE_CODE_COMPLEX
+      && TYPE_LENGTH (valtype) > INT_REGISTER_SIZE)
+    return RETURN_VALUE_STRUCT_CONVENTION;
+
   if (writebuf)
     arm_store_return_value (valtype, regcache, writebuf);
 
@@ -8869,7 +9209,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);
 
@@ -8887,7 +9227,7 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
 CORE_ADDR
 arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
 {
-  char *name;
+  const char *name;
   int namelen;
   CORE_ADDR start_addr;
 
@@ -8976,7 +9316,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.  */
@@ -9010,10 +9350,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]);
@@ -9047,10 +9387,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]);
@@ -9063,8 +9403,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"),
@@ -9075,7 +9413,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 "
@@ -9279,7 +9617,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));
 
@@ -9331,7 +9669,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));
 
@@ -9354,10 +9692,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));
 
@@ -9398,7 +9735,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));
 
@@ -9450,6 +9787,49 @@ arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
     return default_register_reggroup_p (gdbarch, regnum, group);
 }
 
+\f
+/* For backward-compatibility we allow two 'g' packet lengths with
+   the remote protocol depending on whether FPA registers are
+   supplied.  M-profile targets do not have FPA registers, but some
+   stubs already exist in the wild which use a 'g' packet which
+   supplies them albeit with dummy values.  The packet format which
+   includes FPA registers should be considered deprecated for
+   M-profile targets.  */
+
+static void
+arm_register_g_packet_guesses (struct gdbarch *gdbarch)
+{
+  if (gdbarch_tdep (gdbarch)->is_m)
+    {
+      /* If we know from the executable this is an M-profile target,
+        cater for remote targets whose register set layout is the
+        same as the FPA layout.  */
+      register_remote_g_packet_guess (gdbarch,
+                                     /* r0-r12,sp,lr,pc; f0-f7; fps,xpsr */
+                                     (16 * INT_REGISTER_SIZE)
+                                     + (8 * FP_REGISTER_SIZE)
+                                     + (2 * INT_REGISTER_SIZE),
+                                     tdesc_arm_with_m_fpa_layout);
+
+      /* The regular M-profile layout.  */
+      register_remote_g_packet_guess (gdbarch,
+                                     /* r0-r12,sp,lr,pc; xpsr */
+                                     (16 * INT_REGISTER_SIZE)
+                                     + INT_REGISTER_SIZE,
+                                     tdesc_arm_with_m);
+
+      /* 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.  */
+}
+
 \f
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
@@ -9584,7 +9964,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
                  && (attr_arch == TAG_CPU_ARCH_V6_M
                      || attr_arch == TAG_CPU_ARCH_V6S_M
                      || attr_profile == 'M'))
-               tdesc = tdesc_arm_with_m;
+               is_m = 1;
 #endif
            }
 
@@ -9841,6 +10221,8 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   tdep->have_neon_pseudos = have_neon_pseudos;
   tdep->have_neon = have_neon;
 
+  arm_register_g_packet_guesses (gdbarch);
+
   /* Breakpoints.  */
   switch (info.byte_order_for_code)
     {
@@ -9894,7 +10276,6 @@ 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.  */
@@ -9957,6 +10338,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);
@@ -10077,6 +10460,8 @@ _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 ();
@@ -10190,3 +10575,2062 @@ vfp - VFP co-processor."),
                           NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                           &setdebuglist, &showdebuglist);
 }
+
+/* ARM-reversible process record data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+        do  \
+          { \
+            unsigned int reg_len = LENGTH; \
+            if (reg_len) \
+              { \
+                REGS = XNEWVEC (uint32_t, reg_len); \
+                memcpy(&REGS[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+              } \
+          } \
+        while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+        do  \
+          { \
+            unsigned int mem_len = LENGTH; \
+            if (mem_len) \
+            { \
+              MEMS =  XNEWVEC (struct arm_mem_r, mem_len);  \
+              memcpy(&MEMS->len, &RECORD_BUF[0], \
+                     sizeof(struct arm_mem_r) * LENGTH); \
+            } \
+          } \
+          while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded. (boolean expression).  */
+#define INSN_RECORDED(ARM_RECORD) \
+        (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure.  */
+struct arm_mem_r
+{
+  uint32_t len;    /* Record length.  */
+  CORE_ADDR addr;  /* Memory address.  */
+};
+
+/* ARM instruction record contains opcode of current insn
+   and execution state (before entry to decode_insn()),
+   contains list of to-be-modified registers and
+   memory blocks (on return from decode_insn()).  */
+
+typedef struct insn_decode_record_t
+{
+  struct gdbarch *gdbarch;
+  struct regcache *regcache;
+  CORE_ADDR this_addr;          /* Address of the insn being decoded.  */
+  uint32_t arm_insn;            /* Should accommodate thumb.  */
+  uint32_t cond;                /* Condition code.  */
+  uint32_t opcode;              /* Insn opcode.  */
+  uint32_t decode;              /* Insn decode bits.  */
+  uint32_t mem_rec_count;       /* No of mem records.  */
+  uint32_t reg_rec_count;       /* No of reg records.  */
+  uint32_t *arm_regs;           /* Registers to be saved for this record.  */
+  struct arm_mem_r *arm_mems;   /* Memory to be saved for this record.  */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields.  */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+  uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+  if (!len)
+    return 1;
+
+  if (!sbo)
+    ones = ~ones;
+
+  while (ones)
+    {
+      if (!(ones & sbo))
+        {
+          return 0;
+        }
+      ones = ones >> 1;
+    }
+  return 1;
+}
+
+typedef enum
+{
+  ARM_RECORD_STRH=1,
+  ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+  ARM_RECORD=1,
+  THUMB_RECORD,
+  THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf, 
+                 uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  ULONGEST u_regval[2]= {0};
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+  uint32_t opcode1 = 0;
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+  if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+    {
+      /* 1) Handle misc store, immediate offset.  */
+      immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+      immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_src1,
+                                  &u_regval[0]);
+      if (ARM_PC_REGNUM == reg_src1)
+        {
+          /* If R15 was used as Rn, hence current PC+8.  */
+          u_regval[0] = u_regval[0] + 8;
+        }
+      offset_8 = (immed_high << 4) | immed_low;
+      /* Calculate target store address.  */
+      if (14 == arm_insn_r->opcode)
+        {
+          tgt_mem_addr = u_regval[0] + offset_8;
+        }
+      else
+        {
+          tgt_mem_addr = u_regval[0] - offset_8;
+        }
+      if (ARM_RECORD_STRH == str_type)
+        {
+          record_buf_mem[0] = 2;
+          record_buf_mem[1] = tgt_mem_addr;
+          arm_insn_r->mem_rec_count = 1;
+        }
+      else if (ARM_RECORD_STRD == str_type)
+        {
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = tgt_mem_addr;
+          record_buf_mem[2] = 4;
+          record_buf_mem[3] = tgt_mem_addr + 4;
+          arm_insn_r->mem_rec_count = 2;
+        }
+    }
+  else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+    {
+      /* 2) Store, register offset.  */
+      /* Get Rm.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+      /* Get Rn.  */
+      reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+      regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+      if (15 == reg_src2)
+        {
+          /* If R15 was used as Rn, hence current PC+8.  */
+          u_regval[0] = u_regval[0] + 8;
+        }
+      /* Calculate target store address, Rn +/- Rm, register offset.  */
+      if (12 == arm_insn_r->opcode)
+        {
+          tgt_mem_addr = u_regval[0] + u_regval[1];
+        }
+      else
+        {
+          tgt_mem_addr = u_regval[1] - u_regval[0];
+        }
+      if (ARM_RECORD_STRH == str_type)
+        {
+          record_buf_mem[0] = 2;
+          record_buf_mem[1] = tgt_mem_addr;
+          arm_insn_r->mem_rec_count = 1;
+        }
+      else if (ARM_RECORD_STRD == str_type)
+        {
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = tgt_mem_addr;
+          record_buf_mem[2] = 4;
+          record_buf_mem[3] = tgt_mem_addr + 4;
+          arm_insn_r->mem_rec_count = 2;
+        }
+    }
+  else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+           || 2 == arm_insn_r->opcode  || 6 == arm_insn_r->opcode)
+    {
+      /* 3) Store, immediate pre-indexed.  */
+      /* 5) Store, immediate post-indexed.  */
+      immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+      immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+      offset_8 = (immed_high << 4) | immed_low;
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+      /* Calculate target store address, Rn +/- Rm, register offset.  */
+      if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+        {
+          tgt_mem_addr = u_regval[0] + offset_8;
+        }
+      else
+        {
+          tgt_mem_addr = u_regval[0] - offset_8;
+        }
+      if (ARM_RECORD_STRH == str_type)
+        {
+          record_buf_mem[0] = 2;
+          record_buf_mem[1] = tgt_mem_addr;
+          arm_insn_r->mem_rec_count = 1;
+        }
+      else if (ARM_RECORD_STRD == str_type)
+        {
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = tgt_mem_addr;
+          record_buf_mem[2] = 4;
+          record_buf_mem[3] = tgt_mem_addr + 4;
+          arm_insn_r->mem_rec_count = 2;
+        }
+      /* Record Rn also as it changes.  */
+      *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+           || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+    {
+      /* 4) Store, register pre-indexed.  */
+      /* 6) Store, register post -indexed.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+      reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+      regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+      /* Calculate target store address, Rn +/- Rm, register offset.  */
+      if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+        {
+          tgt_mem_addr = u_regval[0] + u_regval[1];
+        }
+      else
+        {
+          tgt_mem_addr = u_regval[1] - u_regval[0];
+        }
+      if (ARM_RECORD_STRH == str_type)
+        {
+          record_buf_mem[0] = 2;
+          record_buf_mem[1] = tgt_mem_addr;
+          arm_insn_r->mem_rec_count = 1;
+        }
+      else if (ARM_RECORD_STRD == str_type)
+        {
+          record_buf_mem[0] = 4;
+          record_buf_mem[1] = tgt_mem_addr;
+          record_buf_mem[2] = 4;
+          record_buf_mem[3] = tgt_mem_addr + 4;
+          arm_insn_r->mem_rec_count = 2;
+        }
+      /* Record Rn also as it changes.  */
+      *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  return 0;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+  uint32_t ret = 0;  /* Return value: -1:record failure ;  0:success  */
+  uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+  uint32_t reg_src1 = 0;
+  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  ULONGEST u_regval = 0;
+
+  gdb_assert (!INSN_RECORDED(arm_insn_r));
+  /* Handle unconditional insn extension space.  */
+
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  if (arm_insn_r->cond)
+    {
+      /* PLD has no affect on architectural state, it just affects
+         the caches.  */
+      if (5 == ((opcode1 & 0xE0) >> 5))
+        {
+          /* BLX(1) */
+          record_buf[0] = ARM_PS_REGNUM;
+          record_buf[1] = ARM_LR_REGNUM;
+          arm_insn_r->reg_rec_count = 2;
+        }
+      /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn.  */
+    }
+
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+    {
+      ret = -1;
+      /* Undefined instruction on ARM V5; need to handle if later 
+         versions define it.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+  /* Handle arithmetic insn extension space.  */
+  if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+      && !INSN_RECORDED(arm_insn_r))
+    {
+      /* Handle MLA(S) and MUL(S).  */
+      if (0 <= insn_op1 && 3 >= insn_op1)
+      {
+        record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+        record_buf[1] = ARM_PS_REGNUM;
+        arm_insn_r->reg_rec_count = 2;
+      }
+      else if (4 <= insn_op1 && 15 >= insn_op1)
+      {
+        /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S).  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+        record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        record_buf[2] = ARM_PS_REGNUM;
+        arm_insn_r->reg_rec_count = 3;
+      }
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+  insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+  /* Handle control insn extension space.  */
+
+  if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+      && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+    {
+      if (!bit (arm_insn_r->arm_insn,25))
+        {
+          if (!bits (arm_insn_r->arm_insn, 4, 7))
+            {
+              if ((0 == insn_op1) || (2 == insn_op1))
+                {
+                  /* MRS.  */
+                  record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                  arm_insn_r->reg_rec_count = 1;
+                }
+              else if (1 == insn_op1)
+                {
+                  /* CSPR is going to be changed.  */
+                  record_buf[0] = ARM_PS_REGNUM;
+                  arm_insn_r->reg_rec_count = 1;
+                }
+              else if (3 == insn_op1)
+                {
+                  /* SPSR is going to be changed.  */
+                  /* We need to get SPSR value, which is yet to be done.  */
+                  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 -1;
+                }
+            }
+          else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+            {
+              if (1 == insn_op1)
+                {
+                  /* BX.  */
+                  record_buf[0] = ARM_PS_REGNUM;
+                  arm_insn_r->reg_rec_count = 1;
+                }
+              else if (3 == insn_op1)
+                {
+                  /* CLZ.  */
+                  record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                  arm_insn_r->reg_rec_count = 1;
+                }
+            }
+          else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+            {
+              /* BLX.  */
+              record_buf[0] = ARM_PS_REGNUM;
+              record_buf[1] = ARM_LR_REGNUM;
+              arm_insn_r->reg_rec_count = 2;
+            }
+          else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+            {
+              /* QADD, QSUB, QDADD, QDSUB */
+              record_buf[0] = ARM_PS_REGNUM;
+              record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+              arm_insn_r->reg_rec_count = 2;
+            }
+          else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+            {
+              /* BKPT.  */
+              record_buf[0] = ARM_PS_REGNUM;
+              record_buf[1] = ARM_LR_REGNUM;
+              arm_insn_r->reg_rec_count = 2;
+
+              /* Save SPSR also;how?  */
+              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 -1;
+            }
+          else if(8 == bits (arm_insn_r->arm_insn, 4, 7) 
+                  || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+                  || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+                  || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+                 )
+            {
+              if (0 == insn_op1 || 1 == insn_op1)
+                {
+                  /* SMLA<x><y>, SMLAW<y>, SMULW<y>.  */
+                  /* We dont do optimization for SMULW<y> where we
+                     need only Rd.  */
+                  record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                  record_buf[1] = ARM_PS_REGNUM;
+                  arm_insn_r->reg_rec_count = 2;
+                }
+              else if (2 == insn_op1)
+                {
+                  /* SMLAL<x><y>.  */
+                  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 if (3 == insn_op1)
+                {
+                  /* SMUL<x><y>.  */
+                  record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+                  arm_insn_r->reg_rec_count = 1;
+                }
+            }
+        }
+      else
+        {
+          /* MSR : immediate form.  */
+          if (1 == insn_op1)
+            {
+              /* CSPR is going to be changed.  */
+              record_buf[0] = ARM_PS_REGNUM;
+              arm_insn_r->reg_rec_count = 1;
+            }
+          else if (3 == insn_op1)
+            {
+              /* SPSR is going to be changed.  */
+              /* we need to get SPSR value, which is yet to be done  */
+              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 -1;
+            }
+        }
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+  insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+  /* Handle load/store insn extension space.  */
+
+  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) 
+      && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+      && !INSN_RECORDED(arm_insn_r))
+    {
+      /* SWP/SWPB.  */
+      if (0 == insn_op1)
+        {
+          /* These insn, changes register and memory as well.  */
+          /* SWP or SWPB insn.  */
+          /* Get memory address given by Rn.  */
+          reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+          regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+          /* SWP insn ?, swaps word.  */
+          if (8 == arm_insn_r->opcode)
+            {
+              record_buf_mem[0] = 4;
+            }
+          else
+            {
+              /* SWPB insn, swaps only byte.  */
+              record_buf_mem[0] = 1;
+            }
+          record_buf_mem[1] = u_regval;
+          arm_insn_r->mem_rec_count = 1;
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+        {
+          /* STRH.  */
+          arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+                          ARM_RECORD_STRH);
+        }
+      else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+        {
+          /* LDRD.  */
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          record_buf[1] = record_buf[0] + 1;
+          arm_insn_r->reg_rec_count = 2;
+        }
+      else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+        {
+          /* STRD.  */
+          arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+                        ARM_RECORD_STRD);
+        }
+      else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+        {
+          /* LDRH, LDRSB, LDRSH.  */
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+      && !INSN_RECORDED(arm_insn_r))
+    {
+      ret = -1;
+      /* Handle coprocessor insn extension space.  */
+    }
+
+  /* To be done for ARMv5 and later; as of now we return -1.  */
+  if (-1 == ret)
+    printf_unfiltered (_("Process record does not support instruction x%0x "
+                         "at address %s.\n"),arm_insn_r->arm_insn,
+                         paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+
+  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 ret;
+}
+
+/* Handling opcode 000 insns.  */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  ULONGEST u_regval[2] = {0};
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+  uint32_t opcode1 = 0;
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+  /* Data processing insn /multiply insn.  */
+  if (9 == arm_insn_r->decode
+      && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+      ||  (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+    {
+      /* Handle multiply instructions.  */
+      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
+        if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+          {
+            /* Handle MLA and MUL.  */
+            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+            record_buf[1] = ARM_PS_REGNUM;
+            arm_insn_r->reg_rec_count = 2;
+          }
+        else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+          {
+            /* Handle SMLAL, SMULL, UMLAL, UMULL.  */
+            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+            record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+            record_buf[2] = ARM_PS_REGNUM;
+            arm_insn_r->reg_rec_count = 3;
+          }
+    }
+  else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+           && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+    {
+      /* Handle misc load insns, as 20th bit  (L = 1).  */
+      /* LDR insn has a capability to do branching, if
+         MOV LR, PC is precceded by LDR insn having Rn as R15
+         in that case, it emulates branch and link insn, and hence we 
+         need to save CSPR and PC as well. I am not sure this is right
+         place; as opcode = 010 LDR insn make this happen, if R15 was
+         used.  */
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      if (15 != reg_dest)
+        {
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          record_buf[0] = reg_dest;
+          record_buf[1] = ARM_PS_REGNUM;
+          arm_insn_r->reg_rec_count = 2;
+        }
+    }
+  else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+           && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+           && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+           && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+    {
+      /* Handle MSR insn.  */
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          /* SPSR is going to be changed.  */
+          /* How to read SPSR value?  */
+          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 -1;
+        }
+    }
+  else if (9 == arm_insn_r->decode
+           && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+           && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* Handling SWP, SWPB.  */
+      /* These insn, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          record_buf_mem[0] = 4;
+        }
+        else
+        {
+          /* SWPB insn, swaps only byte.  */
+          record_buf_mem[0] = 1;
+        }
+      record_buf_mem[1] = u_regval[0];
+      arm_insn_r->mem_rec_count = 1;
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (3 == arm_insn_r->decode && 0x12 == opcode1
+           && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+    {
+      /* Handle BLX, branch and link/exchange.  */
+      if (9 == arm_insn_r->opcode)
+      {
+        /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+           and R14 stores the return address.  */
+        record_buf[0] = ARM_PS_REGNUM;
+        record_buf[1] = ARM_LR_REGNUM;
+        arm_insn_r->reg_rec_count = 2;
+      }
+    }
+  else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+    {
+      /* Handle enhanced software breakpoint insn, BKPT.  */
+      /* CPSR is changed to be executed in ARM state,  disabling normal
+         interrupts, entering abort mode.  */
+      /* According to high vector configuration PC is set.  */
+      /* user hit breakpoint and type reverse, in
+         that case, we need to go back with previous CPSR and
+         Program Counter.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
+
+      /* Save SPSR also; how?  */
+      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 -1;
+    }
+  else if (11 == arm_insn_r->decode
+           && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+  {
+    /* Handle enhanced store insns and DSP insns (e.g. LDRD).  */
+
+    /* Handle str(x) insn */
+    arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+                    ARM_RECORD_STRH);
+  }
+  else if (1 == arm_insn_r->decode && 0x12 == opcode1
+           && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+    {
+      /* Handle BX, branch and link/exchange.  */
+      /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (1 == arm_insn_r->decode && 0x16 == opcode1
+           && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+           && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+    {
+      /* Count leading zeros: CLZ.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+           && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+           && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+           && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+          )
+    {
+      /* Handle MRS insn.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if (arm_insn_r->opcode <= 15)
+    {
+      /* Normal data processing insns.  */
+      /* Out of 11 shifter operands mode, all the insn modifies destination
+         register, which is specified by 13-16 decode.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      record_buf[1] = ARM_PS_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
+    }
+  else
+    {
+      return -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;
+}
+
+/* Handling opcode 001 insns.  */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+      && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+      && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+     )
+    {
+      /* Handle MSR insn.  */
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          /* SPSR is going to be changed.  */
+        }
+    }
+  else if (arm_insn_r->opcode <= 15)
+    {
+      /* Normal data processing insns.  */
+      /* Out of 11 shifter operands mode, all the insn modifies destination
+         register, which is specified by 13-16 decode.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      record_buf[1] = ARM_PS_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
+    }
+  else
+    {
+      return -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;
+}
+
+/* Handling opcode 010 insns.  */
+
+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 record_buf[8], record_buf_mem[8];
+
+  ULONGEST u_regval = 0;
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      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;
+        }
+    }
+  else
+    {
+      /* Store, immediate offset, immediate pre-indexed,
+         immediate post-indexed.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+      /* U == 1 */
+      if (bit (arm_insn_r->arm_insn, 23))
+        {
+          tgt_mem_addr = u_regval + offset_12;
+        }
+      else
+        {
+          tgt_mem_addr = u_regval - offset_12;
+        }
+
+      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;
+        }
+    }
+
+  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;
+}
+
+/* Handling opcode 011 insns.  */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  LONGEST s_word;
+  ULONGEST u_regval[2];
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  /* Handle enhanced store insns and LDRD DSP insn,
+     order begins according to addressing modes for store insns
+     STRH insn.  */
+
+  /* LDR or STR?  */
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      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 (15 != reg_dest)
+        {
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          record_buf[0] = reg_dest;
+          record_buf[1] = ARM_PS_REGNUM;
+          arm_insn_r->reg_rec_count = 2;
+        }
+    }
+  else
+    {
+      if (! bits (arm_insn_r->arm_insn, 4, 11))
+        {
+          /* Store insn, register offset and register pre-indexed,
+             register post-indexed.  */
+          /* Get Rm.  */
+          reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+          /* Get Rn.  */
+          reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+          regcache_raw_read_unsigned (reg_cache, reg_src1
+                                      , &u_regval[0]);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_regval[1]);
+          if (15 == reg_src2)
+            {
+              /* If R15 was used as Rn, hence current PC+8.  */
+              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_regval[0] = u_regval[0] + 8;
+            }
+          /* Calculate target store address, Rn +/- Rm, register offset.  */
+          /* U == 1.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_regval[0] + u_regval[1];
+            }
+          else
+            {
+              tgt_mem_addr = u_regval[1] - u_regval[0];
+            }
+
+          switch (arm_insn_r->opcode)
+            {
+              /* STR.  */
+              case 8:
+              case 12:
+              /* STR.  */    
+              case 9:
+              case 13:
+              /* STRT.  */
+              case 1:
+              case 5:
+              /* STR.  */
+              case 0:
+              case 4:
+                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
+             )
+            {
+              /* Rn is going to be changed in pre-indexed mode and
+                 post-indexed mode as well.  */
+              record_buf[0] = reg_src2;
+              arm_insn_r->reg_rec_count = 1;
+            }
+        }
+      else
+        {
+          /* Store insn, scaled register offset; scaled pre-indexed.  */
+          offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+          /* Get Rm.  */
+          reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+          /* Get Rn.  */
+          reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+          /* Get shift_imm.  */
+          shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+          regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+          regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+          regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+          /* Offset_12 used as shift.  */
+          switch (offset_12)
+            {
+              case 0:
+                /* Offset_12 used as index.  */
+                offset_12 = u_regval[0] << shift_imm;
+              break;
+
+              case 1:
+                offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+              break;
+
+              case 2:
+                if (!shift_imm)
+                  {
+                    if (bit (u_regval[0], 31))
+                      {
+                        offset_12 = 0xFFFFFFFF;
+                      }
+                    else
+                      {
+                        offset_12 = 0;
+                      }
+                  }
+                else
+                  {
+                    /* This is arithmetic shift.  */
+                    offset_12 = s_word >> shift_imm;
+                  }
+                break;
+
+              case 3:
+                if (!shift_imm)
+                  {
+                    regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+                                                &u_regval[1]);
+                    /* Get C flag value and shift it by 31.  */
+                    offset_12 = (((bit (u_regval[1], 29)) << 31) \
+                                  | (u_regval[0]) >> 1);
+                  }
+                else
+                  {
+                    offset_12 = (u_regval[0] >> shift_imm) \
+                                | (u_regval[0] <<
+                                (sizeof(uint32_t) - shift_imm));
+                  }
+              break;
+
+              default:
+                gdb_assert_not_reached ("no decoding pattern found");
+              break;
+            }
+
+          regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+          /* bit U set.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_regval[1] + offset_12;
+            }
+          else
+            {
+              tgt_mem_addr = u_regval[1] - offset_12;
+            }
+
+          switch (arm_insn_r->opcode)
+            {
+              /* STR.  */
+              case 8:
+              case 12:
+              /* STR.  */    
+              case 9:
+              case 13:
+              /* STRT.  */
+              case 1:
+              case 5:
+              /* STR.  */
+              case 0:
+              case 4:
+                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
+             )
+            {
+              /* Rn is going to be changed in register scaled pre-indexed
+                 mode,and scaled post indexed mode.  */
+              record_buf[0] = reg_src2;
+              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;
+}
+
+/* Handling opcode 100 insns.  */
+
+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 record_buf[24], record_buf_mem[48];
+
+  ULONGEST u_regval[2] = {0};
+
+  /* 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.  */
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDM  (1,2,3) where LDM  (3) changes CPSR too.  */
+
+      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);
+      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;
+
+        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++;
+              }
+          }
+
+    }
+  else
+    {
+      /* It handles both STM(1) and STM(2).  */
+      addr_mode = bits (arm_insn_r->arm_insn, 23, 24);    
+
+      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]);
+      while (register_bits)
+        {
+          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;    
+        }
+
+      /* 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;
+    }
+
+  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;
+}
+
+/* Handling opcode 101 insns.  */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+  uint32_t record_buf[8];
+
+  /* Handle B, BL, BLX(1) insns.  */
+  /* B simply branches so we do nothing here.  */
+  /* Note: BLX(1) doesnt fall here but instead it falls into
+     extension space.  */
+  if (bit (arm_insn_r->arm_insn, 24))
+  {
+    record_buf[0] = ARM_LR_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 110 insns.  */
+
+static int
+arm_record_coproc (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,
+                    paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+  return -1;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int
+arm_record_coproc_data_proc (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  */
+
+  /* Handle SWI insn; system call would be handled over here.  */
+
+  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;
+      }
+  }
+
+  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;
+}
+
+/* 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]);
+          if (8 == opcode2)
+            record_buf_mem[0] = 4;    /* STR (2).  */
+          else if (10 == opcode2)
+            record_buf_mem[0] = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            record_buf_mem[0] = 2;    /* STRH (2).  */
+          record_buf_mem[1] = u_regval[0] + u_regval[1];
+          thumb_insn_r->mem_rec_count = 1;
+        }
+    }
+  else if (bit (thumb_insn_r->arm_insn, 11))
+    {
+      /* Handle load from literal pool.  */
+      /* LDR(3).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (opcode1)
+    {
+      opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+      opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if ((3 == opcode2) && (!opcode3))
+        {
+          /* Branch with exchange.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          thumb_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          /* Format 8; special data processing insns.  */
+          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;
+        }
+    }
+  else
+    {
+      /* Format 5; data processing insns.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if (bit (thumb_insn_r->arm_insn, 7))
+        {
+          reg_src1 = reg_src1 + 8;
+        }
+      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);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+             record_buf_mem);
+
+  return 0;
+}
+
+/* Handling opcode 001 insns.  */
+
+static int
+thumb_record_ld_st_imm_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;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  ULONGEST u_regval = 0;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_regval + (immed_5 * 4);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
+             record_buf_mem);
+
+  return 0;
+}
+
+/* Handling opcode 100 insns.  */
+
+static int
+thumb_record_ld_st_stack (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;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  ULONGEST u_regval = 0;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_regval + (immed_8 * 4);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+  else if (0 == opcode)
+    {
+      /* STRH(1).  */
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_regval + (immed_5 * 2);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+             record_buf_mem);
+
+  return 0;
+}
+
+/* Handling opcode 101 insns.  */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+  uint32_t reg_src1;
+
+  ULONGEST u_regval = 0;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+  if (14 == opcode2)
+    {
+      /* 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++;
+            }
+        }
+    }
+  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);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_regval -  \
+                  (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+      thumb_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] = ARM_SP_REGNUM;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (0x1E == opcode1)
+    {
+      /* BKPT insn.  */
+      /* Handle enhanced software breakpoint insn, BKPT.  */
+      /* CPSR is changed to be executed in ARM state,  disabling normal
+         interrupts, entering abort mode.  */
+      /* According to high vector configuration PC is set.  */
+      /* User hits breakpoint and type reverse, in that case, we need to go back with 
+      previous CPSR and Program Counter.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      thumb_insn_r->reg_rec_count = 2;
+      /* We need to save SPSR value, which is not yet done.  */
+      printf_unfiltered (_("Process record does not support instruction "
+                           "0x%0x at address %s.\n"),
+                           thumb_insn_r->arm_insn,
+                           paddress (thumb_insn_r->gdbarch,
+                           thumb_insn_r->this_addr));
+      return -1;
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+      /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = ARM_SP_REGNUM;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+             record_buf_mem);
+
+  return 0;
+}
+
+/* Handling opcode 110 insns.  */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t ret = 0; /* function return value: -1:record failure ;  0:success  */
+  uint32_t reg_src1 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  ULONGEST u_regval = 0;
+
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (1 == opcode2)
+    {
+
+      /* LDMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* Get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+      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++;
+            }
+        }
+    }
+  else if (0 == opcode2)
+    {
+      /* It handles both STMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* Get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_regval;
+      thumb_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--;
+        }
+    }
+  else if (0x1F == opcode1)
+    {
+        /* 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"));
+            return -1;
+          }
+    }
+
+  /* B (1), conditional branch is automatically taken care in process_record,
+    as PC is saved there.  */
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+             record_buf_mem);
+
+  return ret;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t bits_h = 0;
+
+  bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (2 == bits_h || 3 == bits_h)
+    {
+      /* BL */
+      record_buf[0] = ARM_LR_REGNUM;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (1 == bits_h)
+    {
+      /* BLX(1). */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      thumb_insn_r->reg_rec_count = 2;
+    }
+
+  /* B(2) is automatically taken care in process_record, as PC is 
+     saved there.  */
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+  return 0;     
+}
+
+
+/* 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);
+  
+  if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+    return 1;
+  insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+                           insn_size, 
+                           gdbarch_byte_order (insn_record->gdbarch));
+  return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+   dispatch it.  */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+                uint32_t insn_size)
+{
+
+  /* (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] =                    
+  {
+    arm_record_data_proc_misc_ld_str,   /* 000.  */
+    arm_record_data_proc_imm,           /* 001.  */
+    arm_record_ld_st_imm_offset,        /* 010.  */
+    arm_record_ld_st_reg_offset,        /* 011.  */
+    arm_record_ld_st_multiple,          /* 100.  */
+    arm_record_b_bl,                    /* 101.  */
+    arm_record_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] =
+  { \
+    thumb_record_shift_add_sub,        /* 000.  */
+    thumb_record_add_sub_cmp_mov,      /* 001.  */
+    thumb_record_ld_st_reg_offset,     /* 010.  */
+    thumb_record_ld_st_imm_offset,     /* 011.  */
+    thumb_record_ld_st_stack,          /* 100.  */
+    thumb_record_misc,                 /* 101.  */
+    thumb_record_ldm_stm_swi,          /* 110.  */
+    thumb_record_branch                /* 111.  */
+  };
+
+  uint32_t ret = 0;    /* return value: negative:failure   0:success.  */
+  uint32_t insn_id = 0;
+
+  if (extract_arm_insn (arm_record, insn_size))
+    {
+      if (record_debug)
+        {
+          printf_unfiltered (_("Process record: error reading memory at "
+                              "addr %s len = %d.\n"),
+          paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);        
+        }
+      return -1;
+    }
+  else if (ARM_RECORD == record_type)
+    {
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = arm_record_extension_space (arm_record);
+      /* If this insn has fallen into extension space 
+         then we need not decode it anymore.  */
+      if (ret != -1 && !INSN_RECORDED(arm_record))
+        {
+          ret = arm_handle_insn[insn_id] (arm_record);
+        }
+    }
+  else if (THUMB_RECORD == record_type)
+    {
+      /* As thumb does not have condition codes, we set negative.  */
+      arm_record->cond = -1;
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  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;
+    }
+  else
+    {
+      /* Throw assertion.  */
+      gdb_assert_not_reached ("not a valid instruction, could not decode");
+    }
+
+  return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations.  */
+
+static void 
+deallocate_reg_mem (insn_decode_record *record)
+{
+  xfree (record->arm_regs);
+  xfree (record->arm_mems);    
+}
+
+
+/* Parse the current instruction and record the values of the registers and    
+   memory that will be changed in current instruction to record_arch_list".
+   Return -1 if something is wrong.  */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache, 
+                        CORE_ADDR insn_addr)
+{
+
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  uint32_t no_of_rec = 0;
+  uint32_t ret = 0;  /* return value: -1:record failure ;  0:success  */
+  ULONGEST t_bit = 0, insn_id = 0;
+
+  ULONGEST u_regval = 0;
+
+  insn_decode_record arm_record;
+
+  memset (&arm_record, 0, sizeof (insn_decode_record));
+  arm_record.regcache = regcache;
+  arm_record.this_addr = insn_addr;
+  arm_record.gdbarch = gdbarch;
+
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+                                      "addr = %s\n",
+      paddress (gdbarch, arm_record.this_addr));
+    }
+
+  if (extract_arm_insn (&arm_record, 2))
+    {
+      if (record_debug)
+        {
+          printf_unfiltered (_("Process record: error reading memory at "
+                             "addr %s len = %d.\n"),
+                             paddress (arm_record.gdbarch, 
+                             arm_record.this_addr), 2);
+        }
+      return -1;
+    }
+
+  /* Check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+  if (!(u_regval & t_bit))
+    {
+      /* We are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+    }
+  else
+    {
+      insn_id = bits (arm_record.arm_insn, 11, 15);
+      /* is it thumb2 insn?  */
+      if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+        {
+          ret = decode_insn (&arm_record, THUMB2_RECORD, 
+                             THUMB2_INSN_SIZE_BYTES);
+        }
+      else
+        {
+          /* We are decoding thumb insn.  */
+          ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+        }
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      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_full_arch_list_add_reg
+                 (arm_record.regcache , arm_record.arm_regs[no_of_rec]))
+              ret = -1;
+            }
+        }
+      /* Record memories.  */
+      if (arm_record.arm_mems)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count; no_of_rec++)
+            {
+              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))
+                ret = -1;
+            }
+        }
+
+      if (record_full_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
This page took 0.083285 seconds and 4 git commands to generate.