public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-05-29 15:38 paawan oza
  2011-05-31 18:05 ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-05-29 15:38 UTC (permalink / raw)
  To: gdb-patches, Petr Hluzín

Hi,

Fixed some minor issues with Patch.

PATCH STARTS
---------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-05-29 20:44:25.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1751 @@
                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 GET_REG_VAL(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    unsigned int reg_len = 0; \
+    reg_len = LENGTH; \
+    if (reg_len) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
+        while (reg_len) \
+          { \
+            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
+            reg_len--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    unsigned int mem_len = 0; \
+    mem_len = LENGTH; \
+    if (mem_len) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (mem_len)); \
+        while (mem_len) \
+          { \
+            MEMS[mem_len - 1].addr = RECORD_BUF[(mem_len * 2) - 1]; \
+            MEMS[mem_len - 1].len = RECORD_BUF[(mem_len * 2) - 2]; \
+            mem_len--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* 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 recors */
+  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 mendatory 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;
+}
+
+/* handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      ret = -1;
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      ret = -1;
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      ret = -1;
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      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 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 
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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 preccedded 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 insns, 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); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* what if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, 
&u_buf[0].unsigned_regval);            

+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = 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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_data_proc_imm_insn (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.  */
+           /* Oza: FIX ME ? how to read SPSR value?  */
+        }
+    }   
+  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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_ld_st_imm_offset_insn (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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].unsigned_regval + 
u_buf[1].unsigned_regval;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - 
u_buf[0].unsigned_regval;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL_SIGNED (reg_cache, reg_src1, &u_buf[0].signed_word);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].unsigned_regval << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> 
shift_imm; 

+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].unsigned_regval, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, 
&u_buf[1].unsigned_regval);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) 
\
+                                    | (u_buf[0].unsigned_regval) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                         | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - 
shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_handle_ld_st_multiple_insn (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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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 ("Invalid addressing mode for insn");
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction "
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;   
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 

+          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* save SPSR also; how?.  */
+      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_handle_swi_insn (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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[8]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[8]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 

+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) 
+            ? arm_handle_insn[insn_id] (arm_record) 
+            : handle_extension_space (arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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(0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; 
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-29 15:38 [PATCH] arm reversible : <phase_2_complete> paawan oza
@ 2011-05-31 18:05 ` Tom Tromey
  2011-06-03  7:44   ` paawan oza
  2011-06-03  7:51   ` paawan oza
  0 siblings, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-05-31 18:05 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb-patches, Petr Hluzín

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> Fixed some minor issues with Patch.

Thanks.

Overall I think the basic structure is probably ok.
I'd appreciate it if an actual ARM person took a look.

Oza> +#define GET_REG_VAL(REGCACHE,NO,VAL)  \
Oza> +        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
Oza> +
Oza> +#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
Oza> +        regcache_raw_read_unsigned (REGCACHE, NO, VAL);

I think it is better not to have these macros.  They don't add anything,
but just obscure the underlying implementation.

I don't understand why the "SIGNED" macro is defined as calling a
function named ..._unsigned.

Oza> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
Oza> +do  \
Oza> +  { \
Oza> +    unsigned int reg_len = 0; \
Oza> +    reg_len = LENGTH; \

You might as well coalesce these two lines.

Oza> +    if (reg_len) \
Oza> +      { \
Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Oza> +        while (reg_len) \
Oza> +          { \
Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
Oza> +            reg_len--;  \

I think this could be replaced with memcpy.

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;     /* record length.  */

Wrong indentation.

Oza> +/* ARM instruction record.  
Oza> +contains opcode of current insn and execution state (before entry to 
Oza> +decode_insn() ), 
Oza> +contains list of to-be-modified registers and memory blocks (on return from 
Oza> +decode_insn() ).  */

Wrong formatting.

Oza> +/* checks ARM SBZ and SBO mendatory fields.  */

Capitalize.
This problem appears more than once.

Oza> +  memset(&u_buf, 0, sizeof(u_buf));

Wrong formatting.
This appears a few times too.

Oza> +          printf_unfiltered (_("Process record does not support instruction "
Oza> +                             "0x%0x at address %s.\n"),
Oza> +                             arm_insn_r->arm_insn,
Oza> +                         paddress (arm_insn_r->gdbarch, 

It seems odd that a failure is reported just with a printf.
What is the reason for not throwing an exception?

Oza> +      gdb_assert_not_reached ("no decoding pattern found");

This text makes it sound like this assertion could possibly be reached
somehow.  I didn't track through all the insn decoding logic; but if
this can be triggered by some value (perhaps an invalid instruction)
then it is extremely unfriendly to assert.

Oza> +  struct
Oza> +    {
Oza> +      ULONGEST signed_word;

It is weird that a "signed" word has an unsigned type.
Why is this?

Oza> +      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
Oza> +               that case, we need to go back with previous CPSR and 
Oza> +               Program Counter..  */

No names in comments.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-31 18:05 ` Tom Tromey
@ 2011-06-03  7:44   ` paawan oza
  2011-06-03  7:51   ` paawan oza
  1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-06-03  7:44 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín

Hi Tom,

please find my comments inlined below.

Regards,
Oza.



----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Tue, May 31, 2011 11:34:49 PM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> Fixed some minor issues with Patch.

Thanks.

Overall I think the basic structure is probably ok.
I'd appreciate it if an actual ARM person took a look.

Oza> +#define GET_REG_VAL(REGCACHE,NO,VAL)  \
Oza> +        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
Oza> +
Oza> +#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
Oza> +        regcache_raw_read_unsigned (REGCACHE, NO, VAL);

I think it is better not to have these macros.  They don't add anything,
but just obscure the underlying implementation.

I don't understand why the "SIGNED" macro is defined as calling a
function named ..._unsigned.

Oza:  macors removed and it was a mistake to have unsigned, corrected too.

Oza> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
Oza> +do  \
Oza> +  { \
Oza> +    unsigned int reg_len = 0; \
Oza> +    reg_len = LENGTH; \

You might as well coalesce these two lines.

Oza: done

Oza> +    if (reg_len) \
Oza> +      { \
Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Oza> +        while (reg_len) \
Oza> +          { \
Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
Oza> +            reg_len--;  \

I think this could be replaced with memcpy.

Oza: yes, but just to make the logic look symmetrical with MEM_ALLOC I have kept 
that way.

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;     /* record length.  */

Wrong indentation.

Oza: corrected.

Oza> +/* ARM instruction record.  
Oza> +contains opcode of current insn and execution state (before entry to 
Oza> +decode_insn() ), 
Oza> +contains list of to-be-modified registers and memory blocks (on return 
from 

Oza> +decode_insn() ).  */

Wrong formatting.

Oza: corrected.

Oza> +/* checks ARM SBZ and SBO mendatory fields.  */

Capitalize.
This problem appears more than once.

Oza: Capitalization is taken care in all the comments now.

Oza> +  memset(&u_buf, 0, sizeof(u_buf));

Wrong formatting.
This appears a few times too.

Oza: sizeof (...)   formatting correctedin memset, I am not sure if any other 
formatting you referred to.

Oza> +          printf_unfiltered (_("Process record does not support 
instruction "
Oza> +                             "0x%0x at address %s.\n"),
Oza> +                             arm_insn_r->arm_insn,
Oza> +                         paddress (arm_insn_r->gdbarch, 

It seems odd that a failure is reported just with a printf.
What is the reason for not throwing an exception?

Oza : If you see next line
ret = -1
eventullly gdb record code throws an exception as below.
if (ret < 0)
    error (_("Process record: failed to record execution log."));

Oza> +      gdb_assert_not_reached ("no decoding pattern found");

This text makes it sound like this assertion could possibly be reached
somehow.  I didn't track through all the insn decoding logic; but if
this can be triggered by some value (perhaps an invalid instruction)
then it is extremely unfriendly to assert.

Oza: this code would never be reached, except in the case where ARM changes/adds 
decoding logic to this set of insns.
or compiler is producing faulty code.
both have rare chances.
basically I was looking for throwing assertion with message, and could not find 
macro other than this.
please suggest if any better way to handle.

Oza> +  struct
Oza> +    {
Oza> +      ULONGEST signed_word;

It is weird that a "signed" word has an unsigned type.
Why is this?

oza: turned into LONGEST, corrected now.

Oza> +      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
Oza> +               that case, we need to go back with previous CPSR and 
Oza> +               Program Counter..  */

No names in comments.

Oza: sure, removed. 

execuse me if you have to tell things twice as it is quite a long code base 
where i might have failed to take care of same error at all places.
though I tried best to eliminate duplicate errors.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-31 18:05 ` Tom Tromey
  2011-06-03  7:44   ` paawan oza
@ 2011-06-03  7:51   ` paawan oza
  2011-07-12 21:10     ` Tom Tromey
  1 sibling, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-06-03  7:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín

Hi Tom,

Fixed almost all comments.
any more comments are welcome make this patch ok, if ARM person can have a look 
at it it would be great.

PATCH STARTS
------------------------------------diff -urN arm_orig/arm-linux-tdep.c 
arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-06-03 13:16:35.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1763 @@
                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 = 0; reg_len = LENGTH; \
+    if (reg_len) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
+        while (reg_len) \
+          { \
+            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
+            reg_len--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    unsigned int mem_len = 0; mem_len = LENGTH; \
+    if (mem_len) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (mem_len)); \
+        while (mem_len) \
+          { \
+            MEMS[mem_len - 1].addr = RECORD_BUF[(mem_len * 2) - 1]; \
+            MEMS[mem_len - 1].len = RECORD_BUF[(mem_len * 2) - 2]; \
+            mem_len--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* 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 recors */
+  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 mendatory 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;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      ret = -1;
+      /* Handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      ret = -1;
+      /* Handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      ret = -1;
+      /* Handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      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 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 
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof (u_buf));
+
+  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* Accorindly to high vector configuration PC is set accordingly */
+      /* What if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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_buf[0].unsigned_regval);            
+        if (15 == reg_src1)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* Calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , 
&u_buf[1].unsigned_regval);                        

+        if (15 == reg_src2)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = 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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_data_proc_imm_insn (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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_ld_st_imm_offset_insn (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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof (u_buf));
+  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 (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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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_buf.unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      LONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof (u_buf));
+  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,
+        let us begin 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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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_buf[0].unsigned_regval);
+            regcache_raw_read_unsigned (reg_cache, reg_src2
+                                        , 
&u_buf[1].unsigned_regval);                        

+            if (15 == reg_src2)
+              {
+                /* If R15 was used as Rn, hence current PC+8.  */
+                /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+              }            
+            /* Calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].unsigned_regval + 
u_buf[1].unsigned_regval;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - 
u_buf[0].unsigned_regval;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_buf[0].unsigned_regval);
+            regcache_raw_read_signed (reg_cache, reg_src1
+                                        , &u_buf[0].signed_word);
+            regcache_raw_read_unsigned (reg_cache, reg_src2
+                                        , &u_buf[1].unsigned_regval);   
+            /* Offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* Offset_12 used as index.  */
+                  offset_12 = u_buf[0].unsigned_regval << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> 
shift_imm; 

+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].unsigned_regval, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* This is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+                                                  , &u_buf[1].unsigned_regval);
+                      /* Get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) 
\
+                                    | (u_buf[0].unsigned_regval) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                         | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - 
shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            regcache_raw_read_unsigned (reg_cache, reg_src2
+                                        , &u_buf[1].unsigned_regval); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_handle_ld_st_multiple_insn (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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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 ("Invalid addressing mode for insn");
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* Handle B, BL, BLX(1) insns.  */
+  /* Wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* Handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction "
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;   
+}
+
+/* Handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 

+          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* Accorindly to high vector configuration PC is set accordingly.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also; how?.  */
+      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_handle_swi_insn (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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[8]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[8]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 

+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) 
+            ? arm_handle_insn[insn_id] (arm_record) 
+            : handle_extension_space (arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* Yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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(0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* 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_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* We are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; 
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-06-03  7:51   ` paawan oza
@ 2011-07-12 21:10     ` Tom Tromey
  2011-07-13  3:17       ` chandra krishnappa
                         ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: Tom Tromey @ 2011-07-12 21:10 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb-patches, Petr Hluzín

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.

You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding.  I think we should proceed on the
theory that this is simply not going to happen.

Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code.  I expect
there will be bugs; those can be fixed.

You need a ChangeLog entry.  A patch of this magnitude should also have
a NEWS entry.

Some kind of testing would be good.  Do the existing tests in
gdb.reverse work with your port?  If so then I think that is sufficient

Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \

Just write   unsigned int reg_len = LENGTH;

Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \

Mind the spaces and parens.  Better, use XNEWVEC:

    REGS = XNEWVEC (uint32_t, reg_len);

Oza> +        while (reg_len) \
Oza> +          { \
Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
Oza> +            reg_len--;  \
Oza> +          } \

Just use memcpy.

Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \

The same comments apply for this macro.

Oza> +/* ARM instruction record contains opcode of current insn and execution state 
Oza> (before entry to 

Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks 
Oza> (on return from 

Your email got corrupted.  Usually this is some bad MUA setting.

Oza> +  uint32_t mem_rec_count;       /* No of mem recors */

Typo, "recors"

Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */

Typo, should be "mandatory".

Oza> +  if(!sbo)

Spacing.

Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))

Over-parenthesizing makes the code harder to read.  Please fix this.  I
noticed it in many places.  This specific case should read:

  if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))

Oza> +  memset(&u_buf, 0, sizeof (u_buf));

Spacing.  Just go through the entire patch and fix all the spacing
issues.

I feel like I have mentioned this before.

Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> +                                  , &u_buf[0].unsigned_regval);

What if this does not return REG_VALID?
There are multiple instances of this.

Oza> +      gdb_assert_not_reached ("no decoding pattern found");

It seems wrong to use an assert in this code.  At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction.  An unrecognized instruction can occur
for many reasons, e.g., a bad jump.

Oza> +      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)         
Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))

This reads very oddly.  Is there a particular reason behind the ordering
(if so -- document).  If not, isn't this:

  if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)

There are other odd-looking conditions like this.

Oza> +              default:
Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");

Again, assert seems wrong.

I'm afraid I ran out of steam here.  Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up.  I want this patch to go in, but first it
must comply to the usual gdb standards.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-12 21:10     ` Tom Tromey
@ 2011-07-13  3:17       ` chandra krishnappa
  2011-07-13  5:36         ` paawan oza
  2011-07-13 15:20         ` Tom Tromey
  2011-07-13  6:57       ` paawan oza
       [not found]       ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
  2 siblings, 2 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-07-13  3:17 UTC (permalink / raw)
  To: paawan oza, Tom Tromey; +Cc: gdb-patches, Petr Hluzín

Hi,

I am trying to the test if the existing gdb.reverse works with the ARM porting done by Oza..

I am a learner, and I am taking more time than a average developer to get documentation, read, understand and complete the testing of ARM porting of reversible....


Thanks & Regards,
-Chandra K


--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:

> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "paawan oza" <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 2:29 AM
> >>>>> "Oza" == paawan
> oza <paawan1982@yahoo.com>
> writes:
> 
> Oza> any more comments are welcome make this patch ok,
> if ARM person can
> Oza> have a look at it it would be great.
> 
> You have submitted this patch many times now and nobody has
> commented
> on the details of the ARM decoding.  I think we should
> proceed on the
> theory that this is simply not going to happen.
> 
> Also, I am not as concerned about the correctness of every
> detail as I
> am about the general maintainability and style of the
> code.  I expect
> there will be bugs; those can be fixed.
> 
> You need a ChangeLog entry.  A patch of this magnitude
> should also have
> a NEWS entry.
> 
> Some kind of testing would be good.  Do the existing
> tests in
> gdb.reverse work with your port?  If so then I think
> that is sufficient
> 
> Oza> +    unsigned int reg_len = 0; reg_len =
> LENGTH; \
> 
> Just write   unsigned int reg_len = LENGTH;
> 
> Oza> +        REGS = (uint32_t*)
> xmalloc (sizeof(uint32_t) * (reg_len)); \
> 
> Mind the spaces and parens.  Better, use XNEWVEC:
> 
>     REGS = XNEWVEC (uint32_t, reg_len);
> 
> Oza> +        while (reg_len) \
> Oza> +          { \
> Oza> +           
> REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
> Oza> +           
> reg_len--;  \
> Oza> +          } \
> 
> Just use memcpy.
> 
> Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> 
> The same comments apply for this macro.
> 
> Oza> +/* ARM instruction record contains opcode of
> current insn and execution state 
> Oza> (before entry to 
> 
> Oza> +decode_insn() ), contains list of to-be-modified
> registers and memory blocks 
> Oza> (on return from 
> 
> Your email got corrupted.  Usually this is some bad
> MUA setting.
> 
> Oza> +  uint32_t mem_rec_count;   
>    /* No of mem recors */
> 
> Typo, "recors"
> 
> Oza> +/* Checks ARM SBZ and SBO mendatory fields. 
> */
> 
> Typo, should be "mandatory".
> 
> Oza> +  if(!sbo)
> 
> Spacing.
> 
> Oza> +  if ((3 == opcode1) && (bit
> (arm_insn_r->arm_insn, 4)))
> 
> Over-parenthesizing makes the code harder to read. 
> Please fix this.  I
> noticed it in many places.  This specific case should
> read:
> 
>   if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
> 
> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
> 
> Spacing.  Just go through the entire patch and fix all
> the spacing
> issues.
> 
> I feel like I have mentioned this before.
> 
> Oza> +      regcache_raw_read_unsigned
> (reg_cache, reg_src1
> Oza> +             
>                
>     , &u_buf[0].unsigned_regval);
> 
> What if this does not return REG_VALID?
> There are multiple instances of this.
> 
> Oza> +      gdb_assert_not_reached ("no
> decoding pattern found");
> 
> It seems wrong to use an assert in this code.  At
> least, it is not
> obvious to me that this represents a logic error in gdb as
> opposed to a
> merely unrecognized instruction.  An unrecognized
> instruction can occur
> for many reasons, e.g., a bad jump.
> 
> Oza> +      if ((8 ==
> arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)     
> Oza> +      || (12 ==
> arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> +      || (9 ==
> arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)     
> Oza> +      || (13 ==
> arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)     
>    
> Oza> +      || (0 ==
> arm_insn_r->opcode) || (2 == arm_insn_r->opcode) 
>    
> Oza> +      || (4 ==
> arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> +      || (1 ==
> arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> +      || (5 ==
> arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> 
> This reads very oddly.  Is there a particular reason
> behind the ordering
> (if so -- document).  If not, isn't this:
> 
>   if (arm_insn_r->opcode >= 0 &&
> arm_insn_r->opcode <= 15)
> 
> There are other odd-looking conditions like this.
> 
> Oza> +             
> default:
> Oza> +             
>   gdb_assert_not_reached ("Invalid addressing mode for
> insn");
> 
> Again, assert seems wrong.
> 
> I'm afraid I ran out of steam here.  Please fix all
> the issues already
> noted and look at the rest of the patch with a critical eye
> to see what
> else should be cleaned up.  I want this patch to go
> in, but first it
> must comply to the usual gdb standards.
> 
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-13  3:17       ` chandra krishnappa
@ 2011-07-13  5:36         ` paawan oza
  2011-07-13 15:20         ` Tom Tromey
  1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-07-13  5:36 UTC (permalink / raw)
  To: chandra krishnappa, Tom Tromey; +Cc: gdb-patches, Petr Hluzín

I appreciate your effort on this Chandra K; will be sending you updated patch 
with Tom's comments fixed.
thanks for you work and time.
Oza.



----- Original Message ----
From: chandra krishnappa <chandra_roadking@yahoo.com>
To: paawan oza <paawan1982@yahoo.com>; Tom Tromey <tromey@redhat.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wed, July 13, 2011 7:33:50 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

Hi,

I am trying to the test if the existing gdb.reverse works with the ARM porting 
done by Oza..

I am a learner, and I am taking more time than a average developer to get 
documentation, read, understand and complete the testing of ARM porting of 
reversible....


Thanks & Regards,
-Chandra K


--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:

> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "paawan oza" <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 2:29 AM
> >>>>> "Oza" == paawan
> oza <paawan1982@yahoo.com>
> writes:
> 
> Oza> any more comments are welcome make this patch ok,
> if ARM person can
> Oza> have a look at it it would be great.
> 
> You have submitted this patch many times now and nobody has
> commented
> on the details of the ARM decoding.  I think we should
> proceed on the
> theory that this is simply not going to happen.
> 
> Also, I am not as concerned about the correctness of every
> detail as I
> am about the general maintainability and style of the
> code.  I expect
> there will be bugs; those can be fixed.
> 
> You need a ChangeLog entry.  A patch of this magnitude
> should also have
> a NEWS entry.
> 
> Some kind of testing would be good.  Do the existing
> tests in
> gdb.reverse work with your port?  If so then I think
> that is sufficient
> 
> Oza> +    unsigned int reg_len = 0; reg_len =
> LENGTH; \
> 
> Just write   unsigned int reg_len = LENGTH;
> 
> Oza> +        REGS = (uint32_t*)
> xmalloc (sizeof(uint32_t) * (reg_len)); \
> 
> Mind the spaces and parens.  Better, use XNEWVEC:
> 
>     REGS = XNEWVEC (uint32_t, reg_len);
> 
> Oza> +        while (reg_len) \
> Oza> +          { \
> Oza> +           
> REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
> Oza> +           
> reg_len--;  \
> Oza> +          } \
> 
> Just use memcpy.
> 
> Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> 
> The same comments apply for this macro.
> 
> Oza> +/* ARM instruction record contains opcode of
> current insn and execution state 
> Oza> (before entry to 
> 
> Oza> +decode_insn() ), contains list of to-be-modified
> registers and memory blocks 
> Oza> (on return from 
> 
> Your email got corrupted.  Usually this is some bad
> MUA setting.
> 
> Oza> +  uint32_t mem_rec_count;   
>    /* No of mem recors */
> 
> Typo, "recors"
> 
> Oza> +/* Checks ARM SBZ and SBO mendatory fields. 
> */
> 
> Typo, should be "mandatory".
> 
> Oza> +  if(!sbo)
> 
> Spacing.
> 
> Oza> +  if ((3 == opcode1) && (bit
> (arm_insn_r->arm_insn, 4)))
> 
> Over-parenthesizing makes the code harder to read. 
> Please fix this.  I
> noticed it in many places.  This specific case should
> read:
> 
>   if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
> 
> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
> 
> Spacing.  Just go through the entire patch and fix all
> the spacing
> issues.
> 
> I feel like I have mentioned this before.
> 
> Oza> +      regcache_raw_read_unsigned
> (reg_cache, reg_src1
> Oza> +             
>                
>     , &u_buf[0].unsigned_regval);
> 
> What if this does not return REG_VALID?
> There are multiple instances of this.
> 
> Oza> +      gdb_assert_not_reached ("no
> decoding pattern found");
> 
> It seems wrong to use an assert in this code.  At
> least, it is not
> obvious to me that this represents a logic error in gdb as
> opposed to a
> merely unrecognized instruction.  An unrecognized
> instruction can occur
> for many reasons, e.g., a bad jump.
> 
> Oza> +      if ((8 ==
> arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)     
> Oza> +      || (12 ==
> arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> +      || (9 ==
> arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)     
> Oza> +      || (13 ==
> arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)     
>    
> Oza> +      || (0 ==
> arm_insn_r->opcode) || (2 == arm_insn_r->opcode) 
>    
> Oza> +      || (4 ==
> arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> +      || (1 ==
> arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> +      || (5 ==
> arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> 
> This reads very oddly.  Is there a particular reason
> behind the ordering
> (if so -- document).  If not, isn't this:
> 
>   if (arm_insn_r->opcode >= 0 &&
> arm_insn_r->opcode <= 15)
> 
> There are other odd-looking conditions like this.
> 
> Oza> +             
> default:
> Oza> +             
>   gdb_assert_not_reached ("Invalid addressing mode for
> insn");
> 
> Again, assert seems wrong.
> 
> I'm afraid I ran out of steam here.  Please fix all
> the issues already
> noted and look at the rest of the patch with a critical eye
> to see what
> else should be cleaned up.  I want this patch to go
> in, but first it
> must comply to the usual gdb standards.
> 
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-12 21:10     ` Tom Tromey
  2011-07-13  3:17       ` chandra krishnappa
@ 2011-07-13  6:57       ` paawan oza
       [not found]       ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
  2 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-07-13  6:57 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín

Thanks for your comments; I think I will need to scrutinize the overall patch 
and make it correct with your comments.
I understand this patch has been lying around,but as Chandra K is working on the 
port of gdb.reverse, we will see the results soon.

Regards,
Oza.



----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wed, July 13, 2011 2:29:36 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.

You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding.  I think we should proceed on the
theory that this is simply not going to happen.

Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code.  I expect
there will be bugs; those can be fixed.

You need a ChangeLog entry.  A patch of this magnitude should also have
a NEWS entry.

Some kind of testing would be good.  Do the existing tests in
gdb.reverse work with your port?  If so then I think that is sufficient

Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \

Just write   unsigned int reg_len = LENGTH;

Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \

Mind the spaces and parens.  Better, use XNEWVEC:

    REGS = XNEWVEC (uint32_t, reg_len);

Oza> +        while (reg_len) \
Oza> +          { \
Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
Oza> +            reg_len--;  \
Oza> +          } \

Just use memcpy.

Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \

The same comments apply for this macro.

Oza> +/* ARM instruction record contains opcode of current insn and execution 
state 

Oza> (before entry to 

Oza> +decode_insn() ), contains list of to-be-modified registers and memory 
blocks 

Oza> (on return from 

Your email got corrupted.  Usually this is some bad MUA setting.

Oza> +  uint32_t mem_rec_count;       /* No of mem recors */

Typo, "recors"

Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */

Typo, should be "mandatory".

Oza> +  if(!sbo)

Spacing.

Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))

Over-parenthesizing makes the code harder to read.  Please fix this.  I
noticed it in many places.  This specific case should read:

  if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))

Oza> +  memset(&u_buf, 0, sizeof (u_buf));

Spacing.  Just go through the entire patch and fix all the spacing
issues.

I feel like I have mentioned this before.

Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> +                                  , &u_buf[0].unsigned_regval);

What if this does not return REG_VALID?
There are multiple instances of this.

Oza> +      gdb_assert_not_reached ("no decoding pattern found");

It seems wrong to use an assert in this code.  At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction.  An unrecognized instruction can occur
for many reasons, e.g., a bad jump.

Oza> +      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)        
Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))

This reads very oddly.  Is there a particular reason behind the ordering
(if so -- document).  If not, isn't this:

  if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)

There are other odd-looking conditions like this.

Oza> +              default:
Oza> +                gdb_assert_not_reached ("Invalid addressing mode for 
insn");

Again, assert seems wrong.

I'm afraid I ran out of steam here.  Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up.  I want this patch to go in, but first it
must comply to the usual gdb standards.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-13  3:17       ` chandra krishnappa
  2011-07-13  5:36         ` paawan oza
@ 2011-07-13 15:20         ` Tom Tromey
  2011-07-14  4:49           ` chandra krishnappa
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-07-13 15:20 UTC (permalink / raw)
  To: chandra krishnappa; +Cc: paawan oza, gdb-patches, Petr Hluzín

>>>>> "Chandra" == chandra krishnappa <chandra_roadking@yahoo.com> writes:

Chandra> I am trying to the test if the existing gdb.reverse works with the ARM
Chandra> porting done by Oza..

Great, thank you.

Chandra> I am a learner, and I am taking more time than a average developer to
Chandra> get documentation, read, understand and complete the testing of ARM
Chandra> porting of reversible....

No problem.  Feel free to send email if you have questions, or join us
on irc.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-13 15:20         ` Tom Tromey
@ 2011-07-14  4:49           ` chandra krishnappa
  2011-07-14 15:01             ` Yao Qi
  0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-07-14  4:49 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb-patches, Petr Hluzín


two questions... rather I would derive directions out of it....

1. what is the common time I can find you and Oza online or active on IRC?
2. gdb test development active members, with whom I may seek help??

Thanks & Regards,
-Chandra K


--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:

> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "chandra krishnappa" <chandra_roadking@yahoo.com>
> Cc: "paawan oza" <paawan1982@yahoo.com>, gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 7:29 PM
> >>>>> "Chandra" ==
> chandra krishnappa <chandra_roadking@yahoo.com>
> writes:
> 
> Chandra> I am trying to the test if the existing
> gdb.reverse works with the ARM
> Chandra> porting done by Oza..
> 
> Great, thank you.
> 
> Chandra> I am a learner, and I am taking more time than
> a average developer to
> Chandra> get documentation, read, understand and
> complete the testing of ARM
> Chandra> porting of reversible....
> 
> No problem.  Feel free to send email if you have
> questions, or join us
> on irc.
> 
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-07-14  4:49           ` chandra krishnappa
@ 2011-07-14 15:01             ` Yao Qi
  0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-07-14 15:01 UTC (permalink / raw)
  To: gdb-patches

On 07/14/2011 09:39 AM, chandra krishnappa wrote:
> 2. gdb test development active members, with whom I may seek help??

You may have a look at this page about writing test cases for gdb
http://sourceware.org/gdb/wiki/GDBTestcaseCookbook

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]       ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
@ 2011-09-19  7:37         ` paawan oza
  2011-09-22 17:12           ` oza Pawandeep
  2011-10-14 20:13           ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
  0 siblings, 2 replies; 128+ messages in thread
From: paawan oza @ 2011-09-19  7:37 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa



Hi all,

Sorry for delay in fixing review comments. 

Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.

PATCH STARTS
----------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address
(gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN
arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,1769 @@
                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)
+
+
+/* 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;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if (!opcode1 && (9 == opcode2))
+    {
+      ret = -1;
+      /* Handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+   
{
+      ret = -1;
+      /* Handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+                 && bit (arm_insn_r->arm_insn, 4))
+    {
+      ret = -1;
+      /* Handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+    {
+      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 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 
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t
record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+
+  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* Accorindly to high vector configuration PC is set accordingly */
+      /* What if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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_buf[0].unsigned_regval);            
+        if (15 == reg_src1)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) |
immed_low;
+        /* Calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count =
1;
+      }
+    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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);                        
+        if (15 == reg_src2)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+         
}            
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+       
record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+         
}
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = 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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+       
else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+     
}
+    /* DSP insns  (e.g. LDRD)  TBD.  */
+  }  
+  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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 (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
+    {
+      /* 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_buf.unsigned_regval);
+      /* U == 1 */
+      if (bit (arm_insn_r->arm_insn, 23))
+        {   
+          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+        }
+      else
+        {
+         tgt_mem_addr = u_buf.unsigned_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:
+              
+            /* STR insn, STRT insn.  */
+            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:
+            /* STRB insn, STRBT insn.  */
+            record_buf_mem[0] = 1;    
+          break;   
+
+          default:
+            return -1;
+          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      LONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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,
+        let us begin 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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache,
reg_src2
+                                      , &u_buf[1].unsigned_regval);                        
+          if (15 == reg_src2)
+            {
+              /* If R15 was used as Rn, hence current PC+8.  */
+              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+              u_buf[0].unsigned_regval =
u_buf[0].unsigned_regval + 8;
+            }            
+          /* Calculate target store address, Rn +/- Rm, register offset.  */
+          /* U == 1.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[0].unsigned_regval + 
+                             u_buf[1].unsigned_regval;
+           
}
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval - 
+                             u_buf[0].unsigned_regval;
+            }            
+
+          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:
+                /* STR insn, STRT insn.  */
+                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:
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+             
default:
+                return -1;
+              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_buf[0].unsigned_regval);
+          regcache_raw_read_signed (reg_cache, reg_src1
+                                      ,
&u_buf[0].signed_word);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);   
+          /* Offset_12 used as shift.  */
+          switch (offset_12)
+            {
+              case 0:
+                /* Offset_12 used as index. 
*/
+                offset_12 = u_buf[0].unsigned_regval << shift_imm;
+              break;
+              
+              case 1:
+                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm; 
+              break;
+              
+              case 2:
+                if
(!shift_imm)
+                  {
+                    if (bit (u_buf[0].unsigned_regval, 31))
+                      {
+                        offset_12 = 0xFFFFFFFF;
+                      }
+                   
else
+                      {
+                        offset_12 = 0;
+                      }
+                  }
+                else
+                  {
+                    /* This is arithmetic shift. 
*/
+                    offset_12 = u_buf[0].signed_word >> shift_imm;
+                  }
+                break;  
+                
+              case 3:
+                if (!shift_imm)
+                  {
+                    regcache_raw_read_unsigned (reg_cache,
ARM_PS_REGNUM
+                                                , &u_buf[1].unsigned_regval);
+                    /* Get C flag value and shift it by 31.  */
+                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+                                  | (u_buf[0].unsigned_regval) >>
1);
+                  }
+                else
+                  {                      
+                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
+                 
}
+              break;
+
+              default:
+                return -1;
+              break;
+            }      
+
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval); 
+          /* U == 1
*/
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_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 0:
+          case 4:  
+                /* STR insn, STRT insn.  */
+                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:
+                /* STRB insn, STRBT insn. 
*/
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                return -1;
+              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0,
sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch (addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
+          return -1;
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* Handle B, BL, BLX(1) insns.  */
+  /* Wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* Handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction
"
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record
support\n"));
+            return -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 -1;   
+}
+
+/* Handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache,
reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 
+          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+ 
struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* Accorindly to high vector configuration PC is set accordingly.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also; how?.  */
+      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_handle_swi_insn (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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+ 
uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
+  static int (*const arm_handle_insn[8]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100. 
*/
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
+  static int (*const thumb_handle_insn[8]) 
+                                         
(insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+     
thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 
+      arm_record->cond = bits (arm_record->arm_insn, 28,
31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) 
+            ? arm_handle_insn[insn_id] (arm_record) 
+            : handle_extension_space (arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  */
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* Yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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 (0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* 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_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* We are decoding arm
insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
+           
{
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if
(arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct
gdbarch *gdbarch, 
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified




________________________________
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wednesday, 13 July 2011 1:29 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.

You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding.  I think we should proceed on the
theory that this is simply not going to happen.

Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code.  I expect
there will be bugs; those can be fixed.

You need a ChangeLog entry.  A patch of this magnitude
should also have
a NEWS entry.

Some kind of testing would be good.  Do the existing tests in
gdb.reverse work with your port?  If so then I think that is sufficient

Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \

Just write   unsigned int reg_len = LENGTH;

Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \

Mind the spaces and parens.  Better, use XNEWVEC:

    REGS = XNEWVEC (uint32_t, reg_len);

Oza> +        while (reg_len) \
Oza> +          { \
Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
Oza> +            reg_len--;  \
Oza> +          } \

Just use memcpy.

Oza> +#define
MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \

The same comments apply for this macro.

Oza> +/* ARM instruction record contains opcode of current insn and execution state 
Oza> (before entry to 

Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks 
Oza> (on return from 

Your email got corrupted.  Usually this is some bad MUA setting.

Oza> +  uint32_t mem_rec_count;       /* No of mem recors */

Typo, "recors"

Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */

Typo, should be "mandatory".

Oza> +  if(!sbo)

Spacing.

Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))

Over-parenthesizing makes the code harder to read.  Please fix this.  I
noticed it in many places.  This specific case should read:

  if (3 == opcode1 && bit
(arm_insn_r->arm_insn, 4))

Oza> +  memset(&u_buf, 0, sizeof (u_buf));

Spacing.  Just go through the entire patch and fix all the spacing
issues.

I feel like I have mentioned this before.

Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> +                                  , &u_buf[0].unsigned_regval);

What if this does not return REG_VALID?
There are multiple instances of this.

Oza> +      gdb_assert_not_reached ("no decoding pattern found");

It seems wrong to use an assert in this code.  At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction.  An unrecognized instruction can occur
for many reasons, e.g., a bad jump.

Oza> +   
  if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)        
Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))

This reads very oddly.  Is there a particular reason behind the ordering
(if so -- document).  If not, isn't
this:

  if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)

There are other odd-looking conditions like this.

Oza> +              default:
Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");

Again, assert seems wrong.

I'm afraid I ran out of steam here.  Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up.  I want this patch to go in, but first it
must comply to the usual gdb standards.

Tom         

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-09-19  7:37         ` paawan oza
@ 2011-09-22 17:12           ` oza Pawandeep
  2011-09-27  6:52             ` oza Pawandeep
  2011-10-14 20:13           ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-09-22 17:12 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches, Petr Hluzín, chandra krishnappa

Hello Chandra,

Let me know if you are planning to do anymore basic testing on this patch.

@Tom: is it possible to get this patch move in, of course I have been
keen on any review comment; but it has been lying around for a long
time.
and I would like to move to phase-3 implementation then.

Regards,
Oza.

On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>
>
> Hi all,
>
> Sorry for delay in fixing review comments.
>
> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>
> PATCH STARTS
> ----------------------------------
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
>    set_gdbarch_fetch_tls_load_module_address
> (gdbarch,
>                                               svr4_fetch_objfile_link_map);
>
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>    tramp_frame_prepend_unwinder (gdbarch,
>                  &arm_linux_sigreturn_tramp_frame);
>    tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
>
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff -urN
> arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
>
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
>
>  static int arm_debug;
> @@ -8821,3 +8823,1769 @@
>                 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)
> +
> +
> +/* 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;
> +}
> +
> +/* Handling ARM extension space insns.  */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> +  uint32_t ret = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  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.  */
> +    }
> +
> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> +  if (!opcode1 && (9 == opcode2))
> +    {
> +      ret = -1;
> +      /* Handle arithmetic insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> +
> {
> +      ret = -1;
> +      /* Handle control insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
> +                 && bit (arm_insn_r->arm_insn, 4))
> +    {
> +      ret = -1;
> +      /* Handle load/store insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> +    {
> +      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 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
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
> +{
> +  struct regcache *reg_cache = arm_insn_r->regcache;
> +  uint32_t
> record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +
> +  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;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +
> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
> +      /* Accorindly to high vector configuration PC is set accordingly */
> +      /* What if 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)
> +           let us begin according to addressing modes for store insns
> +           STRH insn, addresing modes are taken following.  */
> +    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_buf[0].unsigned_regval);
> +        if (15 == reg_src1)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +          }
> +        offset_8 = (immed_high << 4) |
> immed_low;
> +        /* Calculate target store address.  */
> +        if (14 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count =
> 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);
> +        if (15 == reg_src2)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +
> }
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if (12 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }
> +
> record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +
> }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = 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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +
> else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> +        arm_insn_r->reg_rec_count = 1;
> +
> }
> +    /* DSP insns  (e.g. LDRD)  TBD.  */
> +  }
> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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 (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
> +    {
> +      /* 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_buf.unsigned_regval);
> +      /* U == 1 */
> +      if (bit (arm_insn_r->arm_insn, 23))
> +        {
> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
> +        }
> +      else
> +        {
> +         tgt_mem_addr = u_buf.unsigned_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:
> +
> +            /* STR insn, STRT insn.  */
> +            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:
> +            /* STRB insn, STRBT insn.  */
> +            record_buf_mem[0] = 1;
> +          break;
> +
> +          default:
> +            return -1;
> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      LONGEST signed_word;
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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,
> +        let us begin 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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          if (15 == reg_src2)
> +            {
> +              /* If R15 was used as Rn, hence current PC+8.  */
> +              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
> +              u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +            }
> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
> +          /* U == 1.  */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr = u_buf[0].unsigned_regval +
> +                             u_buf[1].unsigned_regval;
> +
> }
> +          else
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_regval -
> +                             u_buf[0].unsigned_regval;
> +            }
> +
> +          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:
> +                /* STR insn, STRT insn.  */
> +                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:
> +                /* STRB insn, STRBT insn.  */
> +                record_buf_mem[0] = 1;
> +              break;
> +
> +
> default:
> +                return -1;
> +              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_buf[0].unsigned_regval);
> +          regcache_raw_read_signed (reg_cache, reg_src1
> +                                      ,
> &u_buf[0].signed_word);
> +          regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          /* Offset_12 used as shift.  */
> +          switch (offset_12)
> +            {
> +              case 0:
> +                /* Offset_12 used as index.
> */
> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
> +              break;
> +
> +              case 1:
> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
> +              break;
> +
> +              case 2:
> +                if
> (!shift_imm)
> +                  {
> +                    if (bit (u_buf[0].unsigned_regval, 31))
> +                      {
> +                        offset_12 = 0xFFFFFFFF;
> +                      }
> +
> else
> +                      {
> +                        offset_12 = 0;
> +                      }
> +                  }
> +                else
> +                  {
> +                    /* This is arithmetic shift.
> */
> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
> +                  }
> +                break;
> +
> +              case 3:
> +                if (!shift_imm)
> +                  {
> +                    regcache_raw_read_unsigned (reg_cache,
> ARM_PS_REGNUM
> +                                                , &u_buf[1].unsigned_regval);
> +                    /* Get C flag value and shift it by 31.  */
> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
> +                                  | (u_buf[0].unsigned_regval) >>
> 1);
> +                  }
> +                else
> +                  {
> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
> +                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
> +
> }
> +              break;
> +
> +              default:
> +                return -1;
> +              break;
> +            }
> +
> +          regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          /* U == 1
> */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
> +            }
> +          else
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_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 0:
> +          case 4:
> +                /* STR insn, STRT insn.  */
> +                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:
> +                /* STRB insn, STRBT insn.
> */
> +                record_buf_mem[0] = 1;
> +              break;
> +
> +              default:
> +                return -1;
> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
> +  uint32_t start_address = 0, index = 0;
> +  uint32_t record_buf[24], record_buf_mem[48];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0,
> sizeof(u_buf));
> +
> +  /* 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 optmization.  */
> +
> +  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 optmization.  */
> +        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_buf[0].unsigned_regval);
> +    while (register_bits)
> +      {
> +        if (register_bits & 0x00000001)
> +           register_count++;
> +        register_bits = register_bits >> 1;
> +      }
> +
> +    switch (addr_mode)
> +      {
> +        /* Decrement after.  */
> +        case 0:
> +          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
> +          return -1;
> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> +  uint32_t record_buf[8];
> +
> +  /* Handle B, BL, BLX(1) insns.  */
> +  /* Wihtout optmization we save link register,
> +        CSPR for the insn which changes T bit.  */
> +  record_buf[0] = ARM_PS_REGNUM;
> +  record_buf[1] = ARM_LR_REGNUM;
> +  arm_insn_r->reg_rec_count = 2;
> +
> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +
> +  return 0;
> +}
> +
> +/* Handling opcode 110 insns.  */
> +
> +static int
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> +  printf_unfiltered (_("Process record does not support instruction
> "
> +                     "0x%0x at address %s.\n"),
> +                     arm_insn_r->arm_insn,
> +                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
> +
> +   return -1;
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int
> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
> +{
> +   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> +   struct regcache *reg_cache = arm_insn_r->regcache;
> +
> +   uint32_t shift_imm = 0;
> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
> 0;
> +   uint32_t start_address = 0;
> +
> +   /* 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)
> +          {
> +            tdep->arm_swi_record(reg_cache);
> +          }
> +        else
> +          {
> +            printf_unfiltered (_("no syscall record
> support\n"));
> +            return -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 -1;
> +}
> +
> +/* Handling opcode 000 insns.  */
> +
> +static int
> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_src1 = 0;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +      gdb_byte buf[4];
> +    } u_buf[2];
> +
> +  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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +
> struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
> +      record_buf_mem[0] = 2;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> +  struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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.  */
> +      /* Accorindly to high vector configuration PC is set accordingly.  */
> +      /* FIX ME ?  what if 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;
> +      thumb_insn_r->reg_rec_count = 2;
> +      /* Save SPSR also; how?.  */
> +      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_handle_swi_insn (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 reg_val1 = 0;
> +  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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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)
> +          {
> +            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 0;
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int
> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +
> uint32_t opcode = 0, immed_5 = 0;
> +
> +
> +  /* BL , 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;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
> +  static int (*const arm_handle_insn[8])
> +                                      (insn_decode_record*) =
> +  {
> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
> +      arm_handle_ld_st_multiple_insn,           /* 100.
> */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */
> +  };
> +
> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
> +  static int (*const thumb_handle_insn[8])
> +
> (insn_decode_record*) =
> +  { \
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
> +      thumb_handle_misc_insn,                  /* 101.  */
> +
> thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
> +    {
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> +      arm_record->cond = bits (arm_record->arm_insn, 28,
> 31);
> +      insn_id = bits (arm_record->arm_insn, 25, 27);
> +      ret = (0x0F != arm_record->cond)
> +            ? arm_handle_insn[insn_id] (arm_record)
> +            : handle_extension_space (arm_record);
> +    }
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes, following field is useless.  */
> +      arm_record->cond = -1;
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> +
> +      insn_id = bits (arm_record->arm_insn, 13, 15);
> +      ret = thumb_handle_insn[insn_id] (arm_record);
> +    }
> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* Yet to be implemented; handle thumb2 part here.  */
> +      printf_unfiltered (_("Process record does not support 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 (0);
> +    }
> +
> +  return ret;
> +}
> +
> +/* 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;
> +  ULONGEST t_bit = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* 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_buf.unsigned_regval);
> +
> +  if (!(u_buf.unsigned_regval & t_bit))
> +    {
> +      /* We are decoding arm
> insn.  */
> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> +    }
> +  else
> +    {
> +      /* We are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
> +    }
> +
> +  if (0 == ret)
> +    {
> +      /* Record registers.  */
> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
> +
> {
> +              if (record_arch_list_add_reg (arm_record.regcache \
> +                                           , (arm_record.arm_regs[no_of_rec])))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if
> (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +
> +  return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
>    /* Return the expected next PC if FRAME is stopped at a syscall
>       instruction.  */
>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
>
>  /* Structures used for displaced stepping.  */
> @@ -331,6 +334,8 @@
>     instruction?  */
>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct
> gdbarch *gdbarch,
> +                               struct regcache *regcache, CORE_ADDR addr);
>  /* Functions exported from armbsd-tdep.h.  */
>
>  /* Return the appropriate register set for the core section identified
>
>
>
>
> ________________________________
> From: Tom Tromey <tromey@redhat.com>
> To: paawan oza <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
> Sent: Wednesday, 13 July 2011 1:29 AM
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>
>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>
> Oza> any more comments are welcome make this patch ok, if ARM person can
> Oza> have a look at it it would be great.
>
> You have submitted this patch many times now and nobody has commented
> on the details of the ARM decoding.  I think we should proceed on the
> theory that this is simply not going to happen.
>
> Also, I am not as concerned about the correctness of every detail as I
> am about the general maintainability and style of the code.  I expect
> there will be bugs; those can be fixed.
>
> You need a ChangeLog entry.  A patch of this magnitude
> should also have
> a NEWS entry.
>
> Some kind of testing would be good.  Do the existing tests in
> gdb.reverse work with your port?  If so then I think that is sufficient
>
> Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>
> Just write   unsigned int reg_len = LENGTH;
>
> Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>
> Mind the spaces and parens.  Better, use XNEWVEC:
>
>     REGS = XNEWVEC (uint32_t, reg_len);
>
> Oza> +        while (reg_len) \
> Oza> +          { \
> Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
> Oza> +            reg_len--;  \
> Oza> +          } \
>
> Just use memcpy.
>
> Oza> +#define
> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>
> The same comments apply for this macro.
>
> Oza> +/* ARM instruction record contains opcode of current insn and execution state
> Oza> (before entry to
>
> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
> Oza> (on return from
>
> Your email got corrupted.  Usually this is some bad MUA setting.
>
> Oza> +  uint32_t mem_rec_count;       /* No of mem recors */
>
> Typo, "recors"
>
> Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */
>
> Typo, should be "mandatory".
>
> Oza> +  if(!sbo)
>
> Spacing.
>
> Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>
> Over-parenthesizing makes the code harder to read.  Please fix this.  I
> noticed it in many places.  This specific case should read:
>
>   if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
>
> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
>
> Spacing.  Just go through the entire patch and fix all the spacing
> issues.
>
> I feel like I have mentioned this before.
>
> Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
> Oza> +                                  , &u_buf[0].unsigned_regval);
>
> What if this does not return REG_VALID?
> There are multiple instances of this.
>
> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>
> It seems wrong to use an assert in this code.  At least, it is not
> obvious to me that this represents a logic error in gdb as opposed to a
> merely unrecognized instruction.  An unrecognized instruction can occur
> for many reasons, e.g., a bad jump.
>
> Oza> +
>   if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
> Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>
> This reads very oddly.  Is there a particular reason behind the ordering
> (if so -- document).  If not, isn't
> this:
>
>   if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>
> There are other odd-looking conditions like this.
>
> Oza> +              default:
> Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");
>
> Again, assert seems wrong.
>
> I'm afraid I ran out of steam here.  Please fix all the issues already
> noted and look at the rest of the patch with a critical eye to see what
> else should be cleaned up.  I want this patch to go in, but first it
> must comply to the usual gdb standards.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-09-22 17:12           ` oza Pawandeep
@ 2011-09-27  6:52             ` oza Pawandeep
  2011-10-06 18:01               ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-09-27  6:52 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches, Petr Hluzín

Hi Tom,

What do you think about the patch to be ready to to move in <phase_2> ?
Any more comments are welcome from ARM specific community here.
most of the review comments from Michael, Petr, Tom and other folks
have been implemented.

Regards,
Oza.

On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hello Chandra,
>
> Let me know if you are planning to do anymore basic testing on this patch.
>
> @Tom: is it possible to get this patch move in, of course I have been
> keen on any review comment; but it has been lying around for a long
> time.
> and I would like to move to phase-3 implementation then.
>
> Regards,
> Oza.
>
> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>
>>
>> Hi all,
>>
>> Sorry for delay in fixing review comments.
>>
>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>
>> PATCH STARTS
>> ----------------------------------
>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
>> @@ -1025,6 +1025,9 @@
>>    set_gdbarch_fetch_tls_load_module_address
>> (gdbarch,
>>                                               svr4_fetch_objfile_link_map);
>>
>> +  /* Enable process record.  */
>> +  set_gdbarch_process_record (gdbarch, arm_process_record);
>> +
>>    tramp_frame_prepend_unwinder (gdbarch,
>>                  &arm_linux_sigreturn_tramp_frame);
>>    tramp_frame_prepend_unwinder (gdbarch,
>> @@ -1054,6 +1057,8 @@
>>
>>
>>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>> +
>> +  tdep->arm_swi_record = NULL;
>>  }
>>
>>  /* Provide a prototype to silence -Wmissing-prototypes.  */
>> diff -urN
>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
>> @@ -55,6 +55,8 @@
>>  #include "gdb_assert.h"
>>  #include "vec.h"
>>
>> +#include "record.h"
>> +
>>  #include "features/arm-with-m.c"
>>
>>  static int arm_debug;
>> @@ -8821,3 +8823,1769 @@
>>                 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)
>> +
>> +
>> +/* 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;
>> +}
>> +
>> +/* Handling ARM extension space insns.  */
>> +
>> +static int
>> +handle_extension_space (insn_decode_record *arm_insn_r)
>> +{
>> +  uint32_t ret = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0;
>> +
>> +  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.  */
>> +    }
>> +
>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> +  if (!opcode1 && (9 == opcode2))
>> +    {
>> +      ret = -1;
>> +      /* Handle arithmetic insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>> +
>> {
>> +      ret = -1;
>> +      /* Handle control insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>> +                 && bit (arm_insn_r->arm_insn, 4))
>> +    {
>> +      ret = -1;
>> +      /* Handle load/store insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>> +    {
>> +      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 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
>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +  uint32_t
>> record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +
>> +  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;
>> +
>> +  memset (&u_buf, 0, sizeof (u_buf));
>> +
>> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
>> +      /* Accorindly to high vector configuration PC is set accordingly */
>> +      /* What if 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)
>> +           let us begin according to addressing modes for store insns
>> +           STRH insn, addresing modes are taken following.  */
>> +    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_buf[0].unsigned_regval);
>> +        if (15 == reg_src1)
>> +          {
>> +            /* If R15 was used as Rn, hence current PC+8.  */
>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>> +          }
>> +        offset_8 = (immed_high << 4) |
>> immed_low;
>> +        /* Calculate target store address.  */
>> +        if (14 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count =
>> 1;
>> +      }
>> +    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_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>> +                                    , &u_buf[1].unsigned_regval);
>> +        if (15 == reg_src2)
>> +          {
>> +            /* If R15 was used as Rn, hence current PC+8.  */
>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>> +
>> }
>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>> +        if (12 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>> +          }
>> +
>> record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +      }
>> +    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_buf[0].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>> +
>> }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = 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_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>> +                                    , &u_buf[1].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>> +          }
>> +
>> else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>> +        arm_insn_r->reg_rec_count = 1;
>> +
>> }
>> +    /* DSP insns  (e.g. LDRD)  TBD.  */
>> +  }
>> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  memset (&u_buf, 0, sizeof (u_buf));
>> +  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 (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
>> +    {
>> +      /* 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_buf.unsigned_regval);
>> +      /* U == 1 */
>> +      if (bit (arm_insn_r->arm_insn, 23))
>> +        {
>> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>> +        }
>> +      else
>> +        {
>> +         tgt_mem_addr = u_buf.unsigned_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:
>> +
>> +            /* STR insn, STRT insn.  */
>> +            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:
>> +            /* STRB insn, STRBT insn.  */
>> +            record_buf_mem[0] = 1;
>> +          break;
>> +
>> +          default:
>> +            return -1;
>> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      LONGEST signed_word;
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset (&u_buf, 0, sizeof (u_buf));
>> +  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,
>> +        let us begin 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_buf[0].unsigned_regval);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                      , &u_buf[1].unsigned_regval);
>> +          if (15 == reg_src2)
>> +            {
>> +              /* If R15 was used as Rn, hence current PC+8.  */
>> +              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
>> +              u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +            }
>> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
>> +          /* U == 1.  */
>> +          if (bit (arm_insn_r->arm_insn, 23))
>> +            {
>> +              tgt_mem_addr = u_buf[0].unsigned_regval +
>> +                             u_buf[1].unsigned_regval;
>> +
>> }
>> +          else
>> +            {
>> +              tgt_mem_addr = u_buf[1].unsigned_regval -
>> +                             u_buf[0].unsigned_regval;
>> +            }
>> +
>> +          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:
>> +                /* STR insn, STRT insn.  */
>> +                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:
>> +                /* STRB insn, STRBT insn.  */
>> +                record_buf_mem[0] = 1;
>> +              break;
>> +
>> +
>> default:
>> +                return -1;
>> +              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_buf[0].unsigned_regval);
>> +          regcache_raw_read_signed (reg_cache, reg_src1
>> +                                      ,
>> &u_buf[0].signed_word);
>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>> +                                      , &u_buf[1].unsigned_regval);
>> +          /* Offset_12 used as shift.  */
>> +          switch (offset_12)
>> +            {
>> +              case 0:
>> +                /* Offset_12 used as index.
>> */
>> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
>> +              break;
>> +
>> +              case 1:
>> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>> +              break;
>> +
>> +              case 2:
>> +                if
>> (!shift_imm)
>> +                  {
>> +                    if (bit (u_buf[0].unsigned_regval, 31))
>> +                      {
>> +                        offset_12 = 0xFFFFFFFF;
>> +                      }
>> +
>> else
>> +                      {
>> +                        offset_12 = 0;
>> +                      }
>> +                  }
>> +                else
>> +                  {
>> +                    /* This is arithmetic shift.
>> */
>> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
>> +                  }
>> +                break;
>> +
>> +              case 3:
>> +                if (!shift_imm)
>> +                  {
>> +                    regcache_raw_read_unsigned (reg_cache,
>> ARM_PS_REGNUM
>> +                                                , &u_buf[1].unsigned_regval);
>> +                    /* Get C flag value and shift it by 31.  */
>> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>> +                                  | (u_buf[0].unsigned_regval) >>
>> 1);
>> +                  }
>> +                else
>> +                  {
>> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>> +                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>> +
>> }
>> +              break;
>> +
>> +              default:
>> +                return -1;
>> +              break;
>> +            }
>> +
>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>> +                                      , &u_buf[1].unsigned_regval);
>> +          /* U == 1
>> */
>> +          if (bit (arm_insn_r->arm_insn, 23))
>> +            {
>> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>> +            }
>> +          else
>> +            {
>> +              tgt_mem_addr = u_buf[1].unsigned_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 0:
>> +          case 4:
>> +                /* STR insn, STRT insn.  */
>> +                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:
>> +                /* STRB insn, STRBT insn.
>> */
>> +                record_buf_mem[0] = 1;
>> +              break;
>> +
>> +              default:
>> +                return -1;
>> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>> +  uint32_t start_address = 0, index = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset (&u_buf, 0,
>> sizeof(u_buf));
>> +
>> +  /* 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 optmization.  */
>> +
>> +  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 optmization.  */
>> +        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_buf[0].unsigned_regval);
>> +    while (register_bits)
>> +      {
>> +        if (register_bits & 0x00000001)
>> +           register_count++;
>> +        register_bits = register_bits >> 1;
>> +      }
>> +
>> +    switch (addr_mode)
>> +      {
>> +        /* Decrement after.  */
>> +        case 0:
>> +          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
>> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
>> +          return -1;
>> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
>> +{
>> +
>> +  uint32_t record_buf[8];
>> +
>> +  /* Handle B, BL, BLX(1) insns.  */
>> +  /* Wihtout optmization we save link register,
>> +        CSPR for the insn which changes T bit.  */
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = ARM_LR_REGNUM;
>> +  arm_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>> +{
>> +  printf_unfiltered (_("Process record does not support instruction
>> "
>> +                     "0x%0x at address %s.\n"),
>> +                     arm_insn_r->arm_insn,
>> +                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>> +
>> +   return -1;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>> +{
>> +   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +   uint32_t shift_imm = 0;
>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>> 0;
>> +   uint32_t start_address = 0;
>> +
>> +   /* 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)
>> +          {
>> +            tdep->arm_swi_record(reg_cache);
>> +          }
>> +        else
>> +          {
>> +            printf_unfiltered (_("no syscall record
>> support\n"));
>> +            return -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 -1;
>> +}
>> +
>> +/* Handling opcode 000 insns.  */
>> +
>> +static int
>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_src1 = 0;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +      gdb_byte buf[4];
>> +    } u_buf[2];
>> +
>> +  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_buf[0].unsigned_regval);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                      , &u_buf[1].unsigned_regval);
>> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 2;
>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache = thumb_insn_r->regcache;
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_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.  */
>> +      /* Accorindly to high vector configuration PC is set accordingly.  */
>> +      /* FIX ME ?  what if 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;
>> +      thumb_insn_r->reg_rec_count = 2;
>> +      /* Save SPSR also; how?.  */
>> +      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_handle_swi_insn (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 reg_val1 = 0;
>> +  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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_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)
>> +          {
>> +            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 0;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +
>> uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> +  /* BL , 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;
>> +}
>> +
>> +
>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
>> +
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>> +{
>> +
>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
>> +  static int (*const arm_handle_insn[8])
>> +                                      (insn_decode_record*) =
>> +  {
>> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>> +      arm_handle_ld_st_multiple_insn,           /* 100.
>> */
>> +      arm_handle_brn_insn,                      /* 101.  */
>> +      arm_handle_coproc_insn,                   /* 110.  */
>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>> +  };
>> +
>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
>> +  static int (*const thumb_handle_insn[8])
>> +
>> (insn_decode_record*) =
>> +  { \
>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
>> +      thumb_handle_misc_insn,                  /* 101.  */
>> +
>> thumb_handle_swi_insn,                   /* 110.  */
>> +      thumb_handle_branch_insn                 /* 111.  */
>> +  };
>> +
>> +  struct
>> +    {
>> +      gdb_byte buf[insn_size];
>> +    } u_buf;
>> +
>> +  uint32_t ret=0, insn_id = 0;
>> +
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>> +      arm_record->cond = bits (arm_record->arm_insn, 28,
>> 31);
>> +      insn_id = bits (arm_record->arm_insn, 25, 27);
>> +      ret = (0x0F != arm_record->cond)
>> +            ? arm_handle_insn[insn_id] (arm_record)
>> +            : handle_extension_space (arm_record);
>> +    }
>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* As thumb does not have condition codes, following field is useless.  */
>> +      arm_record->cond = -1;
>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>> (arm_record->gdbarch));
>> +
>> +      insn_id = bits (arm_record->arm_insn, 13, 15);
>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>> +    }
>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* Yet to be implemented; handle thumb2 part here.  */
>> +      printf_unfiltered (_("Process record does not support 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 (0);
>> +    }
>> +
>> +  return ret;
>> +}
>> +
>> +/* 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;
>> +  ULONGEST t_bit = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  insn_decode_record arm_record;
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +
>> +  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));
>> +    }
>> +
>> +  /* 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_buf.unsigned_regval);
>> +
>> +  if (!(u_buf.unsigned_regval & t_bit))
>> +    {
>> +      /* We are decoding arm
>> insn.  */
>> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>> +    }
>> +  else
>> +    {
>> +      /* We are decoding thumb insn.  */
>> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>> +    }
>> +
>> +  if (0 == ret)
>> +    {
>> +      /* Record registers.  */
>> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>> +      if (arm_record.arm_regs)
>> +        {
>> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>> +
>> {
>> +              if (record_arch_list_add_reg (arm_record.regcache \
>> +                                           , (arm_record.arm_regs[no_of_rec])))
>> +              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_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_arch_list_add_end ())
>> +        ret = -1;
>> +    }
>> +
>> +  if (arm_record.arm_regs)
>> +    xfree (arm_record.arm_regs);
>> +  if
>> (arm_record.arm_mems)
>> +    xfree (arm_record.arm_mems);
>> +
>> +  return ret;
>> +}
>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
>> @@ -201,6 +201,9 @@
>>    /* Return the expected next PC if FRAME is stopped at a syscall
>>       instruction.  */
>>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>> +
>> +   /* Parse swi insn args, sycall record.  */
>> +  int (*arm_swi_record) (struct regcache *regcache);
>>  };
>>
>>  /* Structures used for displaced stepping.  */
>> @@ -331,6 +334,8 @@
>>     instruction?  */
>>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>
>> +extern int arm_process_record (struct
>> gdbarch *gdbarch,
>> +                               struct regcache *regcache, CORE_ADDR addr);
>>  /* Functions exported from armbsd-tdep.h.  */
>>
>>  /* Return the appropriate register set for the core section identified
>>
>>
>>
>>
>> ________________________________
>> From: Tom Tromey <tromey@redhat.com>
>> To: paawan oza <paawan1982@yahoo.com>
>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>> Sent: Wednesday, 13 July 2011 1:29 AM
>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>
>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>
>> Oza> any more comments are welcome make this patch ok, if ARM person can
>> Oza> have a look at it it would be great.
>>
>> You have submitted this patch many times now and nobody has commented
>> on the details of the ARM decoding.  I think we should proceed on the
>> theory that this is simply not going to happen.
>>
>> Also, I am not as concerned about the correctness of every detail as I
>> am about the general maintainability and style of the code.  I expect
>> there will be bugs; those can be fixed.
>>
>> You need a ChangeLog entry.  A patch of this magnitude
>> should also have
>> a NEWS entry.
>>
>> Some kind of testing would be good.  Do the existing tests in
>> gdb.reverse work with your port?  If so then I think that is sufficient
>>
>> Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>>
>> Just write   unsigned int reg_len = LENGTH;
>>
>> Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>
>> Mind the spaces and parens.  Better, use XNEWVEC:
>>
>>     REGS = XNEWVEC (uint32_t, reg_len);
>>
>> Oza> +        while (reg_len) \
>> Oza> +          { \
>> Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
>> Oza> +            reg_len--;  \
>> Oza> +          } \
>>
>> Just use memcpy.
>>
>> Oza> +#define
>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>
>> The same comments apply for this macro.
>>
>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>> Oza> (before entry to
>>
>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>> Oza> (on return from
>>
>> Your email got corrupted.  Usually this is some bad MUA setting.
>>
>> Oza> +  uint32_t mem_rec_count;       /* No of mem recors */
>>
>> Typo, "recors"
>>
>> Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */
>>
>> Typo, should be "mandatory".
>>
>> Oza> +  if(!sbo)
>>
>> Spacing.
>>
>> Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>
>> Over-parenthesizing makes the code harder to read.  Please fix this.  I
>> noticed it in many places.  This specific case should read:
>>
>>   if (3 == opcode1 && bit
>> (arm_insn_r->arm_insn, 4))
>>
>> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
>>
>> Spacing.  Just go through the entire patch and fix all the spacing
>> issues.
>>
>> I feel like I have mentioned this before.
>>
>> Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>> Oza> +                                  , &u_buf[0].unsigned_regval);
>>
>> What if this does not return REG_VALID?
>> There are multiple instances of this.
>>
>> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>
>> It seems wrong to use an assert in this code.  At least, it is not
>> obvious to me that this represents a logic error in gdb as opposed to a
>> merely unrecognized instruction.  An unrecognized instruction can occur
>> for many reasons, e.g., a bad jump.
>>
>> Oza> +
>>   if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>> Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>> Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>> Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>> Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>> Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>> Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>
>> This reads very oddly.  Is there a particular reason behind the ordering
>> (if so -- document).  If not, isn't
>> this:
>>
>>   if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>
>> There are other odd-looking conditions like this.
>>
>> Oza> +              default:
>> Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");
>>
>> Again, assert seems wrong.
>>
>> I'm afraid I ran out of steam here.  Please fix all the issues already
>> noted and look at the rest of the patch with a critical eye to see what
>> else should be cleaned up.  I want this patch to go in, but first it
>> must comply to the usual gdb standards.
>>
>> Tom
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-09-27  6:52             ` oza Pawandeep
@ 2011-10-06 18:01               ` oza Pawandeep
       [not found]                 ` <CAK1A=4xuUT++WRzdUnZc0KodYF0AiukUyJa7Pr=wzb4i-OQ5eQ@mail.gmail.com>
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-06 18:01 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches, Petr Hluzín

Hi Tom,

Gentle reminder to look into patch.
any arm related comment would be highly appreciated.

Regards,
Oza.

On Tue, Sep 27, 2011 at 9:21 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom,
>
> What do you think about the patch to be ready to to move in <phase_2> ?
> Any more comments are welcome from ARM specific community here.
> most of the review comments from Michael, Petr, Tom and other folks
> have been implemented.
>
> Regards,
> Oza.
>
> On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hello Chandra,
>>
>> Let me know if you are planning to do anymore basic testing on this patch.
>>
>> @Tom: is it possible to get this patch move in, of course I have been
>> keen on any review comment; but it has been lying around for a long
>> time.
>> and I would like to move to phase-3 implementation then.
>>
>> Regards,
>> Oza.
>>
>> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>>
>>>
>>> Hi all,
>>>
>>> Sorry for delay in fixing review comments.
>>>
>>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>>
>>> PATCH STARTS
>>> ----------------------------------
>>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>>> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
>>> @@ -1025,6 +1025,9 @@
>>>    set_gdbarch_fetch_tls_load_module_address
>>> (gdbarch,
>>>                                               svr4_fetch_objfile_link_map);
>>>
>>> +  /* Enable process record.  */
>>> +  set_gdbarch_process_record (gdbarch, arm_process_record);
>>> +
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>>                  &arm_linux_sigreturn_tramp_frame);
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>> @@ -1054,6 +1057,8 @@
>>>
>>>
>>>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>>> +
>>> +  tdep->arm_swi_record = NULL;
>>>  }
>>>
>>>  /* Provide a prototype to silence -Wmissing-prototypes.  */
>>> diff -urN
>>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>>> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
>>> @@ -55,6 +55,8 @@
>>>  #include "gdb_assert.h"
>>>  #include "vec.h"
>>>
>>> +#include "record.h"
>>> +
>>>  #include "features/arm-with-m.c"
>>>
>>>  static int arm_debug;
>>> @@ -8821,3 +8823,1769 @@
>>>                 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)
>>> +
>>> +
>>> +/* 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;
>>> +}
>>> +
>>> +/* Handling ARM extension space insns.  */
>>> +
>>> +static int
>>> +handle_extension_space (insn_decode_record *arm_insn_r)
>>> +{
>>> +  uint32_t ret = 0;
>>> +  uint32_t opcode1 = 0, opcode2 = 0;
>>> +
>>> +  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.  */
>>> +    }
>>> +
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> +  if (!opcode1 && (9 == opcode2))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle arithmetic insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>>> +
>>> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>>> +
>>> {
>>> +      ret = -1;
>>> +      /* Handle control insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>>> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>>> +                 && bit (arm_insn_r->arm_insn, 4))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle load/store insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>>> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>>> +    {
>>> +      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 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
>>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>>> +  uint32_t
>>> record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +
>>> +  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;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +
>>> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly */
>>> +      /* What if 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)
>>> +           let us begin according to addressing modes for store insns
>>> +           STRH insn, addresing modes are taken following.  */
>>> +    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_buf[0].unsigned_regval);
>>> +        if (15 == reg_src1)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +          }
>>> +        offset_8 = (immed_high << 4) |
>>> immed_low;
>>> +        /* Calculate target store address.  */
>>> +        if (14 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count =
>>> 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        if (15 == reg_src2)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +
>>> }
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if (12 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +
>>> record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +
>>> }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = 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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +
>>> else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> +        arm_insn_r->reg_rec_count = 1;
>>> +
>>> }
>>> +    /* DSP insns  (e.g. LDRD)  TBD.  */
>>> +  }
>>> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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 (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
>>> +    {
>>> +      /* 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_buf.unsigned_regval);
>>> +      /* U == 1 */
>>> +      if (bit (arm_insn_r->arm_insn, 23))
>>> +        {
>>> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>>> +        }
>>> +      else
>>> +        {
>>> +         tgt_mem_addr = u_buf.unsigned_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:
>>> +
>>> +            /* STR insn, STRT insn.  */
>>> +            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:
>>> +            /* STRB insn, STRBT insn.  */
>>> +            record_buf_mem[0] = 1;
>>> +          break;
>>> +
>>> +          default:
>>> +            return -1;
>>> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>>> +  uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      LONGEST signed_word;
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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,
>>> +        let us begin 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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          if (15 == reg_src2)
>>> +            {
>>> +              /* If R15 was used as Rn, hence current PC+8.  */
>>> +              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
>>> +              u_buf[0].unsigned_regval =
>>> u_buf[0].unsigned_regval + 8;
>>> +            }
>>> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +          /* U == 1.  */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[0].unsigned_regval +
>>> +                             u_buf[1].unsigned_regval;
>>> +
>>> }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval -
>>> +                             u_buf[0].unsigned_regval;
>>> +            }
>>> +
>>> +          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:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.  */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +
>>> default:
>>> +                return -1;
>>> +              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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_signed (reg_cache, reg_src1
>>> +                                      ,
>>> &u_buf[0].signed_word);
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* Offset_12 used as shift.  */
>>> +          switch (offset_12)
>>> +            {
>>> +              case 0:
>>> +                /* Offset_12 used as index.
>>> */
>>> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
>>> +              break;
>>> +
>>> +              case 1:
>>> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>>> +              break;
>>> +
>>> +              case 2:
>>> +                if
>>> (!shift_imm)
>>> +                  {
>>> +                    if (bit (u_buf[0].unsigned_regval, 31))
>>> +                      {
>>> +                        offset_12 = 0xFFFFFFFF;
>>> +                      }
>>> +
>>> else
>>> +                      {
>>> +                        offset_12 = 0;
>>> +                      }
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    /* This is arithmetic shift.
>>> */
>>> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
>>> +                  }
>>> +                break;
>>> +
>>> +              case 3:
>>> +                if (!shift_imm)
>>> +                  {
>>> +                    regcache_raw_read_unsigned (reg_cache,
>>> ARM_PS_REGNUM
>>> +                                                , &u_buf[1].unsigned_regval);
>>> +                    /* Get C flag value and shift it by 31.  */
>>> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>>> +                                  | (u_buf[0].unsigned_regval) >>
>>> 1);
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>>> +                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>>> +
>>> }
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              break;
>>> +            }
>>> +
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* U == 1
>>> */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>>> +            }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_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 0:
>>> +          case 4:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.
>>> */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
>>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>>> +  uint32_t start_address = 0, index = 0;
>>> +  uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0,
>>> sizeof(u_buf));
>>> +
>>> +  /* 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 optmization.  */
>>> +
>>> +  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 optmization.  */
>>> +        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_buf[0].unsigned_regval);
>>> +    while (register_bits)
>>> +      {
>>> +        if (register_bits & 0x00000001)
>>> +           register_count++;
>>> +        register_bits = register_bits >> 1;
>>> +      }
>>> +
>>> +    switch (addr_mode)
>>> +      {
>>> +        /* Decrement after.  */
>>> +        case 0:
>>> +          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
>>> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
>>> +          return -1;
>>> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +
>>> +  uint32_t record_buf[8];
>>> +
>>> +  /* Handle B, BL, BLX(1) insns.  */
>>> +  /* Wihtout optmization we save link register,
>>> +        CSPR for the insn which changes T bit.  */
>>> +  record_buf[0] = ARM_PS_REGNUM;
>>> +  record_buf[1] = ARM_LR_REGNUM;
>>> +  arm_insn_r->reg_rec_count = 2;
>>> +
>>> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>>> +
>>> +  return 0;
>>> +}
>>> +
>>> +/* Handling opcode 110 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  printf_unfiltered (_("Process record does not support instruction
>>> "
>>> +                     "0x%0x at address %s.\n"),
>>> +                     arm_insn_r->arm_insn,
>>> +                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>>> +
>>> +   return -1;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> +   uint32_t shift_imm = 0;
>>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>>> 0;
>>> +   uint32_t start_address = 0;
>>> +
>>> +   /* 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)
>>> +          {
>>> +            tdep->arm_swi_record(reg_cache);
>>> +          }
>>> +        else
>>> +          {
>>> +            printf_unfiltered (_("no syscall record
>>> support\n"));
>>> +            return -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 -1;
>>> +}
>>> +
>>> +/* Handling opcode 000 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +      gdb_byte buf[4];
>>> +    } u_buf[2];
>>> +
>>> +  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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 2;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = thumb_insn_r->regcache;
>>> +
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly.  */
>>> +      /* FIX ME ?  what if 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;
>>> +      thumb_insn_r->reg_rec_count = 2;
>>> +      /* Save SPSR also; how?.  */
>>> +      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_handle_swi_insn (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 reg_val1 = 0;
>>> +  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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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)
>>> +          {
>>> +            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 0;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> +  /* BL , 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;
>>> +}
>>> +
>>> +
>>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
>>> +
>>> +static int
>>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>>> +{
>>> +
>>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
>>> +  static int (*const arm_handle_insn[8])
>>> +                                      (insn_decode_record*) =
>>> +  {
>>> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
>>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>>> +      arm_handle_ld_st_multiple_insn,           /* 100.
>>> */
>>> +      arm_handle_brn_insn,                      /* 101.  */
>>> +      arm_handle_coproc_insn,                   /* 110.  */
>>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>>> +  };
>>> +
>>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
>>> +  static int (*const thumb_handle_insn[8])
>>> +
>>> (insn_decode_record*) =
>>> +  { \
>>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>>> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
>>> +      thumb_handle_misc_insn,                  /* 101.  */
>>> +
>>> thumb_handle_swi_insn,                   /* 110.  */
>>> +      thumb_handle_branch_insn                 /* 111.  */
>>> +  };
>>> +
>>> +  struct
>>> +    {
>>> +      gdb_byte buf[insn_size];
>>> +    } u_buf;
>>> +
>>> +  uint32_t ret=0, insn_id = 0;
>>> +
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>>> +      arm_record->cond = bits (arm_record->arm_insn, 28,
>>> 31);
>>> +      insn_id = bits (arm_record->arm_insn, 25, 27);
>>> +      ret = (0x0F != arm_record->cond)
>>> +            ? arm_handle_insn[insn_id] (arm_record)
>>> +            : handle_extension_space (arm_record);
>>> +    }
>>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* As thumb does not have condition codes, following field is useless.  */
>>> +      arm_record->cond = -1;
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>>> (arm_record->gdbarch));
>>> +
>>> +      insn_id = bits (arm_record->arm_insn, 13, 15);
>>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>>> +    }
>>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* Yet to be implemented; handle thumb2 part here.  */
>>> +      printf_unfiltered (_("Process record does not support 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 (0);
>>> +    }
>>> +
>>> +  return ret;
>>> +}
>>> +
>>> +/* 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;
>>> +  ULONGEST t_bit = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  insn_decode_record arm_record;
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +
>>> +  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));
>>> +    }
>>> +
>>> +  /* 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_buf.unsigned_regval);
>>> +
>>> +  if (!(u_buf.unsigned_regval & t_bit))
>>> +    {
>>> +      /* We are decoding arm
>>> insn.  */
>>> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>>> +    }
>>> +  else
>>> +    {
>>> +      /* We are decoding thumb insn.  */
>>> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>>> +    }
>>> +
>>> +  if (0 == ret)
>>> +    {
>>> +      /* Record registers.  */
>>> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>>> +      if (arm_record.arm_regs)
>>> +        {
>>> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>>> +
>>> {
>>> +              if (record_arch_list_add_reg (arm_record.regcache \
>>> +                                           , (arm_record.arm_regs[no_of_rec])))
>>> +              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_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_arch_list_add_end ())
>>> +        ret = -1;
>>> +    }
>>> +
>>> +  if (arm_record.arm_regs)
>>> +    xfree (arm_record.arm_regs);
>>> +  if
>>> (arm_record.arm_mems)
>>> +    xfree (arm_record.arm_mems);
>>> +
>>> +  return ret;
>>> +}
>>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>>> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
>>> @@ -201,6 +201,9 @@
>>>    /* Return the expected next PC if FRAME is stopped at a syscall
>>>       instruction.  */
>>>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>>> +
>>> +   /* Parse swi insn args, sycall record.  */
>>> +  int (*arm_swi_record) (struct regcache *regcache);
>>>  };
>>>
>>>  /* Structures used for displaced stepping.  */
>>> @@ -331,6 +334,8 @@
>>>     instruction?  */
>>>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>>
>>> +extern int arm_process_record (struct
>>> gdbarch *gdbarch,
>>> +                               struct regcache *regcache, CORE_ADDR addr);
>>>  /* Functions exported from armbsd-tdep.h.  */
>>>
>>>  /* Return the appropriate register set for the core section identified
>>>
>>>
>>>
>>>
>>> ________________________________
>>> From: Tom Tromey <tromey@redhat.com>
>>> To: paawan oza <paawan1982@yahoo.com>
>>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>>> Sent: Wednesday, 13 July 2011 1:29 AM
>>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>
>>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>>
>>> Oza> any more comments are welcome make this patch ok, if ARM person can
>>> Oza> have a look at it it would be great.
>>>
>>> You have submitted this patch many times now and nobody has commented
>>> on the details of the ARM decoding.  I think we should proceed on the
>>> theory that this is simply not going to happen.
>>>
>>> Also, I am not as concerned about the correctness of every detail as I
>>> am about the general maintainability and style of the code.  I expect
>>> there will be bugs; those can be fixed.
>>>
>>> You need a ChangeLog entry.  A patch of this magnitude
>>> should also have
>>> a NEWS entry.
>>>
>>> Some kind of testing would be good.  Do the existing tests in
>>> gdb.reverse work with your port?  If so then I think that is sufficient
>>>
>>> Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>>>
>>> Just write   unsigned int reg_len = LENGTH;
>>>
>>> Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>>
>>> Mind the spaces and parens.  Better, use XNEWVEC:
>>>
>>>     REGS = XNEWVEC (uint32_t, reg_len);
>>>
>>> Oza> +        while (reg_len) \
>>> Oza> +          { \
>>> Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
>>> Oza> +            reg_len--;  \
>>> Oza> +          } \
>>>
>>> Just use memcpy.
>>>
>>> Oza> +#define
>>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>>
>>> The same comments apply for this macro.
>>>
>>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>>> Oza> (before entry to
>>>
>>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>>> Oza> (on return from
>>>
>>> Your email got corrupted.  Usually this is some bad MUA setting.
>>>
>>> Oza> +  uint32_t mem_rec_count;       /* No of mem recors */
>>>
>>> Typo, "recors"
>>>
>>> Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */
>>>
>>> Typo, should be "mandatory".
>>>
>>> Oza> +  if(!sbo)
>>>
>>> Spacing.
>>>
>>> Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>>
>>> Over-parenthesizing makes the code harder to read.  Please fix this.  I
>>> noticed it in many places.  This specific case should read:
>>>
>>>   if (3 == opcode1 && bit
>>> (arm_insn_r->arm_insn, 4))
>>>
>>> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
>>>
>>> Spacing.  Just go through the entire patch and fix all the spacing
>>> issues.
>>>
>>> I feel like I have mentioned this before.
>>>
>>> Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>>> Oza> +                                  , &u_buf[0].unsigned_regval);
>>>
>>> What if this does not return REG_VALID?
>>> There are multiple instances of this.
>>>
>>> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>>
>>> It seems wrong to use an assert in this code.  At least, it is not
>>> obvious to me that this represents a logic error in gdb as opposed to a
>>> merely unrecognized instruction.  An unrecognized instruction can occur
>>> for many reasons, e.g., a bad jump.
>>>
>>> Oza> +
>>>   if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>>> Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>>> Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>>
>>> This reads very oddly.  Is there a particular reason behind the ordering
>>> (if so -- document).  If not, isn't
>>> this:
>>>
>>>   if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>>
>>> There are other odd-looking conditions like this.
>>>
>>> Oza> +              default:
>>> Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");
>>>
>>> Again, assert seems wrong.
>>>
>>> I'm afraid I ran out of steam here.  Please fix all the issues already
>>> noted and look at the rest of the patch with a critical eye to see what
>>> else should be cleaned up.  I want this patch to go in, but first it
>>> must comply to the usual gdb standards.
>>>
>>> Tom
>>>
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: Fwd: [PATCH] arm reversible : <phase_2_complete>
       [not found]                 ` <CAK1A=4xuUT++WRzdUnZc0KodYF0AiukUyJa7Pr=wzb4i-OQ5eQ@mail.gmail.com>
@ 2011-10-08  2:50                   ` paawan oza
  2011-10-11 18:11                     ` [PATCH] arm reversible : <phase_2_complete> how to go ahead ? paawan oza
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-10-08  2:50 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches



Hi Tom,

Gentle reminder to look into patch.
any arm related comment would be highly appreciated.

Regards,
Oza.

On Tue, Sep 27, 2011 at 9:21 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom,
>
> What do you think about the patch to be ready to to move in <phase_2> ?
> Any more comments are welcome from ARM specific community here.
> most of the review comments from Michael, Petr, Tom and other folks
> have been implemented.
>
> Regards,
> Oza.
>
> On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hello Chandra,
>>
>> Let me know if you are planning to do anymore basic testing on this patch.
>>
>> @Tom: is it possible to get this patch move in, of course I have been
>> keen on any review comment; but it has been lying around for a long
>> time.
>> and I would like to move to phase-3 implementation then.
>>
>> Regards,
>> Oza.
>>
>> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>>
>>>
>>> Hi all,
>>>
>>> Sorry for delay in fixing review comments.
>>>
>>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>>
>>> PATCH STARTS
>>> ----------------------------------
>>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>>> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
>>> @@ -1025,6 +1025,9 @@
>>>    set_gdbarch_fetch_tls_load_module_address
>>> (gdbarch,
>>>                                               svr4_fetch_objfile_link_map);
>>>
>>> +  /* Enable process record.  */
>>> +  set_gdbarch_process_record (gdbarch, arm_process_record);
>>> +
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>>                  &arm_linux_sigreturn_tramp_frame);
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>> @@ -1054,6 +1057,8 @@
>>>
>>>
>>>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>>> +
>>> +  tdep->arm_swi_record = NULL;
>>>  }
>>>
>>>  /* Provide a prototype to silence -Wmissing-prototypes.  */
>>> diff -urN
>>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>>> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
>>> @@ -55,6 +55,8 @@
>>>  #include "gdb_assert.h"
>>>  #include "vec.h"
>>>
>>> +#include "record.h"
>>> +
>>>  #include "features/arm-with-m.c"
>>>
>>>  static int arm_debug;
>>> @@ -8821,3 +8823,1769 @@
>>>                 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)
>>> +
>>> +
>>> +/* 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;
>>> +}
>>> +
>>> +/* Handling ARM extension space insns.  */
>>> +
>>> +static int
>>> +handle_extension_space (insn_decode_record *arm_insn_r)
>>> +{
>>> +  uint32_t ret = 0;
>>> +  uint32_t opcode1 = 0, opcode2 = 0;
>>> +
>>> +  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.  */
>>> +    }
>>> +
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> +  if (!opcode1 && (9 == opcode2))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle arithmetic insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>>> +
>>> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>>> +
>>> {
>>> +      ret = -1;
>>> +      /* Handle control insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>>> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>>> +                 && bit (arm_insn_r->arm_insn, 4))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle load/store insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>>> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>>> +    {
>>> +      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 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
>>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>>> +  uint32_t
>>> record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +
>>> +  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;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +
>>> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly */
>>> +      /* What if 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)
>>> +           let us begin according to addressing modes for store insns
>>> +           STRH insn, addresing modes are taken following.  */
>>> +    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_buf[0].unsigned_regval);
>>> +        if (15 == reg_src1)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +          }
>>> +        offset_8 = (immed_high << 4) |
>>> immed_low;
>>> +        /* Calculate target store address.  */
>>> +        if (14 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count =
>>> 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        if (15 == reg_src2)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +
>>> }
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if (12 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +
>>> record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +
>>> }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = 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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +
>>> else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> +        arm_insn_r->reg_rec_count = 1;
>>> +
>>> }
>>> +    /* DSP insns  (e.g. LDRD)  TBD.  */
>>> +  }
>>> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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 (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
>>> +    {
>>> +      /* 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_buf.unsigned_regval);
>>> +      /* U == 1 */
>>> +      if (bit (arm_insn_r->arm_insn, 23))
>>> +        {
>>> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>>> +        }
>>> +      else
>>> +        {
>>> +         tgt_mem_addr = u_buf.unsigned_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:
>>> +
>>> +            /* STR insn, STRT insn.  */
>>> +            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:
>>> +            /* STRB insn, STRBT insn.  */
>>> +            record_buf_mem[0] = 1;
>>> +          break;
>>> +
>>> +          default:
>>> +            return -1;
>>> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>>> +  uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      LONGEST signed_word;
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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,
>>> +        let us begin 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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          if (15 == reg_src2)
>>> +            {
>>> +              /* If R15 was used as Rn, hence current PC+8.  */
>>> +              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
>>> +              u_buf[0].unsigned_regval =
>>> u_buf[0].unsigned_regval + 8;
>>> +            }
>>> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +          /* U == 1.  */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[0].unsigned_regval +
>>> +                             u_buf[1].unsigned_regval;
>>> +
>>> }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval -
>>> +                             u_buf[0].unsigned_regval;
>>> +            }
>>> +
>>> +          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:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.  */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +
>>> default:
>>> +                return -1;
>>> +              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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_signed (reg_cache, reg_src1
>>> +                                      ,
>>> &u_buf[0].signed_word);
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* Offset_12 used as shift.  */
>>> +          switch (offset_12)
>>> +            {
>>> +              case 0:
>>> +                /* Offset_12 used as index.
>>> */
>>> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
>>> +              break;
>>> +
>>> +              case 1:
>>> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>>> +              break;
>>> +
>>> +              case 2:
>>> +                if
>>> (!shift_imm)
>>> +                  {
>>> +                    if (bit (u_buf[0].unsigned_regval, 31))
>>> +                      {
>>> +                        offset_12 = 0xFFFFFFFF;
>>> +                      }
>>> +
>>> else
>>> +                      {
>>> +                        offset_12 = 0;
>>> +                      }
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    /* This is arithmetic shift.
>>> */
>>> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
>>> +                  }
>>> +                break;
>>> +
>>> +              case 3:
>>> +                if (!shift_imm)
>>> +                  {
>>> +                    regcache_raw_read_unsigned (reg_cache,
>>> ARM_PS_REGNUM
>>> +                                                , &u_buf[1].unsigned_regval);
>>> +                    /* Get C flag value and shift it by 31.  */
>>> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>>> +                                  | (u_buf[0].unsigned_regval) >>
>>> 1);
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>>> +                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>>> +
>>> }
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              break;
>>> +            }
>>> +
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* U == 1
>>> */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>>> +            }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_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 0:
>>> +          case 4:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.
>>> */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
>>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>>> +  uint32_t start_address = 0, index = 0;
>>> +  uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0,
>>> sizeof(u_buf));
>>> +
>>> +  /* 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 optmization.  */
>>> +
>>> +  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 optmization.  */
>>> +        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_buf[0].unsigned_regval);
>>> +    while (register_bits)
>>> +      {
>>> +        if (register_bits & 0x00000001)
>>> +           register_count++;
>>> +        register_bits = register_bits >> 1;
>>> +      }
>>> +
>>> +    switch (addr_mode)
>>> +      {
>>> +        /* Decrement after.  */
>>> +        case 0:
>>> +          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
>>> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
>>> +          return -1;
>>> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +
>>> +  uint32_t record_buf[8];
>>> +
>>> +  /* Handle B, BL, BLX(1) insns.  */
>>> +  /* Wihtout optmization we save link register,
>>> +        CSPR for the insn which changes T bit.  */
>>> +  record_buf[0] = ARM_PS_REGNUM;
>>> +  record_buf[1] = ARM_LR_REGNUM;
>>> +  arm_insn_r->reg_rec_count = 2;
>>> +
>>> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>>> +
>>> +  return 0;
>>> +}
>>> +
>>> +/* Handling opcode 110 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  printf_unfiltered (_("Process record does not support instruction
>>> "
>>> +                     "0x%0x at address %s.\n"),
>>> +                     arm_insn_r->arm_insn,
>>> +                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>>> +
>>> +   return -1;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> +   uint32_t shift_imm = 0;
>>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>>> 0;
>>> +   uint32_t start_address = 0;
>>> +
>>> +   /* 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)
>>> +          {
>>> +            tdep->arm_swi_record(reg_cache);
>>> +          }
>>> +        else
>>> +          {
>>> +            printf_unfiltered (_("no syscall record
>>> support\n"));
>>> +            return -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 -1;
>>> +}
>>> +
>>> +/* Handling opcode 000 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +      gdb_byte buf[4];
>>> +    } u_buf[2];
>>> +
>>> +  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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 2;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = thumb_insn_r->regcache;
>>> +
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly.  */
>>> +      /* FIX ME ?  what if 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;
>>> +      thumb_insn_r->reg_rec_count = 2;
>>> +      /* Save SPSR also; how?.  */
>>> +      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_handle_swi_insn (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 reg_val1 = 0;
>>> +  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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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)
>>> +          {
>>> +            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 0;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> +  /* BL , 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;
>>> +}
>>> +
>>> +
>>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
>>> +
>>> +static int
>>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>>> +{
>>> +
>>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
>>> +  static int (*const arm_handle_insn[8])
>>> +                                      (insn_decode_record*) =
>>> +  {
>>> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
>>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>>> +      arm_handle_ld_st_multiple_insn,           /* 100.
>>> */
>>> +      arm_handle_brn_insn,                      /* 101.  */
>>> +      arm_handle_coproc_insn,                   /* 110.  */
>>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>>> +  };
>>> +
>>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
>>> +  static int (*const thumb_handle_insn[8])
>>> +
>>> (insn_decode_record*) =
>>> +  { \
>>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>>> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
>>> +      thumb_handle_misc_insn,                  /* 101.  */
>>> +
>>> thumb_handle_swi_insn,                   /* 110.  */
>>> +      thumb_handle_branch_insn                 /* 111.  */
>>> +  };
>>> +
>>> +  struct
>>> +    {
>>> +      gdb_byte buf[insn_size];
>>> +    } u_buf;
>>> +
>>> +  uint32_t ret=0, insn_id = 0;
>>> +
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>>> +      arm_record->cond = bits (arm_record->arm_insn, 28,
>>> 31);
>>> +      insn_id = bits (arm_record->arm_insn, 25, 27);
>>> +      ret = (0x0F != arm_record->cond)
>>> +            ? arm_handle_insn[insn_id] (arm_record)
>>> +            : handle_extension_space (arm_record);
>>> +    }
>>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* As thumb does not have condition codes, following field is useless.  */
>>> +      arm_record->cond = -1;
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>>> (arm_record->gdbarch));
>>> +
>>> +      insn_id = bits (arm_record->arm_insn, 13, 15);
>>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>>> +    }
>>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* Yet to be implemented; handle thumb2 part here.  */
>>> +      printf_unfiltered (_("Process record does not support 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 (0);
>>> +    }
>>> +
>>> +  return ret;
>>> +}
>>> +
>>> +/* 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;
>>> +  ULONGEST t_bit = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  insn_decode_record arm_record;
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +
>>> +  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));
>>> +    }
>>> +
>>> +  /* 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_buf.unsigned_regval);
>>> +
>>> +  if (!(u_buf.unsigned_regval & t_bit))
>>> +    {
>>> +      /* We are decoding arm
>>> insn.  */
>>> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>>> +    }
>>> +  else
>>> +    {
>>> +      /* We are decoding thumb insn.  */
>>> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>>> +    }
>>> +
>>> +  if (0 == ret)
>>> +    {
>>> +      /* Record registers.  */
>>> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>>> +      if (arm_record.arm_regs)
>>> +        {
>>> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>>> +
>>> {
>>> +              if (record_arch_list_add_reg (arm_record.regcache \
>>> +                                           , (arm_record.arm_regs[no_of_rec])))
>>> +              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_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_arch_list_add_end ())
>>> +        ret = -1;
>>> +    }
>>> +
>>> +  if (arm_record.arm_regs)
>>> +    xfree (arm_record.arm_regs);
>>> +  if
>>> (arm_record.arm_mems)
>>> +    xfree (arm_record.arm_mems);
>>> +
>>> +  return ret;
>>> +}
>>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>>> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
>>> @@ -201,6 +201,9 @@
>>>    /* Return the expected next PC if FRAME is stopped at a syscall
>>>       instruction.  */
>>>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>>> +
>>> +   /* Parse swi insn args, sycall record.  */
>>> +  int (*arm_swi_record) (struct regcache *regcache);
>>>  };
>>>
>>>  /* Structures used for displaced stepping.  */
>>> @@ -331,6 +334,8 @@
>>>     instruction?  */
>>>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>>
>>> +extern int arm_process_record (struct
>>> gdbarch *gdbarch,
>>> +                               struct regcache *regcache, CORE_ADDR addr);
>>>  /* Functions exported from armbsd-tdep.h.  */
>>>
>>>  /* Return the appropriate register set for the core section identified
>>>
>>>
>>>
>>>
>>> ________________________________
>>> From: Tom Tromey <tromey@redhat.com>
>>> To: paawan oza <paawan1982@yahoo.com>
>>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>>> Sent: Wednesday, 13 July 2011 1:29 AM
>>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>
>>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>>
>>> Oza> any more comments are welcome make this patch ok, if ARM person can
>>> Oza> have a look at it it would be great.
>>>
>>> You have submitted this patch many times now and nobody has commented
>>> on the details of the ARM decoding.  I think we should proceed on the
>>> theory that this is simply not going to happen.
>>>
>>> Also, I am not as concerned about the correctness of every detail as I
>>> am about the general maintainability and style of the code.  I expect
>>> there will be bugs; those can be fixed.
>>>
>>> You need a ChangeLog entry.  A patch of this magnitude
>>> should also have
>>> a NEWS entry.
>>>
>>> Some kind of testing would be good.  Do the existing tests in
>>> gdb.reverse work with your port?  If so then I think that is sufficient
>>>
>>> Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>>>
>>> Just write   unsigned int reg_len = LENGTH;
>>>
>>> Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>>
>>> Mind the spaces and parens.  Better, use XNEWVEC:
>>>
>>>     REGS = XNEWVEC (uint32_t, reg_len);
>>>
>>> Oza> +        while (reg_len) \
>>> Oza> +          { \
>>> Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
>>> Oza> +            reg_len--;  \
>>> Oza> +          } \
>>>
>>> Just use memcpy.
>>>
>>> Oza> +#define
>>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>>
>>> The same comments apply for this macro.
>>>
>>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>>> Oza> (before entry to
>>>
>>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>>> Oza> (on return from
>>>
>>> Your email got corrupted.  Usually this is some bad MUA setting.
>>>
>>> Oza> +  uint32_t mem_rec_count;       /* No of mem recors */
>>>
>>> Typo, "recors"
>>>
>>> Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */
>>>
>>> Typo, should be "mandatory".
>>>
>>> Oza> +  if(!sbo)
>>>
>>> Spacing.
>>>
>>> Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>>
>>> Over-parenthesizing makes the code harder to read.  Please fix this.  I
>>> noticed it in many places.  This specific case should read:
>>>
>>>   if (3 == opcode1 && bit
>>> (arm_insn_r->arm_insn, 4))
>>>
>>> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
>>>
>>> Spacing.  Just go through the entire patch and fix all the spacing
>>> issues.
>>>
>>> I feel like I have mentioned this before.
>>>
>>> Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>>> Oza> +                                  , &u_buf[0].unsigned_regval);
>>>
>>> What if this does not return REG_VALID?
>>> There are multiple instances of this.
>>>
>>> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>>
>>> It seems wrong to use an assert in this code.  At least, it is not
>>> obvious to me that this represents a logic error in gdb as opposed to a
>>> merely unrecognized instruction.  An unrecognized instruction can occur
>>> for many reasons, e.g., a bad jump.
>>>
>>> Oza> +
>>>   if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>>> Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>>> Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>>
>>> This reads very oddly.  Is there a particular reason behind the ordering
>>> (if so -- document).  If not, isn't
>>> this:
>>>
>>>   if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>>
>>> There are other odd-looking conditions like this.
>>>
>>> Oza> +              default:
>>> Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");
>>>
>>> Again, assert seems wrong.
>>>
>>> I'm afraid I ran out of steam here.  Please fix all the issues already
>>> noted and look at the rest of the patch with a critical eye to see what
>>> else should be cleaned up.  I want this patch to go in, but first it
>>> must comply to the usual gdb standards.
>>>
>>> Tom
>>>
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* [PATCH] arm reversible : <phase_2_complete> how to go ahead ?
  2011-10-08  2:50                   ` Fwd: " paawan oza
@ 2011-10-11 18:11                     ` paawan oza
  2011-10-11 19:02                       ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-10-11 18:11 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

Hi,

please guide as how do we go ahead about checking in the patch.

Regards,
Oza.




________________________________
From: paawan oza <paawan1982@yahoo.com>
To: Tom Tromey <tromey@redhat.com>; "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Sent: Saturday, 8 October 2011 8:19 AM
Subject: Re: Fwd: [PATCH] arm reversible : <phase_2_complete>



Hi Tom,

Gentle reminder to look into patch.
any arm related comment would be highly appreciated.

Regards,
Oza.

On Tue, Sep 27, 2011 at 9:21 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom,
>
> What do you think about the patch to be ready to to move in <phase_2> ?
> Any more comments are welcome from ARM specific community here.
> most of the review comments from Michael, Petr, Tom and other folks
> have been implemented.
>
> Regards,
> Oza.
>
> On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hello Chandra,
>>
>> Let me know if you are planning to do anymore basic testing on this patch.
>>
>> @Tom: is it possible to get this patch move in, of course I have been
>> keen on any review comment; but it has been lying around for a long
>> time.
>> and I would like to move to phase-3 implementation then.
>>
>> Regards,
>> Oza.
>>
>> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>>
>>>
>>> Hi all,
>>>
>>> Sorry for delay in fixing review comments.
>>>
>>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>>
>>> PATCH STARTS
>>> ----------------------------------
>>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>>> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
>>> @@ -1025,6 +1025,9 @@
>>>    set_gdbarch_fetch_tls_load_module_address
>>> (gdbarch,
>>>                                               svr4_fetch_objfile_link_map);
>>>
>>> +  /* Enable process record.  */
>>> +  set_gdbarch_process_record (gdbarch, arm_process_record);
>>> +
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>>                  &arm_linux_sigreturn_tramp_frame);
>>>    tramp_frame_prepend_unwinder (gdbarch,
>>> @@ -1054,6 +1057,8 @@
>>>
>>>
>>>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>>> +
>>> +  tdep->arm_swi_record = NULL;
>>>  }
>>>
>>>  /* Provide a prototype to silence -Wmissing-prototypes.  */
>>> diff -urN
>>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>>> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
>>> @@ -55,6 +55,8 @@
>>>  #include "gdb_assert.h"
>>>  #include "vec.h"
>>>
>>> +#include "record.h"
>>> +
>>>  #include "features/arm-with-m.c"
>>>
>>>  static int arm_debug;
>>> @@ -8821,3 +8823,1769 @@
>>>                 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)
>>> +
>>> +
>>> +/* 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;
>>> +}
>>> +
>>> +/* Handling ARM extension space insns.  */
>>> +
>>> +static int
>>> +handle_extension_space (insn_decode_record *arm_insn_r)
>>> +{
>>> +  uint32_t ret = 0;
>>> +  uint32_t opcode1 = 0, opcode2 = 0;
>>> +
>>> +  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.  */
>>> +    }
>>> +
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> +  if (!opcode1 && (9 == opcode2))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle arithmetic insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>>> +
>>> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>>> +
>>> {
>>> +      ret = -1;
>>> +      /* Handle control insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>>> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>>> +                 && bit (arm_insn_r->arm_insn, 4))
>>> +    {
>>> +      ret = -1;
>>> +      /* Handle load/store insn extension space.  */
>>> +    }
>>> +
>>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>>> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>>> +    {
>>> +      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 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
>>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>>> +  uint32_t
>>> record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +
>>> +  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;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +
>>> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly */
>>> +      /* What if 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)
>>> +           let us begin according to addressing modes for store insns
>>> +           STRH insn, addresing modes are taken following.  */
>>> +    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_buf[0].unsigned_regval);
>>> +        if (15 == reg_src1)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +          }
>>> +        offset_8 = (immed_high << 4) |
>>> immed_low;
>>> +        /* Calculate target store address.  */
>>> +        if (14 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count =
>>> 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        if (15 == reg_src2)
>>> +          {
>>> +            /* If R15 was used as Rn, hence current PC+8.  */
>>> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +
>>> }
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if (12 == arm_insn_r->opcode)
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +
>>> record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +      }
>>> +    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_buf[0].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +
>>> }
>>> +        else
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = 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_buf[0].unsigned_regval);
>>> +        regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                    , &u_buf[1].unsigned_regval);
>>> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>>> +          {
>>> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> +          }
>>> +
>>> else
>>> +          {
>>> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> +          }
>>> +        record_buf_mem[0] = 2;
>>> +        record_buf_mem[1] = tgt_mem_addr;
>>> +        arm_insn_r->mem_rec_count = 1;
>>> +        /* Record Rn also as it changes.  */
>>> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> +        arm_insn_r->reg_rec_count = 1;
>>> +
>>> }
>>> +    /* DSP insns  (e.g. LDRD)  TBD.  */
>>> +  }
>>> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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 (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
>>> +    {
>>> +      /* 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_buf.unsigned_regval);
>>> +      /* U == 1 */
>>> +      if (bit (arm_insn_r->arm_insn, 23))
>>> +        {
>>> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>>> +        }
>>> +      else
>>> +        {
>>> +         tgt_mem_addr = u_buf.unsigned_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:
>>> +
>>> +            /* STR insn, STRT insn.  */
>>> +            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:
>>> +            /* STRB insn, STRBT insn.  */
>>> +            record_buf_mem[0] = 1;
>>> +          break;
>>> +
>>> +          default:
>>> +            return -1;
>>> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>>> +  uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> +  struct
>>> +    {
>>> +      LONGEST signed_word;
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0, sizeof (u_buf));
>>> +  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,
>>> +        let us begin 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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          if (15 == reg_src2)
>>> +            {
>>> +              /* If R15 was used as Rn, hence current PC+8.  */
>>> +              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
>>> +              u_buf[0].unsigned_regval =
>>> u_buf[0].unsigned_regval + 8;
>>> +            }
>>> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
>>> +          /* U == 1.  */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[0].unsigned_regval +
>>> +                             u_buf[1].unsigned_regval;
>>> +
>>> }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval -
>>> +                             u_buf[0].unsigned_regval;
>>> +            }
>>> +
>>> +          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:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.  */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +
>>> default:
>>> +                return -1;
>>> +              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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_signed (reg_cache, reg_src1
>>> +                                      ,
>>> &u_buf[0].signed_word);
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* Offset_12 used as shift.  */
>>> +          switch (offset_12)
>>> +            {
>>> +              case 0:
>>> +                /* Offset_12 used as index.
>>> */
>>> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
>>> +              break;
>>> +
>>> +              case 1:
>>> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>>> +              break;
>>> +
>>> +              case 2:
>>> +                if
>>> (!shift_imm)
>>> +                  {
>>> +                    if (bit (u_buf[0].unsigned_regval, 31))
>>> +                      {
>>> +                        offset_12 = 0xFFFFFFFF;
>>> +                      }
>>> +
>>> else
>>> +                      {
>>> +                        offset_12 = 0;
>>> +                      }
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    /* This is arithmetic shift.
>>> */
>>> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
>>> +                  }
>>> +                break;
>>> +
>>> +              case 3:
>>> +                if (!shift_imm)
>>> +                  {
>>> +                    regcache_raw_read_unsigned (reg_cache,
>>> ARM_PS_REGNUM
>>> +                                                , &u_buf[1].unsigned_regval);
>>> +                    /* Get C flag value and shift it by 31.  */
>>> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>>> +                                  | (u_buf[0].unsigned_regval) >>
>>> 1);
>>> +                  }
>>> +                else
>>> +                  {
>>> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>>> +                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>>> +
>>> }
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              break;
>>> +            }
>>> +
>>> +          regcache_raw_read_unsigned (reg_cache, reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          /* U == 1
>>> */
>>> +          if (bit (arm_insn_r->arm_insn, 23))
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>>> +            }
>>> +          else
>>> +            {
>>> +              tgt_mem_addr = u_buf[1].unsigned_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 0:
>>> +          case 4:
>>> +                /* STR insn, STRT insn.  */
>>> +                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:
>>> +                /* STRB insn, STRBT insn.
>>> */
>>> +                record_buf_mem[0] = 1;
>>> +              break;
>>> +
>>> +              default:
>>> +                return -1;
>>> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
>>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>>> +  uint32_t start_address = 0, index = 0;
>>> +  uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>> +
>>> +  memset (&u_buf, 0,
>>> sizeof(u_buf));
>>> +
>>> +  /* 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 optmization.  */
>>> +
>>> +  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 optmization.  */
>>> +        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_buf[0].unsigned_regval);
>>> +    while (register_bits)
>>> +      {
>>> +        if (register_bits & 0x00000001)
>>> +           register_count++;
>>> +        register_bits = register_bits >> 1;
>>> +      }
>>> +
>>> +    switch (addr_mode)
>>> +      {
>>> +        /* Decrement after.  */
>>> +        case 0:
>>> +          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
>>> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
>>> +          return -1;
>>> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +
>>> +  uint32_t record_buf[8];
>>> +
>>> +  /* Handle B, BL, BLX(1) insns.  */
>>> +  /* Wihtout optmization we save link register,
>>> +        CSPR for the insn which changes T bit.  */
>>> +  record_buf[0] = ARM_PS_REGNUM;
>>> +  record_buf[1] = ARM_LR_REGNUM;
>>> +  arm_insn_r->reg_rec_count = 2;
>>> +
>>> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>>> +
>>> +  return 0;
>>> +}
>>> +
>>> +/* Handling opcode 110 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +  printf_unfiltered (_("Process record does not support instruction
>>> "
>>> +                     "0x%0x at address %s.\n"),
>>> +                     arm_insn_r->arm_insn,
>>> +                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>>> +
>>> +   return -1;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> +   uint32_t shift_imm = 0;
>>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>>> 0;
>>> +   uint32_t start_address = 0;
>>> +
>>> +   /* 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)
>>> +          {
>>> +            tdep->arm_swi_record(reg_cache);
>>> +          }
>>> +        else
>>> +          {
>>> +            printf_unfiltered (_("no syscall record
>>> support\n"));
>>> +            return -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 -1;
>>> +}
>>> +
>>> +/* Handling opcode 000 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
>>> +
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +      gdb_byte buf[4];
>>> +    } u_buf[2];
>>> +
>>> +  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_buf[0].unsigned_regval);
>>> +          regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> +                                      , &u_buf[1].unsigned_regval);
>>> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 4;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
>>> +      record_buf_mem[0] = 2;
>>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  struct regcache *reg_cache = thumb_insn_r->regcache;
>>> +
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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.  */
>>> +      /* Accorindly to high vector configuration PC is set accordingly.  */
>>> +      /* FIX ME ?  what if 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;
>>> +      thumb_insn_r->reg_rec_count = 2;
>>> +      /* Save SPSR also; how?.  */
>>> +      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_handle_swi_insn (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 reg_val1 = 0;
>>> +  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];
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  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_buf.unsigned_regval);
>>> +      while (register_bits)
>>> +        {
>>> +          if (register_bits & 0x00000001)
>>> +             register_count++;
>>> +          register_bits = register_bits >> 1;
>>> +        }
>>> +      start_address = u_buf.unsigned_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)
>>> +          {
>>> +            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 0;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns.  */
>>> +
>>> +static int
>>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> +  uint32_t record_buf[8];
>>> +  uint32_t reg_val1 = 0;
>>> +  uint32_t reg_src1 = 0;
>>> +
>>> uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> +  /* BL , 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;
>>> +}
>>> +
>>> +
>>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
>>> +
>>> +static int
>>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>>> +{
>>> +
>>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
>>> +  static int (*const arm_handle_insn[8])
>>> +                                      (insn_decode_record*) =
>>> +  {
>>> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
>>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>>> +      arm_handle_ld_st_multiple_insn,           /* 100.
>>> */
>>> +      arm_handle_brn_insn,                      /* 101.  */
>>> +      arm_handle_coproc_insn,                   /* 110.  */
>>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>>> +  };
>>> +
>>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
>>> +  static int (*const thumb_handle_insn[8])
>>> +
>>> (insn_decode_record*) =
>>> +  { \
>>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>>> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
>>> +      thumb_handle_misc_insn,                  /* 101.  */
>>> +
>>> thumb_handle_swi_insn,                   /* 110.  */
>>> +      thumb_handle_branch_insn                 /* 111.  */
>>> +  };
>>> +
>>> +  struct
>>> +    {
>>> +      gdb_byte buf[insn_size];
>>> +    } u_buf;
>>> +
>>> +  uint32_t ret=0, insn_id = 0;
>>> +
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>>> +      arm_record->cond = bits (arm_record->arm_insn, 28,
>>> 31);
>>> +      insn_id = bits (arm_record->arm_insn, 25, 27);
>>> +      ret = (0x0F != arm_record->cond)
>>> +            ? arm_handle_insn[insn_id] (arm_record)
>>> +            : handle_extension_space (arm_record);
>>> +    }
>>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* As thumb does not have condition codes, following field is useless.  */
>>> +      arm_record->cond = -1;
>>> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>>> (arm_record->gdbarch));
>>> +
>>> +      insn_id = bits (arm_record->arm_insn, 13, 15);
>>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>>> +    }
>>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>>> +    {
>>> +      /* Yet to be implemented; handle thumb2 part here.  */
>>> +      printf_unfiltered (_("Process record does not support 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 (0);
>>> +    }
>>> +
>>> +  return ret;
>>> +}
>>> +
>>> +/* 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;
>>> +  ULONGEST t_bit = 0;
>>> +
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf;
>>> +
>>> +  insn_decode_record arm_record;
>>> +  memset (&u_buf, 0, sizeof(u_buf));
>>> +
>>> +  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));
>>> +    }
>>> +
>>> +  /* 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_buf.unsigned_regval);
>>> +
>>> +  if (!(u_buf.unsigned_regval & t_bit))
>>> +    {
>>> +      /* We are decoding arm
>>> insn.  */
>>> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>>> +    }
>>> +  else
>>> +    {
>>> +      /* We are decoding thumb insn.  */
>>> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>>> +    }
>>> +
>>> +  if (0 == ret)
>>> +    {
>>> +      /* Record registers.  */
>>> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>>> +      if (arm_record.arm_regs)
>>> +        {
>>> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>>> +
>>> {
>>> +              if (record_arch_list_add_reg (arm_record.regcache \
>>> +                                           , (arm_record.arm_regs[no_of_rec])))
>>> +              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_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_arch_list_add_end ())
>>> +        ret = -1;
>>> +    }
>>> +
>>> +  if (arm_record.arm_regs)
>>> +    xfree (arm_record.arm_regs);
>>> +  if
>>> (arm_record.arm_mems)
>>> +    xfree (arm_record.arm_mems);
>>> +
>>> +  return ret;
>>> +}
>>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>>> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
>>> @@ -201,6 +201,9 @@
>>>    /* Return the expected next PC if FRAME is stopped at a syscall
>>>       instruction.  */
>>>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>>> +
>>> +   /* Parse swi insn args, sycall record.  */
>>> +  int (*arm_swi_record) (struct regcache *regcache);
>>>  };
>>>
>>>  /* Structures used for displaced stepping.  */
>>> @@ -331,6 +334,8 @@
>>>     instruction?  */
>>>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>>
>>> +extern int arm_process_record (struct
>>> gdbarch *gdbarch,
>>> +                               struct regcache *regcache, CORE_ADDR addr);
>>>  /* Functions exported from armbsd-tdep.h.  */
>>>
>>>  /* Return the appropriate register set for the core section identified
>>>
>>>
>>>
>>>
>>> ________________________________
>>> From: Tom Tromey <tromey@redhat.com>
>>> To: paawan oza <paawan1982@yahoo.com>
>>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>>> Sent: Wednesday, 13 July 2011 1:29 AM
>>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>
>>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>>
>>> Oza> any more comments are welcome make this patch ok, if ARM person can
>>> Oza> have a look at it it would be great.
>>>
>>> You have submitted this patch many times now and nobody has commented
>>> on the details of the ARM decoding.  I think we should proceed on the
>>> theory that this is simply not going to happen.
>>>
>>> Also, I am not as concerned about the correctness of every detail as I
>>> am about the general maintainability and style of the code.  I expect
>>> there will be bugs; those can be fixed.
>>>
>>> You need a ChangeLog entry.  A patch of this magnitude
>>> should also have
>>> a NEWS entry.
>>>
>>> Some kind of testing would be good.  Do the existing tests in
>>> gdb.reverse work with your port?  If so then I think that is sufficient
>>>
>>> Oza> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>>>
>>> Just write   unsigned int reg_len = LENGTH;
>>>
>>> Oza> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>>
>>> Mind the spaces and parens.  Better, use XNEWVEC:
>>>
>>>     REGS = XNEWVEC (uint32_t, reg_len);
>>>
>>> Oza> +        while (reg_len) \
>>> Oza> +          { \
>>> Oza> +            REGS[reg_len - 1] = RECORD_BUF[reg_len - 1];  \
>>> Oza> +            reg_len--;  \
>>> Oza> +          } \
>>>
>>> Just use memcpy.
>>>
>>> Oza> +#define
>>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>>
>>> The same comments apply for this macro.
>>>
>>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>>> Oza> (before entry to
>>>
>>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>>> Oza> (on return from
>>>
>>> Your email got corrupted.  Usually this is some bad MUA setting.
>>>
>>> Oza> +  uint32_t mem_rec_count;       /* No of mem recors */
>>>
>>> Typo, "recors"
>>>
>>> Oza> +/* Checks ARM SBZ and SBO mendatory fields.  */
>>>
>>> Typo, should be "mandatory".
>>>
>>> Oza> +  if(!sbo)
>>>
>>> Spacing.
>>>
>>> Oza> +  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>>
>>> Over-parenthesizing makes the code harder to read.  Please fix this.  I
>>> noticed it in many places.  This specific case should read:
>>>
>>>   if (3 == opcode1 && bit
>>> (arm_insn_r->arm_insn, 4))
>>>
>>> Oza> +  memset(&u_buf, 0, sizeof (u_buf));
>>>
>>> Spacing.  Just go through the entire patch and fix all the spacing
>>> issues.
>>>
>>> I feel like I have mentioned this before.
>>>
>>> Oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>>> Oza> +                                  , &u_buf[0].unsigned_regval);
>>>
>>> What if this does not return REG_VALID?
>>> There are multiple instances of this.
>>>
>>> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>>
>>> It seems wrong to use an assert in this code.  At least, it is not
>>> obvious to me that this represents a logic error in gdb as opposed to a
>>> merely unrecognized instruction.  An unrecognized instruction can occur
>>> for many reasons, e.g., a bad jump.
>>>
>>> Oza> +
>>>   if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>>> Oza> +      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>>> Oza> +      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> Oza> +      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> Oza> +      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> Oza> +      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> Oza> +      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> Oza> +      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>>
>>> This reads very oddly.  Is there a particular reason behind the ordering
>>> (if so -- document).  If not, isn't
>>> this:
>>>
>>>   if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>>
>>> There are other odd-looking conditions like this.
>>>
>>> Oza> +              default:
>>> Oza> +                gdb_assert_not_reached ("Invalid addressing mode for insn");
>>>
>>> Again, assert seems wrong.
>>>
>>> I'm afraid I ran out of steam here.  Please fix all the issues already
>>> noted and look at the rest of the patch with a critical eye to see what
>>> else should be cleaned up.  I want this patch to go in, but first it
>>> must comply to the usual gdb standards.
>>>
>>> Tom
>>>
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete> how to go ahead ?
  2011-10-11 18:11                     ` [PATCH] arm reversible : <phase_2_complete> how to go ahead ? paawan oza
@ 2011-10-11 19:02                       ` Tom Tromey
  0 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-10-11 19:02 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> please guide as how do we go ahead about checking in the patch.

I'll read it sometime this week.

While I appreciate frequent pings, I think more than once a week is
likely to be counterproductive.  Thanks.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-09-19  7:37         ` paawan oza
  2011-09-22 17:12           ` oza Pawandeep
@ 2011-10-14 20:13           ` Tom Tromey
  2011-10-15  3:46             ` paawan oza
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-10-14 20:13 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> Thanks Chandra for doing testing and working on porintg x86 tcl test
Oza> cases to arm reversible.
Oza> please find the latest version of the patch after fixing couple of
Oza> bugs and review comment fix from Tom.

Your patch got mangled somehow.
It wraps in various places, making it very hard to read.
Could you somehow fix this up and repost it?  Thanks.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-14 20:13           ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
@ 2011-10-15  3:46             ` paawan oza
  2011-10-15  7:01               ` chandra krishnappa
                                 ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: paawan oza @ 2011-10-15  3:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa

please find the patch below.

PATCH STARTS
------------------------


diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -8821,3 +8823,1769 @@
                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)
+
+
+/* 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;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if (!opcode1 && (9 == opcode2))
+    {
+      ret = -1;
+      /* Handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+    {
+      ret = -1;
+      /* Handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+                 && bit (arm_insn_r->arm_insn, 4))
+    {
+      ret = -1;
+      /* Handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+    {
+      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 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 
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+
+  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* Accorindly to high vector configuration PC is set accordingly */
+      /* What if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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_buf[0].unsigned_regval);            
+        if (15 == reg_src1)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* Calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);                        
+        if (15 == reg_src2)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = 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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns  (e.g. LDRD)  TBD.  */
+  }  
+  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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 (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
+    {
+      /* 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_buf.unsigned_regval);
+      /* U == 1 */
+      if (bit (arm_insn_r->arm_insn, 23))
+        {   
+          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+        }
+      else
+        {
+         tgt_mem_addr = u_buf.unsigned_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:
+              
+            /* STR insn, STRT insn.  */
+            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:
+            /* STRB insn, STRBT insn.  */
+            record_buf_mem[0] = 1;    
+          break;   
+
+          default:
+            return -1;
+          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      LONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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,
+        let us begin 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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);                        
+          if (15 == reg_src2)
+            {
+              /* If R15 was used as Rn, hence current PC+8.  */
+              /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+              u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+            }            
+          /* Calculate target store address, Rn +/- Rm, register offset.  */
+          /* U == 1.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[0].unsigned_regval + 
+                             u_buf[1].unsigned_regval;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval - 
+                             u_buf[0].unsigned_regval;
+            }            
+
+          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:
+                /* STR insn, STRT insn.  */
+                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:
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                return -1;
+              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_buf[0].unsigned_regval);
+          regcache_raw_read_signed (reg_cache, reg_src1
+                                      , &u_buf[0].signed_word);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);   
+          /* Offset_12 used as shift.  */
+          switch (offset_12)
+            {
+              case 0:
+                /* Offset_12 used as index.  */
+                offset_12 = u_buf[0].unsigned_regval << shift_imm;
+              break;
+              
+              case 1:
+                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm; 
+              break;
+              
+              case 2:
+                if (!shift_imm)
+                  {
+                    if (bit (u_buf[0].unsigned_regval, 31))
+                      {
+                        offset_12 = 0xFFFFFFFF;
+                      }
+                    else
+                      {
+                        offset_12 = 0;
+                      }
+                  }
+                else
+                  {
+                    /* This is arithmetic shift.  */
+                    offset_12 = u_buf[0].signed_word >> shift_imm;
+                  }
+                break;  
+                
+              case 3:
+                if (!shift_imm)
+                  {
+                    regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+                                                , &u_buf[1].unsigned_regval);
+                    /* Get C flag value and shift it by 31.  */
+                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+                                  | (u_buf[0].unsigned_regval) >> 1);
+                  }
+                else
+                  {                      
+                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                       | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
+                  }
+              break;
+
+              default:
+                return -1;
+              break;
+            }      
+
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval); 
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_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 0:
+          case 4:  
+                /* STR insn, STRT insn.  */
+                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:
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                return -1;
+              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch (addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
+          return -1;
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* Handle B, BL, BLX(1) insns.  */
+  /* Wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* Handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction "
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;   
+}
+
+/* Handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 
+          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* Accorindly to high vector configuration PC is set accordingly.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also; how?.  */
+      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_handle_swi_insn (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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
+  static int (*const arm_handle_insn[8]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
+  static int (*const thumb_handle_insn[8]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) 
+            ? arm_handle_insn[insn_id] (arm_record) 
+            : handle_extension_space (arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  */
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* Yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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 (0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* 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_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* We are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
 
+extern int arm_process_record (struct gdbarch *gdbarch, 
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15  3:46             ` paawan oza
@ 2011-10-15  7:01               ` chandra krishnappa
  2011-10-15  9:32               ` Yao Qi
  2011-10-16 23:32               ` Petr Hluzín
  2 siblings, 0 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-10-15  7:01 UTC (permalink / raw)
  To: Tom Tromey, paawan oza; +Cc: gdb-patches, Petr Hluzín


Oza,

I guess this <below code snippet> phase_2 code require further testing.. are there any changes for what I tested previously?

Also can you suggest if test scripts are written once for all once your complete phase_3 is completed. i.e the syscall functions code is implemented for reversible debugging.

I am trying to buy some time till phase_3 code implementation. Please advice.

Thanks & Regards,
-Chandra K


--- On Sat, 10/15/11, paawan oza <paawan1982@yahoo.com> wrote:

> From: paawan oza <paawan1982@yahoo.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "Tom Tromey" <tromey@redhat.com>
> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Petr Hluzín" <petr.hluzin@gmail.com>, "chandra krishnappa" <chandra_roadking@yahoo.com>
> Date: Saturday, October 15, 2011, 9:15 AM
> please find the patch below.
> 
> PATCH STARTS
> ------------------------
> 
> 
> diff -urN arm_orig/arm-linux-tdep.c
> arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c    2011-07-28
> 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-07-28
> 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
>    set_gdbarch_fetch_tls_load_module_address (gdbarch,
>                                              
> svr4_fetch_objfile_link_map);
>  
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch,
> arm_process_record);
> +
>    tramp_frame_prepend_unwinder (gdbarch,
>                 
> &arm_linux_sigreturn_tramp_frame);
>    tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>  
>  
>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
>  
>  /* Provide a prototype to silence -Wmissing-prototypes. 
> */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000
> +0530
> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000
> +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
>  
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
>  
>  static int arm_debug;
> @@ -8821,3 +8823,1769 @@
>                 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)
> +
> +
> +/* 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;
> +}
> +
> +/* Handling ARM extension space insns.  */
> +
> +static int 
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{  
> +  uint32_t ret = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  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.  */
> +    }
> +  
> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +  
> +  if (!opcode1 && (9 == opcode2))
> +    {
> +      ret = -1;
> +      /* Handle arithmetic insn extension space. 
> */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> +  if (!opcode1 && (2 == opcode2) && !bit
> (arm_insn_r->arm_insn, 20))
> +    {
> +      ret = -1;
> +      /* Handle control insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> +  if (!opcode1 && bit (arm_insn_r->arm_insn,
> 7) \
> +                 && bit
> (arm_insn_r->arm_insn, 4))
> +    {
> +      ret = -1;
> +      /* Handle load/store insn extension space. 
> */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && bit
> (arm_insn_r->arm_insn, 21))
> +    {
> +      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 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 
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
> *arm_insn_r)
> +{
> +  struct regcache *reg_cache = arm_insn_r->regcache;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +
> +  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;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +
> +  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
> preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
> +      /* Accorindly to high vector configuration PC
> is set accordingly */
> +      /* What if 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) 
> +           let us begin according to addressing
> modes for store insns 
> +           STRH insn, addresing modes are taken
> following.  */
> +    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_buf[0].unsigned_regval);            
> +        if (15 == reg_src1)
> +          {
> +            /* If R15 was used as Rn, hence
> current PC+8.  */
> +            u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +          }            
> +        offset_8 = (immed_high << 4) |
> immed_low;
> +        /* Calculate target store address.  */
> +        if (14 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                   
> ,
> &u_buf[1].unsigned_regval);                       
> 
> +        if (15 == reg_src2)
> +          {
> +            /* If R15 was used as Rn, hence
> current PC+8.  */
> +            u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +          }            
> +        /* Calculate target store address, Rn +/-
> Rm, register offset.  */
> +        if (12 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr =
> u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        /* Calculate target store address, Rn +/-
> Rm, register offset.  */
> +        if ((15 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval - offset_8;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = 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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                   
> , &u_buf[1].unsigned_regval);
> +        /* Calculate target store address, Rn +/-
> Rm, register offset.  */
> +        if ((13 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr =
> u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr =
> u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);             
> 
> +        arm_insn_r->reg_rec_count = 1;
> +      }
> +    /* DSP insns  (e.g. LDRD)  TBD.  */
> +  }  
> +  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_handle_data_proc_imm_insn (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_handle_ld_st_imm_offset_insn (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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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 (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
> +    {
> +      /* 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_buf.unsigned_regval);
> +      /* U == 1 */
> +      if (bit (arm_insn_r->arm_insn, 23))
> +        {   
> +          tgt_mem_addr = u_buf.unsigned_regval +
> offset_12;
> +        }
> +      else
> +        {
> +         tgt_mem_addr = u_buf.unsigned_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:
> +              
> +            /* STR insn, STRT insn.  */
> +            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:
> +            /* STRB insn, STRBT insn.  */
> +            record_buf_mem[0] = 1;    
> +          break;   
> +
> +          default:
> +            return -1;
> +          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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0,
> tgt_mem_addr = 0;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      LONGEST signed_word;
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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,
> +        let us begin 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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                     
> ,
> &u_buf[1].unsigned_regval);                       
> 
> +          if (15 == reg_src2)
> +            {
> +              /* If R15 was used as Rn, hence
> current PC+8.  */
> +              /* Pre-indexed mode doesnt
> reach here ; illegal insn.  */
> +              u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +            }            
> +          /* Calculate target store address, Rn
> +/- Rm, register offset.  */
> +          /* U == 1.  */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr =
> u_buf[0].unsigned_regval + 
> +                            
> u_buf[1].unsigned_regval;
> +            }
> +          else
> +            {
> +              tgt_mem_addr =
> u_buf[1].unsigned_regval - 
> +                            
> u_buf[0].unsigned_regval;
> +            }            
> +
> +          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:
> +                /* STR insn, STRT insn. 
> */
> +                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:
> +                /* STRB insn, STRBT insn. 
> */
> +                record_buf_mem[0] =
> 1;    
> +              break;   
> +
> +              default:
> +                return -1;
> +              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_buf[0].unsigned_regval);
> +          regcache_raw_read_signed (reg_cache,
> reg_src1
> +                                     
> , &u_buf[0].signed_word);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                     
> , &u_buf[1].unsigned_regval);   
> +          /* Offset_12 used as shift.  */
> +          switch (offset_12)
> +            {
> +              case 0:
> +                /* Offset_12 used as
> index.  */
> +                offset_12 =
> u_buf[0].unsigned_regval << shift_imm;
> +              break;
> +              
> +              case 1:
> +                offset_12 =
> (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
> 
> +              break;
> +              
> +              case 2:
> +                if (!shift_imm)
> +                  {
> +                    if (bit
> (u_buf[0].unsigned_regval, 31))
> +                      {
> +                        offset_12 =
> 0xFFFFFFFF;
> +                      }
> +                    else
> +                      {
> +                        offset_12 =
> 0;
> +                      }
> +                  }
> +                else
> +                  {
> +                    /* This is
> arithmetic shift.  */
> +                    offset_12 =
> u_buf[0].signed_word >> shift_imm;
> +                  }
> +                break;  
> +                
> +              case 3:
> +                if (!shift_imm)
> +                  {
> +                   
> regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> +                                               
> , &u_buf[1].unsigned_regval);
> +                    /* Get C flag value
> and shift it by 31.  */
> +                    offset_12 = (((bit
> (u_buf[1].unsigned_regval, 29)) << 31) \
> +                                 
> | (u_buf[0].unsigned_regval) >> 1);
> +                  }
> +                else
> +                 
> {                      
> +                    offset_12 =
> (u_buf[0].unsigned_regval >> shift_imm) \
> +                       |
> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
> shift_imm));
> +                  }
> +              break;
> +
> +              default:
> +                return -1;
> +              break;
> +            }      
> +
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                     
> , &u_buf[1].unsigned_regval); 
> +          /* U == 1 */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr =
> u_buf[1].unsigned_regval + offset_12;
> +            }
> +          else
> +            {
> +              tgt_mem_addr =
> u_buf[1].unsigned_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 0:
> +          case 4:  
> +                /* STR insn, STRT insn. 
> */
> +                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:
> +                /* STRB insn, STRBT insn. 
> */
> +                record_buf_mem[0] =
> 1;    
> +              break;   
> +
> +              default:
> +                return -1;
> +              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_handle_ld_st_multiple_insn (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 shift_imm = 0;
> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
> no_of_regs = 0;
> +  uint32_t start_address = 0, index = 0;
> +  uint32_t record_buf[24], record_buf_mem[48];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  /* 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 optmization.  */
> +
> +  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 optmization.  */
> +        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_buf[0].unsigned_regval);
> +    while (register_bits)
> +      {
> +        if (register_bits & 0x00000001)
> +           register_count++;
> +        register_bits = register_bits >> 1;
> +      }
> +
> +    switch (addr_mode)
> +      {
> +        /* Decrement after.  */ 
> +        case 0:                 
>         
> +          start_address =
> (u_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval;
> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
> +          return -1;
> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> +  uint32_t record_buf[8];
> +
> +  /* Handle B, BL, BLX(1) insns.  */
> +  /* Wihtout optmization we save link register, 
> +        CSPR for the insn which changes T bit. 
> */
> +  record_buf[0] = ARM_PS_REGNUM;
> +  record_buf[1] = ARM_LR_REGNUM;
> +  arm_insn_r->reg_rec_count = 2;  
> +
> +  REG_ALLOC (arm_insn_r->arm_regs,
> arm_insn_r->reg_rec_count, record_buf);
> +    
> +  return 0;
> +}
> +
> +/* Handling opcode 110 insns.  */
> +
> +static int 
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> +  printf_unfiltered (_("Process record does not support
> instruction "
> +                     "0x%0x at address
> %s.\n"),
> +                    
> arm_insn_r->arm_insn,
> +                     paddress
> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
> +
> +   return -1;   
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int 
> +arm_handle_coproc_data_proc_insn (insn_decode_record
> *arm_insn_r)
> +{
> +   struct gdbarch_tdep *tdep = gdbarch_tdep
> (arm_insn_r->gdbarch);
> +   struct regcache *reg_cache =
> arm_insn_r->regcache;
> +   
> +   uint32_t shift_imm = 0;
> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
> +   uint32_t start_address = 0;
> +
> +   /* 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)
> +          {
> +           
> tdep->arm_swi_record(reg_cache);
> +          }
> +        else
> +          {
> +            printf_unfiltered (_("no syscall
> record support\n"));
> +            return -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 -1;   
> +}
> +
> +/* Handling opcode 000 insns.  */
> +
> +static int 
> +thumb_handle_shift_add_sub_insn (insn_decode_record
> *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_src1 = 0;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
> +
> +  
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +      gdb_byte buf[4];
> +    } u_buf[2];
> +
> +  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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                     
> , &u_buf[1].unsigned_regval);
> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 
> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
> +      record_buf_mem[0] = 2;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> +  struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +  
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
> = 0, immed_5 = 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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >>
> 1;
> +        }
> +      start_address = u_buf.unsigned_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.  */
> +      /* Accorindly to high vector configuration PC
> is set accordingly.  */
> +      /* FIX ME ?  what if 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;
> +      thumb_insn_r->reg_rec_count = 2;
> +      /* Save SPSR also; how?.  */
> +      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_handle_swi_insn (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 reg_val1 = 0;
> +  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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >>
> 1;
> +        }
> +      start_address = u_buf.unsigned_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)
> +          {
> +           
> 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 0;
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int 
> +thumb_handle_branch_insn (insn_decode_record
> *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +
> +  /* BL , 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;     
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and
> opcodes; and dispatch it.  */
> +
> +static int 
> +decode_insn (insn_decode_record *arm_record, uint32_t
> insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes
> type of arm instruction.  */
> +  static int (*const arm_handle_insn[8]) 
> +                                     
> (insn_decode_record*) = 
> +  { 
> +      arm_handle_data_proc_misc_ld_str_insn,    /*
> 000.  */
> +     
> arm_handle_data_proc_imm_insn,            /*
> 001.  */
> +     
> arm_handle_ld_st_imm_offset_insn,         /* 010. 
> */
> +     
> arm_handle_ld_st_reg_offset_insn,         /* 011. 
> */  
> +     
> arm_handle_ld_st_multiple_insn,           /*
> 100.  */
> +     
> arm_handle_brn_insn,                     
> /* 101.  */
> +     
> arm_handle_coproc_insn,                  
> /* 110.  */
> +     
> arm_handle_coproc_data_proc_insn          /* 111. 
> */  
> +  };
> +  
> +  /* (Starting from numerical 0); bits 13,14,15 decodes
> type of thumb instruction.  */
> +  static int (*const thumb_handle_insn[8]) 
> +                                         
> (insn_decode_record*) =
> +  { \
> +     
> thumb_handle_shift_add_sub_insn,         /* 000. 
> */
> +      thumb_handle_add_sub_cmp_mov_insn,      
> /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,     
> /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,     
> /* 011.  */  
> +     
> thumb_handle_ld_st_stack_insn,           /* 100. 
> */
> +     
> thumb_handle_misc_insn,                  /*
> 101.  */
> +     
> thumb_handle_swi_insn,                  
> /* 110.  */
> +     
> thumb_handle_branch_insn                 /*
> 111.  */  
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +    
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr,
> &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
> +    {
> +      arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch)); 
> +      arm_record->cond = bits
> (arm_record->arm_insn, 28, 31); 
> +      insn_id = bits (arm_record->arm_insn, 25,
> 27);
> +      ret = (0x0F != arm_record->cond) 
> +            ? arm_handle_insn[insn_id]
> (arm_record) 
> +            : handle_extension_space
> (arm_record);
> +    }    
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes,
> following field is useless.  */
> +      arm_record->cond = -1;   
> +      arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> +      
> +      insn_id = bits (arm_record->arm_insn, 13,
> 15);
> +      ret = thumb_handle_insn[insn_id] (arm_record);
> +    }
> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* Yet to be implemented; handle thumb2 part
> here.  */
> +      printf_unfiltered (_("Process record does not
> support 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 (0);
> +    }
> +  
> +  return ret;
> +}
> +
> +/* 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;
> +  ULONGEST t_bit = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* 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_buf.unsigned_regval);
> +    
> +  if (!(u_buf.unsigned_regval & t_bit))
> +    {
> +      /* We are decoding arm insn.  */
> +      ret = decode_insn (&arm_record,
> ARM_INSN_SIZE_BYTES);      
> +    }
> +  else
> +    {
> +      /* We are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record,
> THUMB_INSN_SIZE_BYTES);    
> +    }
> +
> +  if (0 == ret)
> +    {
> +      /* Record registers.  */
> +      record_arch_list_add_reg (arm_record.regcache,
> ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec <
> arm_record.reg_rec_count; no_of_rec++)
> +            {
> +              if (record_arch_list_add_reg
> (arm_record.regcache \
> +                                          
> , (arm_record.arm_regs[no_of_rec])))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +  
> +  return ret; 
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000
> +0530
> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000
> +0530
> @@ -201,6 +201,9 @@
>    /* Return the expected next PC if FRAME is stopped at
> a syscall
>       instruction.  */
>    CORE_ADDR (*syscall_next_pc) (struct frame_info
> *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
>  
>  /* Structures used for displaced stepping.  */
> @@ -331,6 +334,8 @@
>     instruction?  */
>  extern int arm_pc_is_thumb (struct gdbarch *,
> CORE_ADDR);
>  
> +extern int arm_process_record (struct gdbarch *gdbarch, 
> +                              
> struct regcache *regcache, CORE_ADDR addr);
>  /* Functions exported from armbsd-tdep.h.  */
>  
>  /* Return the appropriate register set for the core
> section identified
> 
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15  3:46             ` paawan oza
  2011-10-15  7:01               ` chandra krishnappa
@ 2011-10-15  9:32               ` Yao Qi
  2011-10-15 13:33                 ` Yao Qi
  2011-11-03 17:10                 ` Tom Tromey
  2011-10-16 23:32               ` Petr Hluzín
  2 siblings, 2 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-15  9:32 UTC (permalink / raw)
  To: gdb-patches

On 10/15/2011 11:45 AM, paawan oza wrote:
> please find the patch below.
> 

I noticed that test cases in gdb.reverse are *not* enabled in default.
You need to add the following two lines in your board file to turn them on,

  set_board_info gdb,use_precord 1
  set_board_info gdb,can_reverse 1

It is good if you can post the test result in gdb.reverse so that we are
more confidient to your patch.

I am not an expert on record, so I don't have much comment on your code
logic.  However, some of my cents below.

> 
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
>    set_gdbarch_fetch_tls_load_module_address (gdbarch,
>                                               svr4_fetch_objfile_link_map);
>  
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>    tramp_frame_prepend_unwinder (gdbarch,
>                  &arm_linux_sigreturn_tramp_frame);
>    tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>  
>  
>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
>  
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c    2011-09-18 12:55:12.000000000 +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
>  
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
>  
>  static int arm_debug;
> @@ -8821,3 +8823,1769 @@
>                 NULL, /* FIXME: i18n: "ARM debugging is %s.  */
>                 &setdebuglist, &showdebuglist);
>  }

> +
> +/* 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() ).  */

These lines exceed the hard limit (80 chars).  The second line of
comment should start from column 4, like this:

/* ARM instruction ...
   and execution state ....  */

> +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;
> +}
> +
> +/* Handling ARM extension space insns.  */
> +
> +static int 
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{  
> +  uint32_t ret = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  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.  */
            ^ one redundant space.
> +    }
> +  
> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +  
> +  if (!opcode1 && (9 == opcode2))
> +    {
> +      ret = -1;
> +      /* Handle arithmetic insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> +    {
> +      ret = -1;
> +      /* Handle control insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
> +                 && bit (arm_insn_r->arm_insn, 4))
> +    {
> +      ret = -1;
> +      /* Handle load/store insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> +    {
> +      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 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 
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
> +{
> +  struct regcache *reg_cache = arm_insn_r->regcache;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +
> +  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;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +
> +  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 preccedded 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.  */

Indentation here is wrong.

> +        reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> +        if (15 != reg_dest)
               ^^ magic number here.  Use ARM_PC_REGNUM.

> +          {
> +            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 insns, changes register and memory as well.  */
                               ^^ remove "s".

> +      /* SWP or SWPB insn.  */

This line of comment is useless.

> +      /* 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_buf[0].unsigned_regval);
                                     ^ "," should go to last line.

> +      /* 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_buf[0].unsigned_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 ((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.  */
              ^^^^^^^^^^ Wrong indentation, and instances in other places.

> +        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.  */
> +      /* Accorindly to high vector configuration PC is set accordingly */
> +      /* What if 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) 
> +           let us begin according to addressing modes for store insns 
> +           STRH insn, addresing modes are taken following.  */
> +    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_buf[0].unsigned_regval);
                                       ^ "," should be put in previous line

> +        if (15 == reg_src1)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +          }            
> +        offset_8 = (immed_high << 4) | immed_low;
> +        /* Calculate target store address.  */
> +        if (14 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);                        
> +        if (15 == reg_src2)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +          }            
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if (12 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = 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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }            
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
> +        arm_insn_r->reg_rec_count = 1;
> +      }
> +    /* DSP insns  (e.g. LDRD)  TBD.  */
> +  }  
> +  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 101 insns.  */
> +
> +static int 
> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)

"arm_handle_brn_insn" is confusing, because there is no insn "brn".  I
would name this function as "arm_record_b_bl_blx".

> +{
> +
> +  uint32_t record_buf[8];
> +
> +  /* Handle B, BL, BLX(1) insns.  */
> +  /* Wihtout optmization we save link register, 
> +        CSPR for the insn which changes T bit.  */
> +  record_buf[0] = ARM_PS_REGNUM;
> +  record_buf[1] = ARM_LR_REGNUM;
> +  arm_insn_r->reg_rec_count = 2;  
                                   ^^ trail spaces, and many other places.

We don't have to record PS and LR for these three kinds of insns.  For
B, we don't have to do anything here.  We only record LR for BL and
record LS and PS for BLX.

> +
> +  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +    
> +  return 0;
> +}
> +

> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it.  */
> +
> +static int 
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction.  */
> +  static int (*const arm_handle_insn[8]) 
> +                                      (insn_decode_record*) = 
> +  { 
> +      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
> +      arm_handle_ld_st_multiple_insn,           /* 100.  */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */

I don't like the name scheme "arm_handle_xxxx_insn" of these fucntions.
 In gdb backend, we "handle" insn for many different purposees, such as
software-single-step, displaced stepping, record, and etc.  I suggest
that we name them like "arm_record_xxx" (without "_insn").


> +  };
> +  
> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction.  */
> +  static int (*const thumb_handle_insn[8]) 
> +                                          (insn_decode_record*) =
> +  { \
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
> +      thumb_handle_ld_st_stack_insn,           /* 100.  */
> +      thumb_handle_misc_insn,                  /* 101.  */
> +      thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */  
> +  };

> +
> +/* 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;
> +  ULONGEST t_bit = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* 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_buf.unsigned_regval);
> +    
> +  if (!(u_buf.unsigned_regval & t_bit))
> +    {
> +      /* We are decoding arm insn.  */
> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
> +    }
> +  else
> +    {
> +      /* We are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    

It is not correct to me.  Both thumb 16-bit and 32-bit insn are handled
here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.

> +    }
> +
> +  if (0 == ret)
> +    {
> +      /* Record registers.  */
> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
> +            {
> +              if (record_arch_list_add_reg (arm_record.regcache \
> +                                           , (arm_record.arm_regs[no_of_rec])))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +  
> +  return ret; 
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h    2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h    2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
>    /* Return the expected next PC if FRAME is stopped at a syscall
>       instruction.  */
>    CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
>  

I don't see any function is installed on this function pointer.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15  9:32               ` Yao Qi
@ 2011-10-15 13:33                 ` Yao Qi
  2011-10-15 16:34                   ` oza Pawandeep
  2011-11-03 17:10                 ` Tom Tromey
  1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-10-15 13:33 UTC (permalink / raw)
  To: gdb-patches

On 10/15/2011 05:31 PM, Yao Qi wrote:
> I noticed that test cases in gdb.reverse are *not* enabled in default.
> You need to add the following two lines in your board file to turn them on,
> 
>   set_board_info gdb,use_precord 1
>   set_board_info gdb,can_reverse 1
> 
> It is good if you can post the test result in gdb.reverse so that we are
> more confidient to your patch.
       ^^^^^^^^^^ typo "confident".

I run test cases in gdb.reverse with my own board file [1], and get
following result on x86:

		=== gdb Summary ===

# of expected passes		2774
# of unexpected failures	22

I also applied your patch, and run gdb.reverse test cases on arm natively:

		=== gdb Summary ===

# of expected passes		1180
# of unexpected failures	1090
# of expected failures		142

I don't think these fails are all related to your arm-reverse patch.
IMO, it means there are still some work to do, not only in arm bits, but
also in gdb general parts and test cases.  Sorry that I can't give any
useful suggestion here.

-- 
Yao (齐尧)

[1] My board file reverse.exp

load_generic_config "unix"
process_multilib_options ""

# The default compiler for this target.
set_board_info compiler "[find_gcc]"

set_board_info gdb,can_reverse 1
set_board_info gdb,use_precord 1

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15 13:33                 ` Yao Qi
@ 2011-10-15 16:34                   ` oza Pawandeep
  2011-10-15 17:38                     ` oza Pawandeep
  2011-10-17  3:18                     ` Yao Qi
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-15 16:34 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi Yao,

first of all thank you for your comments, will be sending the patch
soon with your comments incorporated as much as possible.
thank you again for sending test results;

I suppose failed test case might be including

1) system call support
2) signal support
3) any other linux ABI support
4) there are some programs on x86 assembly which needs to be written
for ARM and put separately.

Thanks Yao,
Oza.


On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 10/15/2011 05:31 PM, Yao Qi wrote:
>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>> You need to add the following two lines in your board file to turn them on,
>>
>>   set_board_info gdb,use_precord 1
>>   set_board_info gdb,can_reverse 1
>>
>> It is good if you can post the test result in gdb.reverse so that we are
>> more confidient to your patch.
>       ^^^^^^^^^^ typo "confident".
>
> I run test cases in gdb.reverse with my own board file [1], and get
> following result on x86:
>
>                === gdb Summary ===
>
> # of expected passes            2774
> # of unexpected failures        22
>
> I also applied your patch, and run gdb.reverse test cases on arm natively:
>
>                === gdb Summary ===
>
> # of expected passes            1180
> # of unexpected failures        1090
> # of expected failures          142
>
> I don't think these fails are all related to your arm-reverse patch.
> IMO, it means there are still some work to do, not only in arm bits, but
> also in gdb general parts and test cases.  Sorry that I can't give any
> useful suggestion here.
>
> --
> Yao (齐尧)
>
> [1] My board file reverse.exp
>
> load_generic_config "unix"
> process_multilib_options ""
>
> # The default compiler for this target.
> set_board_info compiler "[find_gcc]"
>
> set_board_info gdb,can_reverse 1
> set_board_info gdb,use_precord 1
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15 16:34                   ` oza Pawandeep
@ 2011-10-15 17:38                     ` oza Pawandeep
  2011-10-16  8:00                       ` oza Pawandeep
  2011-10-17  3:18                     ` Yao Qi
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-15 17:38 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi Yao,

I have implemented your comments, and will be sending the patch soon.

please find my comments below on some of your comments.

1) all the lines are truncated to < 80 chars now:

2) all the trailing spaces are deleted.

3) fixed indentation as much as I could find any.

4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn".  I
would name this function as "arm_record_b_bl_blx

Oza: the name is changed, and rest of the names are also changed as
you suggested.

5)
Yao:
We don't have to record PS and LR for these three kinds of insns.  For
B, we don't have to do anything here.  We only record LR for BL and
record LS and PS for BLX.

Oza: yes, but in that case we just need to handle BL insn.
because BLX(1) reside in extension space which is/should be handled
separately in function
handle_instruction_space function.

so, BLX(1) will not fall here at all.

6)
Yao: It is not correct to me.  Both thumb 16-bit and 32-bit insn are handled
here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.

Oza: yes currently we have support for only 16 bit thumb.
the moment we support 32 bit, we will have one more else case with
THUMB_FULL_INSN_SIZE_BYTES 4

it will look like this

else if (ARM_INSN_SIZE_BYTES == insn_size)
{
}
else if (THUMB_INSN_SIZE_BYTES == insn_size)
{
}
else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
{
}

name is just an example:
if we want to handle thumb in same branch then could be changed
easily, depending on the writer of the code.
but as of now code doesnt support, so havent thought about it.

7) Yao: I don't see any function is installed on this function pointer.

Oza: yes, because phase 3 implementation is still pending which is
supposed to include system call function pointer and support of
syscall reverse.

Regards,
Oza.



On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> first of all thank you for your comments, will be sending the patch
> soon with your comments incorporated as much as possible.
> thank you again for sending test results;
>
> I suppose failed test case might be including
>
> 1) system call support
> 2) signal support
> 3) any other linux ABI support
> 4) there are some programs on x86 assembly which needs to be written
> for ARM and put separately.
>
> Thanks Yao,
> Oza.
>
>
> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>> You need to add the following two lines in your board file to turn them on,
>>>
>>>   set_board_info gdb,use_precord 1
>>>   set_board_info gdb,can_reverse 1
>>>
>>> It is good if you can post the test result in gdb.reverse so that we are
>>> more confidient to your patch.
>>       ^^^^^^^^^^ typo "confident".
>>
>> I run test cases in gdb.reverse with my own board file [1], and get
>> following result on x86:
>>
>>                === gdb Summary ===
>>
>> # of expected passes            2774
>> # of unexpected failures        22
>>
>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>
>>                === gdb Summary ===
>>
>> # of expected passes            1180
>> # of unexpected failures        1090
>> # of expected failures          142
>>
>> I don't think these fails are all related to your arm-reverse patch.
>> IMO, it means there are still some work to do, not only in arm bits, but
>> also in gdb general parts and test cases.  Sorry that I can't give any
>> useful suggestion here.
>>
>> --
>> Yao (齐尧)
>>
>> [1] My board file reverse.exp
>>
>> load_generic_config "unix"
>> process_multilib_options ""
>>
>> # The default compiler for this target.
>> set_board_info compiler "[find_gcc]"
>>
>> set_board_info gdb,can_reverse 1
>> set_board_info gdb,use_precord 1
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15 17:38                     ` oza Pawandeep
@ 2011-10-16  8:00                       ` oza Pawandeep
  2011-10-16  8:44                         ` oza Pawandeep
  2011-10-17  4:25                         ` Yao Qi
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-16  8:00 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi,

please find the updated patch with Yao's comments.

PATCH STARTS
--------------------------------

diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c	2011-10-16 10:25:10.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,1772 @@
 			   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)
+
+
+/* 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;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (!opcode1 && (9 == opcode2))
+    {
+      ret = -1;
+      /* Handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+    {
+      ret = -1;
+      /* Handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+                 && bit (arm_insn_r->arm_insn, 4))
+    {
+      ret = -1;
+      /* Handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+    {
+      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 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
+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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+
+  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 preccedded 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* Accorindly to high vector configuration PC is set accordingly */
+      /* What if 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)
+    let us begin according to addressing modes for store insns
+    STRH insn, addresing modes are taken following.  */
+    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_buf[0].unsigned_regval);
+        if (15 == reg_src1)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }
+        offset_8 = (immed_high << 4) | immed_low;
+        /* Calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        if (15 == reg_src2)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = 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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns  (e.g. LDRD)  TBD.  */
+  }
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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_buf.unsigned_regval);
+      /* U == 1 */
+      if (bit (arm_insn_r->arm_insn, 23))
+        {
+          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+        }
+      else
+        {
+         tgt_mem_addr = u_buf.unsigned_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:
+            return -1;
+          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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      LONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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,
+  let us begin 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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          if (15 == reg_src2)
+            {
+   	      /* If R15 was used as Rn, hence current PC+8.  */
+	      /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+              u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+            }
+          /* Calculate target store address, Rn +/- Rm, register offset.  */
+          /* U == 1.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[0].unsigned_regval +
+                             u_buf[1].unsigned_regval;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval -
+                             u_buf[0].unsigned_regval;
+            }
+
+          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:
+                return -1;
+              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_buf[0].unsigned_regval);
+          regcache_raw_read_signed (reg_cache, reg_src1
+                                      , &u_buf[0].signed_word);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          /* Offset_12 used as shift.  */
+          switch (offset_12)
+            {
+              case 0:
+                /* Offset_12 used as index.  */
+                offset_12 = u_buf[0].unsigned_regval << shift_imm;
+              break;
+
+              case 1:
+                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
+                                                             shift_imm;
+              break;
+
+              case 2:
+                if (!shift_imm)
+                  {
+                    if (bit (u_buf[0].unsigned_regval, 31))
+                      {
+                        offset_12 = 0xFFFFFFFF;
+                      }
+                    else
+                      {
+                        offset_12 = 0;
+                      }
+                  }
+                else
+                  {
+                    /* This is arithmetic shift.  */
+                    offset_12 = u_buf[0].signed_word >> shift_imm;
+                  }
+                break;
+
+              case 3:
+                if (!shift_imm)
+                  {
+                    regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+                                                , &u_buf[1].unsigned_regval);
+                    /* Get C flag value and shift it by 31.  */
+                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+                                  | (u_buf[0].unsigned_regval) >> 1);
+                  }
+                else
+                  {
+                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                                | (u_buf[0].unsigned_regval <<
+                                (sizeof(uint32_t) - shift_imm));
+                  }
+              break;
+
+              default:
+                return -1;
+              break;
+            }
+
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_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 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:
+                return -1;
+              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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch (addr_mode)
+      {
+        /* Decrement after.  */
+        case 0:		  				
+          start_address = (u_buf[0].unsigned_regval) -
(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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
+          return -1;
+        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 shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;
+}
+
+/* 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;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+          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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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 reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* Accorindly to high vector configuration PC is set accordingly.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also; how?.  */
+      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_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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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; 	
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it.  */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction.  */
+  static int (*const arm_handle_insn[8])
+                                      (insn_decode_record*) =
+  {
+      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 int (*const thumb_handle_insn[8])
+                                          (insn_decode_record*) =
+  { \
+      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_swi,                          /* 110.  */
+      thumb_record_branch                      /* 111.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)
+            ? arm_handle_insn[insn_id] (arm_record)
+            : handle_extension_space (arm_record);
+    }
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is
useless.  */
+      arm_record->cond = -1;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* Yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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 (0);
+    }
+
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* 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_buf.unsigned_regval);
+
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* We are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+
+  return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h	2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified


On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> I have implemented your comments, and will be sending the patch soon.
>
> please find my comments below on some of your comments.
>
> 1) all the lines are truncated to < 80 chars now:
>
> 2) all the trailing spaces are deleted.
>
> 3) fixed indentation as much as I could find any.
>
> 4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn".  I
> would name this function as "arm_record_b_bl_blx
>
> Oza: the name is changed, and rest of the names are also changed as
> you suggested.
>
> 5)
> Yao:
> We don't have to record PS and LR for these three kinds of insns.  For
> B, we don't have to do anything here.  We only record LR for BL and
> record LS and PS for BLX.
>
> Oza: yes, but in that case we just need to handle BL insn.
> because BLX(1) reside in extension space which is/should be handled
> separately in function
> handle_instruction_space function.
>
> so, BLX(1) will not fall here at all.
>
> 6)
> Yao: It is not correct to me.  Both thumb 16-bit and 32-bit insn are handled
> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>
> Oza: yes currently we have support for only 16 bit thumb.
> the moment we support 32 bit, we will have one more else case with
> THUMB_FULL_INSN_SIZE_BYTES 4
>
> it will look like this
>
> else if (ARM_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
> {
> }
>
> name is just an example:
> if we want to handle thumb in same branch then could be changed
> easily, depending on the writer of the code.
> but as of now code doesnt support, so havent thought about it.
>
> 7) Yao: I don't see any function is installed on this function pointer.
>
> Oza: yes, because phase 3 implementation is still pending which is
> supposed to include system call function pointer and support of
> syscall reverse.
>
> Regards,
> Oza.
>
>
>
> On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>>
>> Thanks Yao,
>> Oza.
>>
>>
>> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>>> You need to add the following two lines in your board file to turn them on,
>>>>
>>>>   set_board_info gdb,use_precord 1
>>>>   set_board_info gdb,can_reverse 1
>>>>
>>>> It is good if you can post the test result in gdb.reverse so that we are
>>>> more confidient to your patch.
>>>       ^^^^^^^^^^ typo "confident".
>>>
>>> I run test cases in gdb.reverse with my own board file [1], and get
>>> following result on x86:
>>>
>>>                === gdb Summary ===
>>>
>>> # of expected passes            2774
>>> # of unexpected failures        22
>>>
>>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>>
>>>                === gdb Summary ===
>>>
>>> # of expected passes            1180
>>> # of unexpected failures        1090
>>> # of expected failures          142
>>>
>>> I don't think these fails are all related to your arm-reverse patch.
>>> IMO, it means there are still some work to do, not only in arm bits, but
>>> also in gdb general parts and test cases.  Sorry that I can't give any
>>> useful suggestion here.
>>>
>>> --
>>> Yao (齐尧)
>>>
>>> [1] My board file reverse.exp
>>>
>>> load_generic_config "unix"
>>> process_multilib_options ""
>>>
>>> # The default compiler for this target.
>>> set_board_info compiler "[find_gcc]"
>>>
>>> set_board_info gdb,can_reverse 1
>>> set_board_info gdb,use_precord 1
>>>
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-16  8:00                       ` oza Pawandeep
@ 2011-10-16  8:44                         ` oza Pawandeep
  2011-10-17  4:25                         ` Yao Qi
  1 sibling, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-16  8:44 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi,

please find the updated patch with Yao's comments.

PATCH STARTS
--------------------------------

diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c	2011-10-16 10:25:10.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,1772 @@
 			   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)
+
+
+/* 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;
+}
+
+/* Handling ARM extension space insns.  */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (!opcode1 && (9 == opcode2))
+    {
+      ret = -1;
+      /* Handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+    {
+      ret = -1;
+      /* Handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+                 && bit (arm_insn_r->arm_insn, 4))
+    {
+      ret = -1;
+      /* Handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+    {
+      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 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
+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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+
+  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 preccedded 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* Accorindly to high vector configuration PC is set accordingly */
+      /* What if 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)
+    let us begin according to addressing modes for store insns
+    STRH insn, addresing modes are taken following.  */
+    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_buf[0].unsigned_regval);
+        if (15 == reg_src1)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }
+        offset_8 = (immed_high << 4) | immed_low;
+        /* Calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        if (15 == reg_src2)
+          {
+            /* If R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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_buf[0].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = 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_buf[0].unsigned_regval);
+        regcache_raw_read_unsigned (reg_cache, reg_src2
+                                    , &u_buf[1].unsigned_regval);
+        /* Calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* Record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns  (e.g. LDRD)  TBD.  */
+  }
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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_buf.unsigned_regval);
+      /* U == 1 */
+      if (bit (arm_insn_r->arm_insn, 23))
+        {
+          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+        }
+      else
+        {
+         tgt_mem_addr = u_buf.unsigned_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:
+            return -1;
+          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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      LONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof (u_buf));
+  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,
+  let us begin 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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          if (15 == reg_src2)
+            {
+   	      /* If R15 was used as Rn, hence current PC+8.  */
+	      /* Pre-indexed mode doesnt reach here ; illegal insn.  */
+              u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+            }
+          /* Calculate target store address, Rn +/- Rm, register offset.  */
+          /* U == 1.  */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[0].unsigned_regval +
+                             u_buf[1].unsigned_regval;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval -
+                             u_buf[0].unsigned_regval;
+            }
+
+          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:
+                return -1;
+              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_buf[0].unsigned_regval);
+          regcache_raw_read_signed (reg_cache, reg_src1
+                                      , &u_buf[0].signed_word);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          /* Offset_12 used as shift.  */
+          switch (offset_12)
+            {
+              case 0:
+                /* Offset_12 used as index.  */
+                offset_12 = u_buf[0].unsigned_regval << shift_imm;
+              break;
+
+              case 1:
+                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
+                                                             shift_imm;
+              break;
+
+              case 2:
+                if (!shift_imm)
+                  {
+                    if (bit (u_buf[0].unsigned_regval, 31))
+                      {
+                        offset_12 = 0xFFFFFFFF;
+                      }
+                    else
+                      {
+                        offset_12 = 0;
+                      }
+                  }
+                else
+                  {
+                    /* This is arithmetic shift.  */
+                    offset_12 = u_buf[0].signed_word >> shift_imm;
+                  }
+                break;
+
+              case 3:
+                if (!shift_imm)
+                  {
+                    regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+                                                , &u_buf[1].unsigned_regval);
+                    /* Get C flag value and shift it by 31.  */
+                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+                                  | (u_buf[0].unsigned_regval) >> 1);
+                  }
+                else
+                  {
+                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                                | (u_buf[0].unsigned_regval <<
+                                (sizeof(uint32_t) - shift_imm));
+                  }
+              break;
+
+              default:
+                return -1;
+              break;
+            }
+
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+            }
+          else
+            {
+              tgt_mem_addr = u_buf[1].unsigned_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 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:
+                return -1;
+              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 shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+  uint32_t start_address = 0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  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 optmization.  */
+        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_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch (addr_mode)
+      {
+        /* Decrement after.  */
+        case 0:		  				
+          start_address = (u_buf[0].unsigned_regval) -
(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_buf[0].unsigned_regval;
+          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
+          return -1;
+        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 shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;
+}
+
+/* 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;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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_buf[0].unsigned_regval);
+          regcache_raw_read_unsigned (reg_cache, reg_src2
+                                      , &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+          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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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 reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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.  */
+      /* Accorindly to high vector configuration PC is set accordingly.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also; how?.  */
+      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_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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_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)
+          {
+            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 0;
+}
+
+/* Handling opcode 111 insns.  */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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; 	
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it.  */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction.  */
+  static int (*const arm_handle_insn[8])
+                                      (insn_decode_record*) =
+  {
+      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 int (*const thumb_handle_insn[8])
+                                          (insn_decode_record*) =
+  { \
+      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_swi,                          /* 110.  */
+      thumb_record_branch                      /* 111.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)
+            ? arm_handle_insn[insn_id] (arm_record)
+            : handle_extension_space (arm_record);
+    }
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is
useless.  */
+      arm_record->cond = -1;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* Yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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 (0);
+    }
+
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* 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_buf.unsigned_regval);
+
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* We are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+
+  return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h	2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified


On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> I have implemented your comments, and will be sending the patch soon.
>
> please find my comments below on some of your comments.
>
> 1) all the lines are truncated to < 80 chars now:
>
> 2) all the trailing spaces are deleted.
>
> 3) fixed indentation as much as I could find any.
>
> 4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn".  I
> would name this function as "arm_record_b_bl_blx
>
> Oza: the name is changed, and rest of the names are also changed as
> you suggested.
>
> 5)
> Yao:
> We don't have to record PS and LR for these three kinds of insns.  For
> B, we don't have to do anything here.  We only record LR for BL and
> record LS and PS for BLX.
>
> Oza: yes, but in that case we just need to handle BL insn.
> because BLX(1) reside in extension space which is/should be handled
> separately in function
> handle_instruction_space function.
>
> so, BLX(1) will not fall here at all.
>
> 6)
> Yao: It is not correct to me.  Both thumb 16-bit and 32-bit insn are handled
> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>
> Oza: yes currently we have support for only 16 bit thumb.
> the moment we support 32 bit, we will have one more else case with
> THUMB_FULL_INSN_SIZE_BYTES 4
>
> it will look like this
>
> else if (ARM_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
> {
> }
>
> name is just an example:
> if we want to handle thumb in same branch then could be changed
> easily, depending on the writer of the code.
> but as of now code doesnt support, so havent thought about it.
>
> 7) Yao: I don't see any function is installed on this function pointer.
>
> Oza: yes, because phase 3 implementation is still pending which is
> supposed to include system call function pointer and support of
> syscall reverse.
>
> Regards,
> Oza.
>
>
>
> On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>>
>> Thanks Yao,
>> Oza.
>>
>>
>> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>>> You need to add the following two lines in your board file to turn them on,
>>>>
>>>>   set_board_info gdb,use_precord 1
>>>>   set_board_info gdb,can_reverse 1
>>>>
>>>> It is good if you can post the test result in gdb.reverse so that we are
>>>> more confidient to your patch.
>>>       ^^^^^^^^^^ typo "confident".
>>>
>>> I run test cases in gdb.reverse with my own board file [1], and get
>>> following result on x86:
>>>
>>>                === gdb Summary ===
>>>
>>> # of expected passes            2774
>>> # of unexpected failures        22
>>>
>>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>>
>>>                === gdb Summary ===
>>>
>>> # of expected passes            1180
>>> # of unexpected failures        1090
>>> # of expected failures          142
>>>
>>> I don't think these fails are all related to your arm-reverse patch.
>>> IMO, it means there are still some work to do, not only in arm bits, but
>>> also in gdb general parts and test cases.  Sorry that I can't give any
>>> useful suggestion here.
>>>
>>> --
>>> Yao (齐尧)
>>>
>>> [1] My board file reverse.exp
>>>
>>> load_generic_config "unix"
>>> process_multilib_options ""
>>>
>>> # The default compiler for this target.
>>> set_board_info compiler "[find_gcc]"
>>>
>>> set_board_info gdb,can_reverse 1
>>> set_board_info gdb,use_precord 1
>>>
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15  3:46             ` paawan oza
  2011-10-15  7:01               ` chandra krishnappa
  2011-10-15  9:32               ` Yao Qi
@ 2011-10-16 23:32               ` Petr Hluzín
  2011-10-22 15:42                 ` oza Pawandeep
  2011-11-03 17:38                 ` Tom Tromey
  2 siblings, 2 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-10-16 23:32 UTC (permalink / raw)
  To: paawan oza; +Cc: Tom Tromey, gdb-patches, chandra krishnappa

On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
> please find the patch below.

I did not verify the style guidelines (spaces etc.), I am not familiar enough.
However some places have a comma ',' at the beginning of new line - I
think the "operator at newline" guideline does not apply to commas.

I did not check ARM semantics. It looks plausible, though.

The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
Only the assertion thing got worse:

In arm_handle_ld_st_imm_offset_insn()
>+   switch (arm_insn_r->opcode)
In arm_handle_ld_st_reg_offset_insn():
>+   switch (arm_insn_r->opcode)
>+   switch (offset_12)
>+   switch (arm_insn_r->opcode)
In arm_handle_ld_st_multiple_insn()
>+   switch (addr_mode)

These switches seem to have `return -1;' in cases which are not
reachable, therefore shoudl have gdb_assert_not_reached().
The guideline - which I think Tom was reffering to - is that
impossible states and coding bugs in gdb should trigger assertions
however user's input (no matter how malformed) should trigger warning
or error messages.
(This would mean to turn the lines with `default:' to the previous
revision. I understand this sucks.)

Some situations are difficult to decide whether they are trigger-able
by user input or not.
If my code is not coded or intended to handle such situations I prefer
to kill the process (or whatever are assertions configured to do) and
get feedback from user.
I am not familiar with GDB customs, though. Tom?

Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>
Tom> It seems wrong to use an assert in this code.  At least, it is not
Tom> obvious to me that this represents a logic error in gdb as opposed to a
Tom> merely unrecognized instruction.  An unrecognized instruction can occur
Tom> for many reasons, e.g., a bad jump.

The switch variable `arm_insn_r->opcode' cannot be initialized to any
value different from 0..15 because of the expression:
arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
The switch variable `offset_12' cannot be initialized to any value
different from 0..3 because of the expression: offset_12 = bits
(arm_insn_r->arm_insn, 5, 6).
The switch variable `addr_mode' cannot be initialized to any value
different from 0..3 because of the expression: addr_mode = bits
(arm_insn_r->arm_insn, 23, 24).
It would be bit easier to see that if the variables were local (as I suggested).
Other values are not possible to create, even with corrupted input or
unrecognized instructions.

Paawan: If Tom and I give you contradicting suggestions then you
should complain.


Issues remaining from my previous reviews:

In arm_handle_coproc_data_proc_insn()
+   if (15 == arm_insn_r->opcode)
...
+        /* Handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
...
+   return -1;

The function still returns -1 even when the instruction was recognized
(15) and OS syscall support function is not NULL.
Yes, there is no way to set it to non-NULL value yet but when it is
implemented then you would have to do this change anyway:
-   tdep->arm_swi_record(reg_cache);
+   return tdep->arm_swi_record(reg_cache);

I guess the function should use `arm_insn_r' argument to record the
changes - which is missing.
In thumb_handle_swi_insn() the situation is the opposite: it returns 0
no matter what the arm_swi_record() returns.


In arm_handle_data_proc_misc_ld_str_insn()
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>>
>> You can get the same result (and simpler code) with
>> ULONGEST u_buf[2];
>> or maybe also better name with
>> ULONGEST u_regvals[2];
>>
>> The same applies to other functions.
>
> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
> and I fixed Tom’s review comments for endianness. I will change this, but pelase
> do not mind if it is not there in the immediate versions of patch, eventually
> after testing it will be changed.

This is still true.


> Oza: please report as I don’t have any automated tool which reports them, if it
> is not effort for you please report all if possible. Gcc also give some warning
> about unused one, but not sure about gdb warning suppression.

Unused local variables, as requested:
arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
reg_src2, addr_mode, start_address
thumb_handle_ld_st_imm_offset_insn: reg_val1
thumb_handle_ld_st_stack_insn: reg_val1
thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
opcode)', immed_8, immed_5
thumb_handle_swi_insn: reg_val1
thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5

Typos:
preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
addresing -> addressing, optmization -> optimization, Wihtout
optmization  -> Without optimization,

Otherwise the patch looks good.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15 16:34                   ` oza Pawandeep
  2011-10-15 17:38                     ` oza Pawandeep
@ 2011-10-17  3:18                     ` Yao Qi
  2011-10-17  4:28                       ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-10-17  3:18 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: gdb-patches

On 10/16/2011 12:34 AM, oza Pawandeep wrote:
> Hi Yao,
> 
> first of all thank you for your comments, will be sending the patch
> soon with your comments incorporated as much as possible.
> thank you again for sending test results;
> 
> I suppose failed test case might be including
> 
> 1) system call support
> 2) signal support
> 3) any other linux ABI support
> 4) there are some programs on x86 assembly which needs to be written
> for ARM and put separately.

x86 assembly will not compiled and run for arm target, so they don't
make fails here.  Beside these fails, I find there are some GDB internal
errors in test result:

stepi^M
../../gdb/gdb/breakpoint.c:12523: internal-error:
insert_single_step_breakpoint: Assertion `single_step_breakpoints[1] ==
NULL' failed.

stepi^M
../../gdb/gdb/infrun.c:1804: internal-error: resume: Assertion
`!(singlestep_breakpoints_inserted_p && step)' failed.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-16  8:00                       ` oza Pawandeep
  2011-10-16  8:44                         ` oza Pawandeep
@ 2011-10-17  4:25                         ` Yao Qi
  1 sibling, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-17  4:25 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: gdb-patches

On 10/16/2011 01:27 PM, oza Pawandeep wrote:
> Hi,
> 
> please find the updated patch with Yao's comments.

First of all, do you plan to fix these test case fails I posted?  Two
GDB internal errors make your arm-reversible patch unusable in some
cases.  They should be fixed, IMO.

> On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep
<oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> I have implemented your comments, and will be sending the patch soon.
>>
>> please find my comments below on some of your comments.
>>
>> 1) all the lines are truncated to < 80 chars now:
>>
>> 2) all the trailing spaces are deleted.
>>
>> 3) fixed indentation as much as I could find any.
>>

Looks like most of indentaiton of your 2nd line of comment is incorrect.
 I'll point some of them out, but I may miss some.

I suggest that you can find some good editor which can highlight
trailing spaces and too-long line easily.

>> 6)
>> Yao: It is not correct to me.  Both thumb 16-bit and 32-bit insn are
handled
>> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>>
>> Oza: yes currently we have support for only 16 bit thumb.
>> the moment we support 32 bit, we will have one more else case with
>> THUMB_FULL_INSN_SIZE_BYTES 4

Yes, only 16-bit thumb is supported, but you should report a warning or
error when encounter a 32-bit thumb insn, and skip it.  In
arm_process_record, you assume that all thumb insns are 16-bit, which is
not correct.  Please reference "thumb_process_displaced_insn".

>>
>> it will look like this
>>
>> else if (ARM_INSN_SIZE_BYTES == insn_size)
>> {
>> }
>> else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> {
>> }
>> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
>> {
>> }


> 
> PATCH STARTS
> --------------------------------
> 
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
>    set_gdbarch_fetch_tls_load_module_address (gdbarch,
>                                               svr4_fetch_objfile_link_map);
> 
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>    tramp_frame_prepend_unwinder (gdbarch,
>  				&arm_linux_sigreturn_tramp_frame);
>    tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
> 
> 
>    tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
> 
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c	2011-10-16 10:25:10.000000000 +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
> 
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
> 
>  static int arm_debug;
> @@ -8821,3 +8823,1772 @@
>  			   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)
> +
> +
> +/* 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() ).  */
  ^^ incorrect indentation

> +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;
> +}
> +
> +/* Handling ARM extension space insns.  */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> +  uint32_t ret = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  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.  */
         ^^ incorrect indentation
> +    }
> +
> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> +  if (!opcode1 && (9 == opcode2))
> +    {
> +      ret = -1;
> +      /* Handle arithmetic insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> +  if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> +    {
> +      ret = -1;
> +      /* Handle control insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> +  if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \

You can put the condition in the next line if it is too long, but don't
need "\" here.

> +                 && bit (arm_insn_r->arm_insn, 4))
> +    {
> +      ret = -1;
> +      /* Handle load/store insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> +    {
> +      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 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
> +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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +
> +  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;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +
> +  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 preccedded 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.  */
        ^^ incorrect indentation

> +        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));
  ^^ incorrect indentation

> +          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_buf[0].unsigned_regval);
                                     ^ "," should be in previous line.

> +      /* 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_buf[0].unsigned_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 ((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.  */
         ^^ incorrect indentation

> +      /* Accorindly to high vector configuration PC is set accordingly */
> +      /* What if user hit breakpoint and type reverse, in
> +      that case, we need to go back with previous CPSR and
> +      Program Counter.  */
         ^^ incorrect indentation

> +      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)
> +    let us begin according to addressing modes for store insns
> +    STRH insn, addresing modes are taken following.  */
       ^^ incorrect indentation

> +    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_buf[0].unsigned_regval);
> +        if (15 == reg_src1)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +          }
> +        offset_8 = (immed_high << 4) | immed_low;
> +        /* Calculate target store address.  */
> +        if (14 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
                                       ^ "," should be in previous line.
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);
                                       ^ likewise.

> +        if (15 == reg_src2)
> +          {
> +            /* If R15 was used as Rn, hence current PC+8.  */
> +            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +          }
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if (12 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = 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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                    , &u_buf[1].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm, register offset.  */
> +        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> +        arm_insn_r->reg_rec_count = 1;
> +      }
> +    /* DSP insns  (e.g. LDRD)  TBD.  */
> +  }
> +  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.  */
         ^^ incorrect indentation

> +      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.  */
         ^^ incorrect indentation

> +      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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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.  */
         ^^ incorrect indentation

> +      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.  */
         ^^ incorrect indentation
> +      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_buf.unsigned_regval);
> +      /* U == 1 */
> +      if (bit (arm_insn_r->arm_insn, 23))
> +        {
> +          tgt_mem_addr = u_buf.unsigned_regval + offset_12;
> +        }
> +      else
> +        {
> +         tgt_mem_addr = u_buf.unsigned_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:
> +            return -1;
> +          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.  */
          ^^ incorrect indentation

> +          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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      LONGEST signed_word;
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof (u_buf));
> +  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,
> +  let us begin according to addressing modes for store insns
> +  STRH insn.  */
     ^^ incorrect indentation
> +
> +  /* 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.  */
         ^^ incorrect indentation
> +      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.  */
          ^^ incorrect indentation

> +          /* 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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          if (15 == reg_src2)
> +            {
> +   	      /* If R15 was used as Rn, hence current PC+8.  */
> +	      /* Pre-indexed mode doesnt reach here ; illegal insn.  */
> +              u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +            }
> +          /* Calculate target store address, Rn +/- Rm, register offset.  */
> +          /* U == 1.  */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr = u_buf[0].unsigned_regval +
> +                             u_buf[1].unsigned_regval;
> +            }
> +          else
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_regval -
> +                             u_buf[0].unsigned_regval;
> +            }
> +
> +          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:
> +                return -1;
> +              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.  */
              ^^ incorrect indentation

> +              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_buf[0].unsigned_regval);
> +          regcache_raw_read_signed (reg_cache, reg_src1
> +                                      , &u_buf[0].signed_word);
> +          regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                      , &u_buf[1].unsigned_regval);
                                         ^ "," should be in previous line.

> +          /* Offset_12 used as shift.  */
> +          switch (offset_12)
> +            {
> +              case 0:
> +                /* Offset_12 used as index.  */
> +                offset_12 = u_buf[0].unsigned_regval << shift_imm;
> +              break;
> +
> +              case 1:
> +                offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
                                           ^ ^^ spaces need between "?"
and ":".
> +                                                             shift_imm;
> +              break;
> +
> +              case 2:
> +                if (!shift_imm)
> +                  {
> +                    if (bit (u_buf[0].unsigned_regval, 31))
> +                      {
> +                        offset_12 = 0xFFFFFFFF;
> +                      }
> +                    else
> +                      {
> +                        offset_12 = 0;
> +                      }
> +                  }
> +                else
> +                  {
> +                    /* This is arithmetic shift.  */
> +                    offset_12 = u_buf[0].signed_word >> shift_imm;
> +                  }
> +                break;
> +
> +              case 3:
> +                if (!shift_imm)
> +                  {
> +                    regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> +                                                , &u_buf[1].unsigned_regval);
> +                    /* Get C flag value and shift it by 31.  */
> +                    offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
> +                                  | (u_buf[0].unsigned_regval) >> 1);
> +                  }
> +                else
> +                  {
> +                    offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
> +                                | (u_buf[0].unsigned_regval <<
> +                                (sizeof(uint32_t) - shift_imm));
> +                  }
> +              break;
> +
> +              default:
> +                return -1;
> +              break;
> +            }
> +
> +          regcache_raw_read_unsigned (reg_cache, reg_src2
> +                                      , &u_buf[1].unsigned_regval);
> +          /* U == 1 */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
> +            }
> +          else
> +            {
> +              tgt_mem_addr = u_buf[1].unsigned_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 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:
> +                return -1;
> +              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)
             ^^ incorrect indentation

> +          || (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.  */
              ^^ incorrect indentation
> +              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 shift_imm = 0;
> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
> +  uint32_t start_address = 0, index = 0;
> +  uint32_t record_buf[24], record_buf_mem[48];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  /* 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
     ^^ incorrect indentation

> +  without optmization.  */
> +
> +  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 optmization.  */
> +        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_buf[0].unsigned_regval);
> +    while (register_bits)
> +      {
> +        if (register_bits & 0x00000001)
> +           register_count++;
> +        register_bits = register_bits >> 1;
> +      }
> +
> +    switch (addr_mode)
> +      {
> +        /* Decrement after.  */
> +        case 0:		  				
> +          start_address = (u_buf[0].unsigned_regval) -
> (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_buf[0].unsigned_regval;
> +          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_buf[0].unsigned_regval) - (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_buf[0].unsigned_regval + 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:
> +          return -1;
> +        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 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;
> +}
> +

I don't understand why coproc insn is not handled for process record
here.  is it in phase_3?

> +
> +/* 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;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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 101 insns.  */
> +
> +static int
> +thumb_record_misc (insn_decode_record *thumb_insn_r)
> +{
> +  struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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.  */
> +      /* Accorindly to high vector configuration PC is set accordingly.  */
> +      /* FIX ME ?  what if 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;
> +      thumb_insn_r->reg_rec_count = 2;
> +      /* Save SPSR also; how?.  */
> +      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));
  Wrong indentation.

> +      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_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 reg_val1 = 0;
> +  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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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)
> +          {
> +            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.  */
     ^^ wrong indentation.

> +
> +  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 111 insns.  */
> +
> +static int
> +thumb_record_branch (insn_decode_record *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +
> +  /* BL , 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.  */
      ^^ wrong indentation.

> +
> +  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> +  return 0; 	
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> dispatch it.  */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  static int (*const arm_handle_insn[8])
> +                                      (insn_decode_record*) =
> +  {
> +      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 int (*const thumb_handle_insn[8])
> +                                          (insn_decode_record*) =
> +  { \
> +      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_swi,                          /* 110.  */
> +      thumb_record_branch                      /* 111.  */
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
> +    {
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> +      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> +      insn_id = bits (arm_record->arm_insn, 25, 27);
> +      ret = (0x0F != arm_record->cond)
> +            ? arm_handle_insn[insn_id] (arm_record)
> +            : handle_extension_space (arm_record);
> +    }
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes, following field is
> useless.  */
> +      arm_record->cond = -1;
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));

"," should be in previous line.  Wrong indentaiton, and

> +
> +      insn_id = bits (arm_record->arm_insn, 13, 15);
> +      ret = thumb_handle_insn[insn_id] (arm_record);
> +    }
> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* Yet to be implemented; handle thumb2 part here.  */
> +      printf_unfiltered (_("Process record does not support 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 (0);
> +    }
> +
> +  return ret;
> +}
> +
> +/* 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..  */

We should not copy/paste such comment of gdbarch hook method.  Please
replace it with
"/* This is the implementation of gdbarch method process_record.  */"

> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> +                             CORE_ADDR insn_addr)

                                ^^ wrong indentation.
> +{
> +
> +  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  uint32_t no_of_rec = 0;
> +  uint32_t ret = 0;
> +  ULONGEST t_bit = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* 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_buf.unsigned_regval);
> +
> +  if (!(u_buf.unsigned_regval & t_bit))
> +    {
> +      /* We are decoding arm insn.  */
> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> +    }
> +  else
> +    {
> +      /* We are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);

If a 32-bit thumb-2 insn is red in, the following logic is wrong.  As I
pointed out at the beginning.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-17  3:18                     ` Yao Qi
@ 2011-10-17  4:28                       ` oza Pawandeep
  2011-10-17 15:42                         ` chandra krishnappa
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-17  4:28 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi Yao,

Thanks for your comments. please find my comments below.

1)
Yao:  x86 assembly will not compiled and run for arm target, so they don't
> make fails here.  Beside these fails, I find there are some GDB internal
> errors in test result

Oza: what I meant here was: x86 assembly might have failed to compile
even and gdb test results might be including that.
anyway, arm assembly has to be written separately, which I guess
Chandra K. might be doing.

2)
Yao:
Looks like most of indentaiton of your 2nd line of comment is incorrect.
 I'll point some of them out, but I may miss some.

I suggest that you can find some good editor which can highlight
trailing spaces and too-long line easily.

Oza: this is one thing I have been struggling with, I have been moving
this patch back and forth from windows to linux and using
source insight, vi, xemacs
an d finally when I paste it to google mail the space gets distorted.
I need to find out what I can do.
sorry about repeating space mistakes.

3) Yes, only 16-bit thumb is supported, but you should report a warning or
error when encounter a 32-bit thumb insn, and skip it.  In
arm_process_record, you assume that all thumb insns are 16-bit, which is
not correct.  Please reference "thumb_process_displaced_insn".

Oza: I will include this logic.

4) Yao:
I don't understand why coproc insn is not handled for process record
here.  is it in phase_3?

Oza: initially I had planned to put both coprocessor and
arm_extension_space insn in phase 3.
but I am going to update this patch with arm__extension_space insn atleast.

as far as coprocessor insns are concerned, I could not find any API
which could be used to read coprocessor register values.
I had sent email regarding the same long back: but I did not get
response, so I moved it to phase 3.

If you could point me out the way to read coprocessor register values:
I will try to implement on phase 2.

Thanks Yao,
Regards,
Oza.





On Mon, Oct 17, 2011 at 7:25 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 10/16/2011 12:34 AM, oza Pawandeep wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>
> x86 assembly will not compiled and run for arm target, so they don't
> make fails here.  Beside these fails, I find there are some GDB internal
> errors in test result:
>
> stepi^M
> ../../gdb/gdb/breakpoint.c:12523: internal-error:
> insert_single_step_breakpoint: Assertion `single_step_breakpoints[1] ==
> NULL' failed.
>
> stepi^M
> ../../gdb/gdb/infrun.c:1804: internal-error: resume: Assertion
> `!(singlestep_breakpoints_inserted_p && step)' failed.
>
> --
> Yao (齐尧)
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-17  4:28                       ` oza Pawandeep
@ 2011-10-17 15:42                         ` chandra krishnappa
  0 siblings, 0 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-10-17 15:42 UTC (permalink / raw)
  To: Yao Qi, oza Pawandeep; +Cc: gdb-patches

Hi Yao and Oza,

Thanks for your comments and hints.. Yes, I wish to try test and submit test scripts soon. some hurdles to find time for testing.. will sort out and submit as soon as possible..

Thanks & Regards,
-Chandra K


--- On Mon, 10/17/11, oza Pawandeep <oza.pawandeep@gmail.com> wrote:

> From: oza Pawandeep <oza.pawandeep@gmail.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "Yao Qi" <yao@codesourcery.com>
> Cc: gdb-patches@sourceware.org
> Date: Monday, October 17, 2011, 9:55 AM
> Hi Yao,
> 
> Thanks for your comments. please find my comments below.
> 
> 1)
> Yao:  x86 assembly will not compiled and run for arm
> target, so they don't
> > make fails here.  Beside these fails, I find
> there are some GDB internal
> > errors in test result
> 
> Oza: what I meant here was: x86 assembly might have failed
> to compile
> even and gdb test results might be including that.
> anyway, arm assembly has to be written separately, which I
> guess
> Chandra K. might be doing.
> 
> 2)
> Yao:
> Looks like most of indentaiton of your 2nd line of comment
> is incorrect.
>  I'll point some of them out, but I may miss some.
> 
> I suggest that you can find some good editor which can
> highlight
> trailing spaces and too-long line easily.
> 
> Oza: this is one thing I have been struggling with, I have
> been moving
> this patch back and forth from windows to linux and using
> source insight, vi, xemacs
> an d finally when I paste it to google mail the space gets
> distorted.
> I need to find out what I can do.
> sorry about repeating space mistakes.
> 
> 3) Yes, only 16-bit thumb is supported, but you should
> report a warning or
> error when encounter a 32-bit thumb insn, and skip
> it.  In
> arm_process_record, you assume that all thumb insns are
> 16-bit, which is
> not correct.  Please reference
> "thumb_process_displaced_insn".
> 
> Oza: I will include this logic.
> 
> 4) Yao:
> I don't understand why coproc insn is not handled for
> process record
> here.  is it in phase_3?
> 
> Oza: initially I had planned to put both coprocessor and
> arm_extension_space insn in phase 3.
> but I am going to update this patch with
> arm__extension_space insn atleast.
> 
> as far as coprocessor insns are concerned, I could not find
> any API
> which could be used to read coprocessor register values.
> I had sent email regarding the same long back: but I did
> not get
> response, so I moved it to phase 3.
> 
> If you could point me out the way to read coprocessor
> register values:
> I will try to implement on phase 2.
> 
> Thanks Yao,
> Regards,
> Oza.
> 
> 
> 
> 
> 
> On Mon, Oct 17, 2011 at 7:25 AM, Yao Qi <yao@codesourcery.com>
> wrote:
> > On 10/16/2011 12:34 AM, oza Pawandeep wrote:
> >> Hi Yao,
> >>
> >> first of all thank you for your comments, will be
> sending the patch
> >> soon with your comments incorporated as much as
> possible.
> >> thank you again for sending test results;
> >>
> >> I suppose failed test case might be including
> >>
> >> 1) system call support
> >> 2) signal support
> >> 3) any other linux ABI support
> >> 4) there are some programs on x86 assembly which
> needs to be written
> >> for ARM and put separately.
> >
> > x86 assembly will not compiled and run for arm target,
> so they don't
> > make fails here.  Beside these fails, I find there
> are some GDB internal
> > errors in test result:
> >
> > stepi^M
> > ../../gdb/gdb/breakpoint.c:12523: internal-error:
> > insert_single_step_breakpoint: Assertion
> `single_step_breakpoints[1] ==
> > NULL' failed.
> >
> > stepi^M
> > ../../gdb/gdb/infrun.c:1804: internal-error: resume:
> Assertion
> > `!(singlestep_breakpoints_inserted_p && step)'
> failed.
> >
> > --
> > Yao (齐尧)
> >
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-16 23:32               ` Petr Hluzín
@ 2011-10-22 15:42                 ` oza Pawandeep
  2011-10-23 10:17                   ` oza Pawandeep
  2011-11-03 17:38                 ` Tom Tromey
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-22 15:42 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, Tom Tromey, gdb-patches, chandra krishnappa

Hi Petr,

Thanks for your comments again.

I have tried to take care of all your comments except

1) there is contradiction between yours and Tom's comment about
gdb_assert_not_reached.
I have changed back and forth earlier.
currently it return -1, indirectly gdb throws __error which results
into record stop completely.

2) the local variable usage as you sueggsted definately improves cache
line usage and performance
I want to leave it to regression probably in phase - 3; because other
changes from Yao and you have taken good amount of time.

please excuse me If you have to repeat he comments:
as this patch has grown too much that I miss something some or the other thing

the next patch update include the implementation of arm_extension_space insn.

Regards,
Oza.

On Mon, Oct 17, 2011 at 2:32 AM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
> On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
>> please find the patch below.
>
> I did not verify the style guidelines (spaces etc.), I am not familiar enough.
> However some places have a comma ',' at the beginning of new line - I
> think the "operator at newline" guideline does not apply to commas.
>
> I did not check ARM semantics. It looks plausible, though.
>
> The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
> Only the assertion thing got worse:
>
> In arm_handle_ld_st_imm_offset_insn()
>>+   switch (arm_insn_r->opcode)
> In arm_handle_ld_st_reg_offset_insn():
>>+   switch (arm_insn_r->opcode)
>>+   switch (offset_12)
>>+   switch (arm_insn_r->opcode)
> In arm_handle_ld_st_multiple_insn()
>>+   switch (addr_mode)
>
> These switches seem to have `return -1;' in cases which are not
> reachable, therefore shoudl have gdb_assert_not_reached().
> The guideline - which I think Tom was reffering to - is that
> impossible states and coding bugs in gdb should trigger assertions
> however user's input (no matter how malformed) should trigger warning
> or error messages.
> (This would mean to turn the lines with `default:' to the previous
> revision. I understand this sucks.)
>
> Some situations are difficult to decide whether they are trigger-able
> by user input or not.
> If my code is not coded or intended to handle such situations I prefer
> to kill the process (or whatever are assertions configured to do) and
> get feedback from user.
> I am not familiar with GDB customs, though. Tom?
>
> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>
> Tom> It seems wrong to use an assert in this code.  At least, it is not
> Tom> obvious to me that this represents a logic error in gdb as opposed to a
> Tom> merely unrecognized instruction.  An unrecognized instruction can occur
> Tom> for many reasons, e.g., a bad jump.
>
> The switch variable `arm_insn_r->opcode' cannot be initialized to any
> value different from 0..15 because of the expression:
> arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
> The switch variable `offset_12' cannot be initialized to any value
> different from 0..3 because of the expression: offset_12 = bits
> (arm_insn_r->arm_insn, 5, 6).
> The switch variable `addr_mode' cannot be initialized to any value
> different from 0..3 because of the expression: addr_mode = bits
> (arm_insn_r->arm_insn, 23, 24).
> It would be bit easier to see that if the variables were local (as I suggested).
> Other values are not possible to create, even with corrupted input or
> unrecognized instructions.
>
> Paawan: If Tom and I give you contradicting suggestions then you
> should complain.
>
>
> Issues remaining from my previous reviews:
>
> In arm_handle_coproc_data_proc_insn()
> +   if (15 == arm_insn_r->opcode)
> ...
> +        /* Handle arm syscall insn.  */
> +        if (tdep->arm_swi_record != NULL)
> +          {
> +            tdep->arm_swi_record(reg_cache);
> +          }
> ...
> +   return -1;
>
> The function still returns -1 even when the instruction was recognized
> (15) and OS syscall support function is not NULL.
> Yes, there is no way to set it to non-NULL value yet but when it is
> implemented then you would have to do this change anyway:
> -   tdep->arm_swi_record(reg_cache);
> +   return tdep->arm_swi_record(reg_cache);
>
> I guess the function should use `arm_insn_r' argument to record the
> changes - which is missing.
> In thumb_handle_swi_insn() the situation is the opposite: it returns 0
> no matter what the arm_swi_record() returns.
>
>
> In arm_handle_data_proc_misc_ld_str_insn()
>>> +  struct
>>> +    {
>>> +      ULONGEST unsigned_regval;
>>> +    } u_buf[2];
>>>
>>> You can get the same result (and simpler code) with
>>> ULONGEST u_buf[2];
>>> or maybe also better name with
>>> ULONGEST u_regvals[2];
>>>
>>> The same applies to other functions.
>>
>> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
>> and I fixed Tom’s review comments for endianness. I will change this, but pelase
>> do not mind if it is not there in the immediate versions of patch, eventually
>> after testing it will be changed.
>
> This is still true.
>
>
>> Oza: please report as I don’t have any automated tool which reports them, if it
>> is not effort for you please report all if possible. Gcc also give some warning
>> about unused one, but not sure about gdb warning suppression.
>
> Unused local variables, as requested:
> arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
> arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
> arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
> arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
> reg_src2, addr_mode, start_address
> thumb_handle_ld_st_imm_offset_insn: reg_val1
> thumb_handle_ld_st_stack_insn: reg_val1
> thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
> opcode)', immed_8, immed_5
> thumb_handle_swi_insn: reg_val1
> thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5
>
> Typos:
> preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
> addresing -> addressing, optmization -> optimization, Wihtout
> optmization  -> Without optimization,
>
> Otherwise the patch looks good.
>
> --
> Petr Hluzin
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-22 15:42                 ` oza Pawandeep
@ 2011-10-23 10:17                   ` oza Pawandeep
  2011-10-24  7:43                     ` Petr Hluzín
                                       ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-23 10:17 UTC (permalink / raw)
  To: Petr Hluzín, Tom Tromey, gdb-patches, chandra krishnappa

Hi all,

please find the updated patch attached.
check: this patch includes ARM extension space insn.

@Yao: I have tried to take care of formatting as much as possible in
xemacs editor, execuse me with identation problems and trailing space
problems.
I ahev tried to correct it; but not sure it has fallen righlty.

@Petr: tried to implement most of your comments: (please wait for some
variable to be made local, which will be done later,I have that in
mind).

@Chandra: please take this patch and run your tests on this. (it is
integrated with gdb7.3)



PATCH STARTS
-----------------------
diff -wurN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -wurN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c	2011-10-22 17:48:05.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,2005 @@
 			   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)
+
+#define INSN_RECORDED(ARM_RECORD) \
+  ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))
+
+/* 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;
+
+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 (15 == 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;
+  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;
+
+  /* handle unconditional insn extension space */
+
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+  opcode1 = 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>, cprocessor 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.  */
+                  /* FIX ME: 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 (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.  */
+              /* FIX ME: 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;
+            }
+        }
+    }
+
+  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 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
+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.  */
+	  /* What if 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).  */
+    arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+                    ARM_RECORD_STRH);
+    /* DSP insns  (e.g. LDRD)  TBD.  */
+  }
+  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:
+            return -1;
+          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,
+  let us begin 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:
+                return -1;
+              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:
+                return -1;
+              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:
+                return -1;
+              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:
+          return -1;
+        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;
+
+   /* 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.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also;how?.  */
+      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_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;
+  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];
+
+  /* BL , 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; 	
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it.  */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction.  */
+  static int (*const arm_handle_insn[8])
+                                      (insn_decode_record*) =
+  {
+      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 int (*const thumb_handle_insn[8])
+                                          (insn_decode_record*) =
+  { \
+      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_swi,                   /* 110.  */
+      thumb_record_branch                 /* 111.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      arm_record_extension_space (arm_record);
+      /* if this insn has fallen into extension space then we need
not decode it anymore.  */
+      if (!INSN_RECORDED(arm_record))
+        {
+          arm_handle_insn[insn_id] (arm_record);
+        }
+    }
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, we set negatiive.  */
+      arm_record->cond = -1;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+
+      insn_id = bits (arm_record->arm_insn, 11, 15);
+      /* is it thumb2 insn?  */
+      if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+        {
+          printf_unfiltered (_("Process record does not support thumb32 "
+                               "instruction 0x%0x at address %s.\n"),
+                                arm_record->arm_insn,
+                         paddress (arm_record->gdbarch,
arm_record->this_addr));
+          ret = -1;
+        }
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else
+    {
+      /* Throw assertion.  */
+      gdb_assert (0);
+    }
+
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 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));
+    }
+
+  /* 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_INSN_SIZE_BYTES);
+    }
+  else
+    {
+      /* We are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+
+  return ret;
+}
diff -wurN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h	2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified




Regards,
Oza.

On Sat, Oct 22, 2011 at 8:18 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Petr,
>
> Thanks for your comments again.
>
> I have tried to take care of all your comments except
>
> 1) there is contradiction between yours and Tom's comment about
> gdb_assert_not_reached.
> I have changed back and forth earlier.
> currently it return -1, indirectly gdb throws __error which results
> into record stop completely.
>
> 2) the local variable usage as you sueggsted definately improves cache
> line usage and performance
> I want to leave it to regression probably in phase - 3; because other
> changes from Yao and you have taken good amount of time.
>
> please excuse me If you have to repeat he comments:
> as this patch has grown too much that I miss something some or the other thing
>
> the next patch update include the implementation of arm_extension_space insn.
>
> Regards,
> Oza.
>
> On Mon, Oct 17, 2011 at 2:32 AM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
>> On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
>>> please find the patch below.
>>
>> I did not verify the style guidelines (spaces etc.), I am not familiar enough.
>> However some places have a comma ',' at the beginning of new line - I
>> think the "operator at newline" guideline does not apply to commas.
>>
>> I did not check ARM semantics. It looks plausible, though.
>>
>> The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
>> Only the assertion thing got worse:
>>
>> In arm_handle_ld_st_imm_offset_insn()
>>>+   switch (arm_insn_r->opcode)
>> In arm_handle_ld_st_reg_offset_insn():
>>>+   switch (arm_insn_r->opcode)
>>>+   switch (offset_12)
>>>+   switch (arm_insn_r->opcode)
>> In arm_handle_ld_st_multiple_insn()
>>>+   switch (addr_mode)
>>
>> These switches seem to have `return -1;' in cases which are not
>> reachable, therefore shoudl have gdb_assert_not_reached().
>> The guideline - which I think Tom was reffering to - is that
>> impossible states and coding bugs in gdb should trigger assertions
>> however user's input (no matter how malformed) should trigger warning
>> or error messages.
>> (This would mean to turn the lines with `default:' to the previous
>> revision. I understand this sucks.)
>>
>> Some situations are difficult to decide whether they are trigger-able
>> by user input or not.
>> If my code is not coded or intended to handle such situations I prefer
>> to kill the process (or whatever are assertions configured to do) and
>> get feedback from user.
>> I am not familiar with GDB customs, though. Tom?
>>
>> Oza> +      gdb_assert_not_reached ("no decoding pattern found");
>>>
>> Tom> It seems wrong to use an assert in this code.  At least, it is not
>> Tom> obvious to me that this represents a logic error in gdb as opposed to a
>> Tom> merely unrecognized instruction.  An unrecognized instruction can occur
>> Tom> for many reasons, e.g., a bad jump.
>>
>> The switch variable `arm_insn_r->opcode' cannot be initialized to any
>> value different from 0..15 because of the expression:
>> arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
>> The switch variable `offset_12' cannot be initialized to any value
>> different from 0..3 because of the expression: offset_12 = bits
>> (arm_insn_r->arm_insn, 5, 6).
>> The switch variable `addr_mode' cannot be initialized to any value
>> different from 0..3 because of the expression: addr_mode = bits
>> (arm_insn_r->arm_insn, 23, 24).
>> It would be bit easier to see that if the variables were local (as I suggested).
>> Other values are not possible to create, even with corrupted input or
>> unrecognized instructions.
>>
>> Paawan: If Tom and I give you contradicting suggestions then you
>> should complain.
>>
>>
>> Issues remaining from my previous reviews:
>>
>> In arm_handle_coproc_data_proc_insn()
>> +   if (15 == arm_insn_r->opcode)
>> ...
>> +        /* Handle arm syscall insn.  */
>> +        if (tdep->arm_swi_record != NULL)
>> +          {
>> +            tdep->arm_swi_record(reg_cache);
>> +          }
>> ...
>> +   return -1;
>>
>> The function still returns -1 even when the instruction was recognized
>> (15) and OS syscall support function is not NULL.
>> Yes, there is no way to set it to non-NULL value yet but when it is
>> implemented then you would have to do this change anyway:
>> -   tdep->arm_swi_record(reg_cache);
>> +   return tdep->arm_swi_record(reg_cache);
>>
>> I guess the function should use `arm_insn_r' argument to record the
>> changes - which is missing.
>> In thumb_handle_swi_insn() the situation is the opposite: it returns 0
>> no matter what the arm_swi_record() returns.
>>
>>
>> In arm_handle_data_proc_misc_ld_str_insn()
>>>> +  struct
>>>> +    {
>>>> +      ULONGEST unsigned_regval;
>>>> +    } u_buf[2];
>>>>
>>>> You can get the same result (and simpler code) with
>>>> ULONGEST u_buf[2];
>>>> or maybe also better name with
>>>> ULONGEST u_regvals[2];
>>>>
>>>> The same applies to other functions.
>>>
>>> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
>>> and I fixed Tom’s review comments for endianness. I will change this, but pelase
>>> do not mind if it is not there in the immediate versions of patch, eventually
>>> after testing it will be changed.
>>
>> This is still true.
>>
>>
>>> Oza: please report as I don’t have any automated tool which reports them, if it
>>> is not effort for you please report all if possible. Gcc also give some warning
>>> about unused one, but not sure about gdb warning suppression.
>>
>> Unused local variables, as requested:
>> arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
>> arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
>> arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
>> arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
>> reg_src2, addr_mode, start_address
>> thumb_handle_ld_st_imm_offset_insn: reg_val1
>> thumb_handle_ld_st_stack_insn: reg_val1
>> thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
>> opcode)', immed_8, immed_5
>> thumb_handle_swi_insn: reg_val1
>> thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5
>>
>> Typos:
>> preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
>> addresing -> addressing, optmization -> optimization, Wihtout
>> optmization  -> Without optimization,
>>
>> Otherwise the patch looks good.
>>
>> --
>> Petr Hluzin
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-23 10:17                   ` oza Pawandeep
@ 2011-10-24  7:43                     ` Petr Hluzín
  2011-10-25  7:20                     ` Yao Qi
  2011-11-03 17:41                     ` Tom Tromey
  2 siblings, 0 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-10-24  7:43 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Tom Tromey, gdb-patches, chandra krishnappa

Hi Oza, hi folks

On 22 October 2011 17:41, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> @Chandra: please take this patch and run your tests on this. (it is
> integrated with gdb7.3)

You probably meant to say the patch should be applied to gdb-7.3. It
is not there yet.

> +
> +#define INSN_RECORDED(ARM_RECORD) \
> +  ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))

Is it supposed to return a boolean-like value? If yes then it would be
more descriptive to use INSN_IS_RECORDED. However I do not know if GDB
uses this convention. Tom?
Also there are extra parentheses. There should be parentheses around
ARM_RECORD argument.
Consider adding `== NULL' to the two tests to make it clear the fields
are pointers, not integers or booleans, and that the || is supposed to
be logical, not bit-wise. (I have heard few people have tools good
enough to tell them the types.)

In arm_record_strx:
> +      if (ARM_RECORD_STRH == str_type)
> +        {
> +          *(record_buf_mem) = 2;
> +          *(record_buf_mem + 1) = tgt_mem_addr;

Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?

> +          arm_insn_r->mem_rec_count = 1;
> +        }
> +      else if (ARM_RECORD_STRD == str_type)
> +        {
> +          *(record_buf_mem) = 4;
> +          *(record_buf_mem + 1) = tgt_mem_addr;
> +          *(record_buf_mem + 2) = 4;
> +          *(record_buf_mem + 3) = tgt_mem_addr + 4;

The same here and several more places in this function. Search for "*("

In arm_record_extension_space:
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
> +  opcode1 = 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))

This condition is never true because `opcode1 = bits
(arm_insn_r->arm_insn, 4, 7)' is value in range 0..15 therefore
`opcode1 & 0xE0' is always zero. I think.

> +        {
> +          /* 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>, cprocessor insn.  */

Typo cprocessor.

> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21) &&
> +    !(INSN_RECORDED(arm_insn_r)))

Operators should go to beginning of a new line, not at the end of previous line.
I.e.
if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21)
   && !(INSN_RECORDED(arm_insn_r)))

It is on multiple places involving the macro.

> +      if (!INSN_RECORDED(arm_record))
> +        {
> +          arm_handle_insn[insn_id] (arm_record);
> +        }
> +    }
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes, we set negatiive.  */

Typo negatiive.

In function arm_record_extension_space:
The function stores some values in local variable `uint32_t
record_buf[8]' but these values are never read. I suspect you forgot
to add calls to:
+  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);

In function arm_record_extension_space:
The calls to INSN_RECORDED(arm_insn_r) will always return false,
because the fields referenced by the macro are always 0 at entry to
arm_record_extension_space() and the function does not modify them.
The missing calls to REG_ALLOC() & MEM_ALLOC() would modify them in
the end but it would be late anyway. I guess you will have to either
add a local flag variable or alter control flow - either way the
INSN_RECORDED seems like going to be unused.
(Function arm_record_strx() works differently and is not affected.)

In function arm_record_extension_space:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' at the
beginning of the function. That way it will be easy to understand
which part of code does change the state.

In function decode_insn:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' just before
call to arm_record_extension_space. That way it will be easy to
understand which part of code does change the state. Or use return
value from arm_record_extension_space() -  this would make the
understanding even faster.

In function decode_insn:
Consider adding these assertions at the exit:
+ gdb_assert (arm_record->mem_rec_count == 0 || arm_record->arm_mems != NULL);
+ gdb_assert (arm_record->reg_rec_count == 0 || arm_record->arm_regs != NULL);
This would catch the missing REG_ALLOC calls in arm_record_extension_space().


Issues remaining since the previous revision:

Tom Tromey or someone should decide whether to use gdb_assert or not
(in the situation described in [1]).

Probably turn field `decode' & friends in insn_decode_record_t to
local variables. (Phase 3?)

[1] http://sourceware.org/ml/gdb-patches/2011-10/msg00449.html

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-23 10:17                   ` oza Pawandeep
  2011-10-24  7:43                     ` Petr Hluzín
@ 2011-10-25  7:20                     ` Yao Qi
  2011-11-03 17:41                     ` Tom Tromey
  2 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-25  7:20 UTC (permalink / raw)
  To: gdb-patches

On 10/22/2011 11:41 PM, oza Pawandeep wrote:

> 
> @Yao: I have tried to take care of formatting as much as possible in
> xemacs editor, execuse me with identation problems and trailing space
> problems.
> I ahev tried to correct it; but not sure it has fallen righlty.

Yeah, it looks much better.  I still have some comments below.

> 
> 
> PATCH STARTS
> -----------------------
> diff -wurN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c	2011-10-22 17:48:05.000000000 +0530
> @@ -8821,3 +8823,2005 @@
>  			   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
> +

macro THUMB2_INSN_SIZE_BYTES is never used.  Please remove it.

> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
                    ^ space before "(" and ",".
> +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); \
                 ^        ^ spaces are needed before "(" and ",".

> +      } \
> +  } \
> +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)
> +
> +#define INSN_RECORDED(ARM_RECORD) \
> +  ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))
> +
> +/* 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;
> +}
> +

This function is used to match opcode for instructions.  Why don't
you use bit operation (AND and OR) and logic operation to match
instruction?  Bit operation and logic operation are widely used in
gdb.  It is efficient and easy to read.  I suggest to replace
sbo_sbz by bit/logical operation when matching instruction.

> +typedef enum
> +{
> +  ARM_RECORD_STRH=1,
> +  ARM_RECORD_STRD
> +}arm_record_strx_t;
> +
> +static int
> +arm_record_strx(insn_decode_record *arm_insn_r, uint32_t *record_buf,
                  ^ space is missing

> +                   uint32_t *record_buf_mem, arm_record_strx_t str_type)
                     ^ wrong indentation.

> +{
> +
> +   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]);

"," should be in previous line here and somewhere else.

> +      if (15 == reg_src1)
             ^^ 15 is a magic number here and somewhere else.
Please use ARM_PC_REGNUM.

> +        {
> +          /* 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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 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.  */
> +	  /* What if 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).  */
> +    arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
                      ^ space is required.

> +                    ARM_RECORD_STRH);
> +    /* DSP insns  (e.g. LDRD)  TBD.  */

Comment here is confusing.  STRH (register) and STRH (immediate) are
handled here, but comment doesn't reflect this.

> +  }
> +  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 110 insns.  */
> +
> +static int
> +thumb_record_swi (insn_decode_record *thumb_insn_r)	

The name of function is incorrect.  Better to name it
"thumb_record_ldm_stm_swi", or something similar.
			
> +{
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> +  struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> +  uint32_t ret = 0;
> +  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.  */

Redundant comments?

> +
> +  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];
> +
> +  /* BL , BLX(1).  */
> +  record_buf[0] = ARM_PS_REGNUM;
> +  record_buf[1] = ARM_LR_REGNUM;
> +  thumb_insn_r->reg_rec_count = 2;
> +

Again, don't have to store register PS for BL.

> +  /* 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; 	
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> dispatch it.  */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  static int (*const arm_handle_insn[8])
> +                                      (insn_decode_record*) =
> +  {
> +      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 int (*const thumb_handle_insn[8])
> +                                          (insn_decode_record*) =
> +  { \
> +      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_swi,                   /* 110.  */
> +      thumb_record_branch                 /* 111.  */
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
> +    {
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> +      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> +      insn_id = bits (arm_record->arm_insn, 25, 27);
> +      arm_record_extension_space (arm_record);
> +      /* if this insn has fallen into extension space then we need
> not decode it anymore.  */
> +      if (!INSN_RECORDED(arm_record))
> +        {
> +          arm_handle_insn[insn_id] (arm_record);
> +        }
> +    }
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes, we set negatiive.  */
> +      arm_record->cond = -1;
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> +
> +      insn_id = bits (arm_record->arm_insn, 11, 15);
> +      /* is it thumb2 insn?  */
> +      if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
> +        {
> +          printf_unfiltered (_("Process record does not support thumb32 "
> +                               "instruction 0x%0x at address %s.\n"),
> +                                arm_record->arm_insn,
> +                         paddress (arm_record->gdbarch,
> arm_record->this_addr));
> +          ret = -1;
> +        }
> +      insn_id = bits (arm_record->arm_insn, 13, 15);
> +      ret = thumb_handle_insn[insn_id] (arm_record);
> +    }

This kind of design leaves thumb2-32 bit support difficult in the
future.  We can let the caller, arm_process_record, to differentiate
arm/thumb 16bit/thumb 32bit, and call different decode routines
respectively, like this,

int
arm_process_record
{
  if (!(u_regval & t_bit))
    {
      /* We are decoding arm insn.  */
      ret = arm_record_decode_arm (&arm_record);
    }
  else
   {
      insn = read_memory_unsigned_integer (start, 2, byte_order_for_code);
      if (thumb_insn_size (insn) == 4)
        ret = arm_record_decode_thumb_32bit (&arm_record);
      else
        ret = arm_record_decode_thumb_16bit (&arm_record);
   }

  ....
}

In arm_record_decode_thumb_32bit, just print a warning like what we
have now.  It makes future work easier.

> +  else
> +    {
> +      /* Throw assertion.  */
> +      gdb_assert (0);
> +    }
> +
> +  return ret;
> +}
> +

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-15  9:32               ` Yao Qi
  2011-10-15 13:33                 ` Yao Qi
@ 2011-11-03 17:10                 ` Tom Tromey
  2011-11-04 16:27                   ` Yao Qi
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:10 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:

Yao> I noticed that test cases in gdb.reverse are *not* enabled in default.

Do you know why that is?  It seems to me that they should be enabled on
platforms where they are known to work.  The current situation means
that any regressions are probably completely missed.

Yao> I am not an expert on record, so I don't have much comment on your code
Yao> logic.  However, some of my cents below.

I think your review was quite helpful.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-16 23:32               ` Petr Hluzín
  2011-10-22 15:42                 ` oza Pawandeep
@ 2011-11-03 17:38                 ` Tom Tromey
  2011-11-05 17:35                   ` Petr Hluzín
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:38 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb-patches, chandra krishnappa

>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:

Petr> The guideline - which I think Tom was reffering to - is that
Petr> impossible states and coding bugs in gdb should trigger assertions
Petr> however user's input (no matter how malformed) should trigger warning
Petr> or error messages.

Yes, I think that rule makes the most sense.

Petr> Some situations are difficult to decide whether they are trigger-able
Petr> by user input or not.
Petr> If my code is not coded or intended to handle such situations I prefer
Petr> to kill the process (or whatever are assertions configured to do) and
Petr> get feedback from user.
Petr> I am not familiar with GDB customs, though. Tom?

I think crashing gdb should be limited to "can't happen" scenarios
arising from the internal logic.

Tripping across an unrecognized instruction or the like should just
result in an ordinary gdb error -- something the user can reasonably
recover from.

If the error message is informative enough about what went wrong, it
will result in a bug report :-)

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-10-23 10:17                   ` oza Pawandeep
  2011-10-24  7:43                     ` Petr Hluzín
  2011-10-25  7:20                     ` Yao Qi
@ 2011-11-03 17:41                     ` Tom Tromey
  2011-11-05 17:36                       ` Petr Hluzín
  2 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:41 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Petr Hluzín, gdb-patches

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> please find the updated patch attached.
Oza> check: this patch includes ARM extension space insn.

Thanks for persevering through the review process.

I read the whole thread and I think at this point there are still some
unaddressed comments.  If I am incorrect, could you point me to the most
up-to-date version of the patch?  Then I will review it.  Otherwise I
will wait for your next mail.  Thanks.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-03 17:10                 ` Tom Tromey
@ 2011-11-04 16:27                   ` Yao Qi
  0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-11-04 16:27 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 11/04/2011 01:10 AM, Tom Tromey wrote:
>>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:
> 
> Yao> I noticed that test cases in gdb.reverse are *not* enabled in default.
> 
> Do you know why that is?  It seems to me that they should be enabled on
> platforms where they are known to work.  The current situation means
> that any regressions are probably completely missed.
> 

I don't know why, looks these cases are written in that way at the
beginning.

I have a sed script to convert "target_info exists gdb,use_precord" to a
proc "support_process_record" which returns true on x86-linux and
x86_64-linux.  There are some fails running these tests in gdb.reverse
on x86-linux, IMO, we don't have to KFAIL them, because these fails are
unknown to us.  I'll send out this patch later.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-03 17:38                 ` Tom Tromey
@ 2011-11-05 17:35                   ` Petr Hluzín
  2011-11-07 15:39                     ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-11-05 17:35 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb-patches, chandra krishnappa

On 3 November 2011 18:38, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
>
> Petr> The guideline - which I think Tom was reffering to - is that
> Petr> impossible states and coding bugs in gdb should trigger assertions
> Petr> however user's input (no matter how malformed) should trigger warning
> Petr> or error messages.
>
> Yes, I think that rule makes the most sense.
>
> Petr> Some situations are difficult to decide whether they are trigger-able
> Petr> by user input or not.
> Petr> If my code is not coded or intended to handle such situations I prefer
> Petr> to kill the process (or whatever are assertions configured to do) and
> Petr> get feedback from user.
> Petr> I am not familiar with GDB customs, though. Tom?
>
> I think crashing gdb should be limited to "can't happen" scenarios
> arising from the internal logic.

How strong is the "can't happen" requirement? Is programmer required
to prove the assertion cannot be triggered? The difficulty in general
case would be equivalent to proving a code is bug-free - i.e. it is
impossible. At my job we try to verify an assumption until we have a
sort-of-proof or the search becomes difficult and no clue/indication
to the contrary has been found yet.
I am asking because GDB code contains surprisingly few assertions.

> Tripping across an unrecognized instruction or the like should just
> result in an ordinary gdb error -- something the user can reasonably
> recover from.
>
> If the error message is informative enough about what went wrong, it
> will result in a bug report :-)

Well, when user gets a message "assertion failed" (and the user had
not messed with gdb sources) then the user knows its a bug in gdb. The
user does not have to understand what code broke - application
programmers generally do not have the knowledge anyway (symbols, ELF
internals, debugging hooks etc).

Anyway, the patch had used assertions correctly because expression
`bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
matter how bogus X value. Yes, all 2^32 values map to 0..15. The
assertions satisfy the guideline. (This is not even the hard-to-prove
case I was speculating above.)

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-03 17:41                     ` Tom Tromey
@ 2011-11-05 17:36                       ` Petr Hluzín
  0 siblings, 0 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-11-05 17:36 UTC (permalink / raw)
  To: Tom Tromey, chandra krishnappa; +Cc: oza Pawandeep, gdb-patches

On 3 November 2011 18:40, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
> I read the whole thread and I think at this point there are still some
> unaddressed comments.  If I am incorrect, could you point me to the most
> up-to-date version of the patch?  Then I will review it.  Otherwise I
> will wait for your next mail.  Thanks.

The most recent version of Oza's patch is at [1], my review is at [2].
Oza fixed all issues. (I do not check whitespace, though.) Oza removed
the assertions as you asked, however I believe they should have stayed
(as I explained in mail few minutes ago and in [3]).

However Oza improved ARM extension space insn support which introduced
some bugs - I think, I have no feedback from Oza whether I
misunderstood the code.

[1] http://sourceware.org/ml/gdb-patches/2011-10/msg00613.html
[2] http://sourceware.org/ml/gdb-patches/2011-10/msg00617.html
[3] http://sourceware.org/ml/gdb-patches/2011-10/msg00449.html

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-05 17:35                   ` Petr Hluzín
@ 2011-11-07 15:39                     ` Tom Tromey
  2011-11-08  6:02                       ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-07 15:39 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb-patches, chandra krishnappa

>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:

Petr> How strong is the "can't happen" requirement? Is programmer required
Petr> to prove the assertion cannot be triggered? The difficulty in general
Petr> case would be equivalent to proving a code is bug-free - i.e. it is
Petr> impossible. At my job we try to verify an assumption until we have a
Petr> sort-of-proof or the search becomes difficult and no clue/indication
Petr> to the contrary has been found yet.
Petr> I am asking because GDB code contains surprisingly few assertions.

I don't think there is a hard-and-fast rule in gdb.  I am not completely
sure though.

I think in gdb it is best to error instead of assert if there is any
doubt.  That's because I think when people turn to gdb they are already
a bit frustrated, and then if gdb itself fails, this is extremely
irritating.  That's certainly been the case for me in the past.

I realize you can sort of recover from internal_error (and hence
assertions).  But my impression is that internal_error is treated like
"not an exception-thrower" in gdb, leading to cleanup problems and the
like.

Petr> Anyway, the patch had used assertions correctly because expression
Petr> `bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
Petr> matter how bogus X value. Yes, all 2^32 values map to 0..15. The
Petr> assertions satisfy the guideline. (This is not even the hard-to-prove
Petr> case I was speculating above.)

Yeah, my review was wrong here.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-07 15:39                     ` Tom Tromey
@ 2011-11-08  6:02                       ` oza Pawandeep
  2011-11-08 10:17                         ` Yao Qi
  2011-11-09  5:28                         ` oza Pawandeep
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-08  6:02 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi All,

sorry for delay in reply. was on vacation.
I have already addressed the comments from both Petr and Yao in the next patch.
the comments which I have not fixed please find the explanation below.

Petr >>
Is it supposed to return a boolean-like value? If yes then it would be
more descriptive to use INSN_IS_RECORDED. However I do not know if GDB
uses this convention. Tom?
Also there are extra parentheses. There should be parentheses around
ARM_RECORD argument.
Consider adding `== NULL' to the two tests to make it clear the fields
are pointers, not integers or booleans, and that the || is supposed to
be logical, not bit-wise. (I have heard few people have tools good
enough to tell them the types.)

Oza >> I have changed the condition itself now.
you were right; after changing now it makes sense.


Petr >>
Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?


Oza >> because calling function takes care of REG_ALLOC routine calls.
I did not want ALLOC calls to be scattered into any other function
other than main decoding functions.


Petr >>
This condition is never true because `opcode1 = bits
(arm_insn_r->arm_insn, 4, 7)' is value in range 0..15 therefore
`opcode1 & 0xE0' is always zero. I think.

Oza >> you are right, I fixed it now.
Oza >> typo mistakes are corrected.

Petr >> Operators should go to beginning of a new line, not at the end
of previous line.

Oza >> corrected.

Petr >>
In function arm_record_extension_space:
The function stores some values in local variable `uint32_t
record_buf[8]' but these values are never read. I suspect you forgot
to add calls to:
+  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);



Oza >> yes, thanks for this comment, I added them now.


Petr >> n function arm_record_extension_space:
The calls to INSN_RECORDED(arm_insn_r) will always return false,
because the fields referenced by the macro are always 0 at entry to
arm_record_extension_space() and the function does not modify them.
The missing calls to REG_ALLOC() & MEM_ALLOC() would modify them in
the end but it would be late anyway. I guess you will have to either
add a local flag variable or alter control flow - either way the
INSN_RECORDED seems like going to be unused.
(Function arm_record_strx() works differently and is not affected.)

In function arm_record_extension_space:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' at the
beginning of the function. That way it will be easy to understand
which part of code does change the state.

In function decode_insn:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' just before
call to arm_record_extension_space. That way it will be easy to
understand which part of code does change the state. Or use return
value from arm_record_extension_space() -  this would make the
understanding even faster.

In function decode_insn:
Consider adding these assertions at the exit:
+ gdb_assert (arm_record->mem_rec_count == 0 || arm_record->arm_mems != NULL);
+ gdb_assert (arm_record->reg_rec_count == 0 || arm_record->arm_regs != NULL);
This would catch the missing REG_ALLOC calls in arm_record_extension_space().


Oza >> the whole logic is falling in place now, everything is taken
care with the change of the MACRO IS_INSN_RECORDED.


Yao >> macro THUMB2_INSN_SIZE_BYTES is never used.  Please remove it.

Oza >> it is intropduced again as required in the logic which you have proposed.



Yao >> This function is used to match opcode for instructions.  Why don't
you use bit operation (AND and OR) and logic operation to match
instruction?  Bit operation and logic operation are widely used in
gdb.  It is efficient and easy to read.  I suggest to replace
sbo_sbz by bit/logical operation when matching instruction.


Oza >> I am not sure what you meant by re-writting sbo_sbz function.
as there is already '&' and '!' and '>>' which all are bit operators.

Yao >> 15 is a magic number here and somewhere else.
Please use ARM_PC_REGNUM.

Oza >> corrected.

Yao >> Comment here is confusing.  STRH (register) and STRH (immediate) are
handled here, but comment doesn't reflect this.

Oza >> done

Yao >> The name of function is incorrect.  Better to name it
"thumb_record_ldm_stm_swi", or something similar.

Oza >> done

Yao >> Again, don't have to store register PS for BL.

Oza >> done

Yao >> This kind of design leaves thumb2-32 bit support difficult in the
future.  We can let the caller, arm_process_record, to differentiate
arm/thumb 16bit/thumb 32bit, and call different decode routines
respectively, like this,

Oza >> proposed logic incorporated in caller.

Regards,
Oza.


On Mon, Nov 7, 2011 at 9:08 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
>
> Petr> How strong is the "can't happen" requirement? Is programmer required
> Petr> to prove the assertion cannot be triggered? The difficulty in general
> Petr> case would be equivalent to proving a code is bug-free - i.e. it is
> Petr> impossible. At my job we try to verify an assumption until we have a
> Petr> sort-of-proof or the search becomes difficult and no clue/indication
> Petr> to the contrary has been found yet.
> Petr> I am asking because GDB code contains surprisingly few assertions.
>
> I don't think there is a hard-and-fast rule in gdb.  I am not completely
> sure though.
>
> I think in gdb it is best to error instead of assert if there is any
> doubt.  That's because I think when people turn to gdb they are already
> a bit frustrated, and then if gdb itself fails, this is extremely
> irritating.  That's certainly been the case for me in the past.
>
> I realize you can sort of recover from internal_error (and hence
> assertions).  But my impression is that internal_error is treated like
> "not an exception-thrower" in gdb, leading to cleanup problems and the
> like.
>
> Petr> Anyway, the patch had used assertions correctly because expression
> Petr> `bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
> Petr> matter how bogus X value. Yes, all 2^32 values map to 0..15. The
> Petr> assertions satisfy the guideline. (This is not even the hard-to-prove
> Petr> case I was speculating above.)
>
> Yeah, my review was wrong here.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-08  6:02                       ` oza Pawandeep
@ 2011-11-08 10:17                         ` Yao Qi
  2011-11-08 10:45                           ` oza Pawandeep
  2011-11-09  5:28                         ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-11-08 10:17 UTC (permalink / raw)
  To: gdb-patches

On 11/08/2011 02:01 PM, oza Pawandeep wrote:
> Yao >> This function is used to match opcode for instructions.  Why don't
> you use bit operation (AND and OR) and logic operation to match
> instruction?  Bit operation and logic operation are widely used in
> gdb.  It is efficient and easy to read.  I suggest to replace
> sbo_sbz by bit/logical operation when matching instruction.
> 
> 
> Oza >> I am not sure what you meant by re-writting sbo_sbz function.
> as there is already '&' and '!' and '>>' which all are bit operators.

I suggested to remove sbo_sbz function, to decode instructions with
macros bits/bit, and to match using if/else/switch etc.

Please reference arm_get_next_pc_raw, arm_process_displaced_insn and
thumb_process_displaced_insn to see how instructions are decoded and
matched.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-08 10:17                         ` Yao Qi
@ 2011-11-08 10:45                           ` oza Pawandeep
  0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-08 10:45 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

Hi Yao,

the function sbo_sbz is generic function, which checks whether alll
the bits are 1 or all are 0 ?
the position of starting bit could be anything and ending bit could be anything.
this function accepts any position (between 0-31) and any length.

I looked at the functions which you suggested;
they seem to be working on specific insns.

I could not find a better way other than ANDing all the bits to find
out whether they all are 1 or 0.

I could be easily wrong here or still might not be getting the angle
which you are trying to bring in.

Regards,
Oza.



On Tue, Nov 8, 2011 at 3:46 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 11/08/2011 02:01 PM, oza Pawandeep wrote:
>> Yao >> This function is used to match opcode for instructions.  Why don't
>> you use bit operation (AND and OR) and logic operation to match
>> instruction?  Bit operation and logic operation are widely used in
>> gdb.  It is efficient and easy to read.  I suggest to replace
>> sbo_sbz by bit/logical operation when matching instruction.
>>
>>
>> Oza >> I am not sure what you meant by re-writting sbo_sbz function.
>> as there is already '&' and '!' and '>>' which all are bit operators.
>
> I suggested to remove sbo_sbz function, to decode instructions with
> macros bits/bit, and to match using if/else/switch etc.
>
> Please reference arm_get_next_pc_raw, arm_process_displaced_insn and
> thumb_process_displaced_insn to see how instructions are decoded and
> matched.
>
> --
> Yao (齐尧)
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-08  6:02                       ` oza Pawandeep
  2011-11-08 10:17                         ` Yao Qi
@ 2011-11-09  5:28                         ` oza Pawandeep
  2011-11-09  6:08                           ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-09  5:28 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Thanks Tom, Petr and Yao for your comments.
I will be reintroducing assert_not_reached.

apart from that some unanswered questions of Petr and Yao as below.

Petr >>  is the code integrated to gdb 7.3 ?

Oza >> not yet, what I meant was, the patch could be directly applied
on gdb-7.3.

Petr >> what about making opcode and other global variable to local
variable. in phase 3 ?

Oza >> yes, would like to take it in phase 3.

Yao >> some gdb.reverse tests are failing; are you planning to address those ?

Oza >> I ahve changed the code after that to soem extent, and more
over I am waiting for Chandra K to respond on his test case matter.


please let me know apart from that If any question remained unanswered.
next mail will contain the latest patch.

Regards,
Oza.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-09  5:28                         ` oza Pawandeep
@ 2011-11-09  6:08                           ` oza Pawandeep
  2011-11-17  9:24                             ` oza Pawandeep
  2011-11-17 20:40                             ` Tom Tromey
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-09  6:08 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi,

please find the latest patch below.

PATCH STARTS
--------------------------------


diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c	2011-11-09 11:31:46.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,2039 @@
 			   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)
+
+#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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;
+  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;
+
+  /* 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.  */
+                  /* FIX ME: 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 (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.  */
+              /* FIX ME: 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;
+            }
+        }
+    }
+
+  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 0x%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.  */
+	  /* What if 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,
+  let us begin 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;
+
+   /* 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.  */
+      /* FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* Save SPSR also;how?.  */
+      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;
+  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; 	
+}
+
+
+/* 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 int (*const arm_handle_insn[8])
+                                      (insn_decode_record*) =
+  {
+      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 int (*const thumb_handle_insn[8])
+                                          (insn_decode_record*) =
+  { \
+      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.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      arm_record_extension_space (arm_record);
+      /* if this insn has fallen into extension space then we need
not decode it anymore.  */
+      if (!INSN_RECORDED(arm_record))
+        {
+          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;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+      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 (0);
+    }
+
+  return ret;
+}
+
+/* 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;
+  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));
+    }
+
+  /* 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,
THUMB_INSN_SIZE_BYTES);
+        }
+      else
+        {
+          /* We are decoding thumb insn.  */
+          ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+        }
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , (arm_record.arm_regs[no_of_rec])))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+
+  return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h	2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-09  6:08                           ` oza Pawandeep
@ 2011-11-17  9:24                             ` oza Pawandeep
  2011-11-17  9:52                               ` Yao Qi
  2011-11-17 20:40                             ` Tom Tromey
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-17  9:24 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Petr and Yao,

It has been a while since I have heard from you.
Can I assume that there are no more review comments ?

Regards,
Oza.

On Wed, Nov 9, 2011 at 11:37 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi,
>
> please find the latest patch below.
>
> PATCH STARTS
> --------------------------------
>
>
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c   2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
>   set_gdbarch_fetch_tls_load_module_address (gdbarch,
>                                              svr4_fetch_objfile_link_map);
>
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>   tramp_frame_prepend_unwinder (gdbarch,
>                                &arm_linux_sigreturn_tramp_frame);
>   tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
>   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
>
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c  2011-11-09 11:31:46.000000000 +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
>
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
>
>  static int arm_debug;
> @@ -8821,3 +8823,2039 @@
>                           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)
> +
> +#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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;
> +  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;
> +
> +  /* 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.  */
> +                  /* FIX ME: 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 (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.  */
> +              /* FIX ME: 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;
> +            }
> +        }
> +    }
> +
> +  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 0x%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.  */
> +         /* What if 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,
> +  let us begin 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;
> +
> +   /* 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.  */
> +      /* FIX ME ?  what if 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;
> +      thumb_insn_r->reg_rec_count = 2;
> +      /* Save SPSR also;how?.  */
> +      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;
> +  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;
> +}
> +
> +
> +/* 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 int (*const arm_handle_insn[8])
> +                                      (insn_decode_record*) =
> +  {
> +      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 int (*const thumb_handle_insn[8])
> +                                          (insn_decode_record*) =
> +  { \
> +      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.  */
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> +      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> +      insn_id = bits (arm_record->arm_insn, 25, 27);
> +      arm_record_extension_space (arm_record);
> +      /* if this insn has fallen into extension space then we need
> not decode it anymore.  */
> +      if (!INSN_RECORDED(arm_record))
> +        {
> +          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;
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> +      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 (0);
> +    }
> +
> +  return ret;
> +}
> +
> +/* 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;
> +  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));
> +    }
> +
> +  /* 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,
> THUMB_INSN_SIZE_BYTES);
> +        }
> +      else
> +        {
> +          /* We are decoding thumb insn.  */
> +          ret = decode_insn (&arm_record, THUMB_RECORD,
> THUMB2_INSN_SIZE_BYTES);
> +        }
> +    }
> +
> +  if (0 == ret)
> +    {
> +      /* Record registers.  */
> +      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
> no_of_rec++)
> +            {
> +              if (record_arch_list_add_reg (arm_record.regcache \
> +                                           , (arm_record.arm_regs[no_of_rec])))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +
> +  return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h  2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
>   /* Return the expected next PC if FRAME is stopped at a syscall
>      instruction.  */
>   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
>
>  /* Structures used for displaced stepping.  */
> @@ -331,6 +334,8 @@
>    instruction?  */
>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> +                               struct regcache *regcache, CORE_ADDR addr);
>  /* Functions exported from armbsd-tdep.h.  */
>
>  /* Return the appropriate register set for the core section identified
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-17  9:24                             ` oza Pawandeep
@ 2011-11-17  9:52                               ` Yao Qi
  0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-11-17  9:52 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: gdb-patches

On 11/17/2011 05:23 PM, oza Pawandeep wrote:
> Hi Petr and Yao,
> 
> It has been a while since I have heard from you.
> Can I assume that there are no more review comments ?
> 

I have no more comments.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-09  6:08                           ` oza Pawandeep
  2011-11-17  9:24                             ` oza Pawandeep
@ 2011-11-17 20:40                             ` Tom Tromey
  2011-11-18  3:18                               ` oza Pawandeep
  2011-11-19  9:43                               ` oza Pawandeep
  1 sibling, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-11-17 20:40 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

oza> please find the latest patch below.

No ChangeLog entry.

No NEWS entry.

Patch got mangled by your mailer again.

oza> +        memcpy(&REGS[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \

Wrong spacing.

oza> +        memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \

Likewise.

oza> +}arm_record_strx_t;

Spacing.

oza> +}record_type_t;

Again.

oza> +
oza> +static int
oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
oza> +    uint32_t *record_buf_mem, arm_record_strx_t str_type)

Indentation.

oza> +   if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))

Too many parens.

oza> +  else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))

Again.

oza> +  else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
oza> +    || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))

Again, plus indentation.

oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
oza> +                                 , &u_regval[0]);

Formatting -- "," is on the wrong line.

I see most of these issues multiple times.  Please go over the entire
patch and fix them all.  I feel like I asked this before.

oza> +                  /* FIX ME: How to read SPSR value?  */

We try not to put FIXME comments into new code.
Nobody ever fixes them.

You can just write an informative comment instead: "We have no way to
read the SPSR value".  Assuming that is accurate.

The enclosing function, arm_record_extension_space, takes care to return
a value, but (1) the meaning of the return value is not documented in
the function's introductory comment (this problems affects many of the
new functions), and (2) the only caller does not check it.

What happens if the user hits an instruction which is not handled?
Right now a message is printed.  But shouldn't it abort the operation in
some other way?  That is, is emitting a message really sufficient?

oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
oza> dispatch it.  */
oza> +
oza> +static int
oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
oza> +                uint32_t insn_size)

E.g., here the return value should be documented.

oza> +  static int (*const arm_handle_insn[8])
oza> +                                      (insn_decode_record*) =

Formatting looks weird.
A typedef for the function type would probably make this look less
strange.

oza> +      /* if this insn has fallen into extension space then we need
oza> not decode it anymore.  */
oza> +      if (!INSN_RECORDED(arm_record))
oza> +        {
oza> +          arm_handle_insn[insn_id] (arm_record);

... it seems like there should be a check of the return value here.
I don't understand this.

oza> +              if (record_arch_list_add_mem \

No need for this backslash.

oza> +                ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
oza> +                arm_record.arm_mems[no_of_rec].len))

Really messed up formatting.

oza> +  if (arm_record.arm_regs)
oza> +    xfree (arm_record.arm_regs);
oza> +  if (arm_record.arm_mems)
oza> +    xfree (arm_record.arm_mems);

This is fine as long as you have proved that nothing in any possible
call path here can throw an exception.  If anything throws an exception,
then you are leaking memory and should instead use a cleanup.

oza> +   /* Parse swi insn args, sycall record.  */
oza> +  int (*arm_swi_record) (struct regcache *regcache);

Since this is only used in your Phase 3 patch, it belongs there.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-17 20:40                             ` Tom Tromey
@ 2011-11-18  3:18                               ` oza Pawandeep
  2011-11-18 17:22                                 ` Tom Tromey
  2011-11-19  9:43                               ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-18  3:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

Thanks for the comments. I am confused over formatting and I have been
trying to fix all the time but it always falls apart.
what I have been doing is:

change the code in windows,
and then take it to linux.
make sure it compiles.
then edit it in xemacs editor.
make the formatting right.
then use diff  -urN command to get diff.
open the diff file in xemacs (here also again I see some formatting problems)
and then from linux I open google and paste everything.
but when I check the sent mail in yahoo, some formatting seem to be lost.

I have no idea what is the best way to maintain formatting right from
the editing of file to the diff of files to the mails.

Regards,
Oza.
On Fri, Nov 18, 2011 at 1:10 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the latest patch below.
>
> No ChangeLog entry.
>
> No NEWS entry.
>
> Patch got mangled by your mailer again.
>
> oza> +        memcpy(&REGS[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>
> Wrong spacing.
>
> oza> +        memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>
> Likewise.
>
> oza> +}arm_record_strx_t;
>
> Spacing.
>
> oza> +}record_type_t;
>
> Again.
>
> oza> +
> oza> +static int
> oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> oza> +    uint32_t *record_buf_mem, arm_record_strx_t str_type)
>
> Indentation.
>
> oza> +   if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>
> Too many parens.
>
> oza> +  else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>
> Again.
>
> oza> +  else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> oza> +    || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>
> Again, plus indentation.
>
> oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
> oza> +                                 , &u_regval[0]);
>
> Formatting -- "," is on the wrong line.
>
> I see most of these issues multiple times.  Please go over the entire
> patch and fix them all.  I feel like I asked this before.
>
> oza> +                  /* FIX ME: How to read SPSR value?  */
>
> We try not to put FIXME comments into new code.
> Nobody ever fixes them.
>
> You can just write an informative comment instead: "We have no way to
> read the SPSR value".  Assuming that is accurate.
>
> The enclosing function, arm_record_extension_space, takes care to return
> a value, but (1) the meaning of the return value is not documented in
> the function's introductory comment (this problems affects many of the
> new functions), and (2) the only caller does not check it.
>
> What happens if the user hits an instruction which is not handled?
> Right now a message is printed.  But shouldn't it abort the operation in
> some other way?  That is, is emitting a message really sufficient?
>
> oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> oza> dispatch it.  */
> oza> +
> oza> +static int
> oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> oza> +                uint32_t insn_size)
>
> E.g., here the return value should be documented.
>
> oza> +  static int (*const arm_handle_insn[8])
> oza> +                                      (insn_decode_record*) =
>
> Formatting looks weird.
> A typedef for the function type would probably make this look less
> strange.
>
> oza> +      /* if this insn has fallen into extension space then we need
> oza> not decode it anymore.  */
> oza> +      if (!INSN_RECORDED(arm_record))
> oza> +        {
> oza> +          arm_handle_insn[insn_id] (arm_record);
>
> ... it seems like there should be a check of the return value here.
> I don't understand this.
>
> oza> +              if (record_arch_list_add_mem \
>
> No need for this backslash.
>
> oza> +                ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> oza> +                arm_record.arm_mems[no_of_rec].len))
>
> Really messed up formatting.
>
> oza> +  if (arm_record.arm_regs)
> oza> +    xfree (arm_record.arm_regs);
> oza> +  if (arm_record.arm_mems)
> oza> +    xfree (arm_record.arm_mems);
>
> This is fine as long as you have proved that nothing in any possible
> call path here can throw an exception.  If anything throws an exception,
> then you are leaking memory and should instead use a cleanup.
>
> oza> +   /* Parse swi insn args, sycall record.  */
> oza> +  int (*arm_swi_record) (struct regcache *regcache);
>
> Since this is only used in your Phase 3 patch, it belongs there.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-18  3:18                               ` oza Pawandeep
@ 2011-11-18 17:22                                 ` Tom Tromey
  0 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-11-18 17:22 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> Thanks for the comments. I am confused over formatting and I have been
Oza> trying to fix all the time but it always falls apart.

Yeah, it is a bit of a pain.  I wish we had a tool that could reformat
the code according to our standards.  Then we would basically never have
to review the formatting.

Oza> change the code in windows,
Oza> and then take it to linux.
Oza> make sure it compiles.
Oza> then edit it in xemacs editor.
Oza> make the formatting right.

Ouch!  That sounds quite painful.

I try to do the formatting correctly from the start.
Doing it later is too error-prone.

Oza> I have no idea what is the best way to maintain formatting right from
Oza> the editing of file to the diff of files to the mails.

Me neither, sorry.  It depends on the mailer.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-17 20:40                             ` Tom Tromey
  2011-11-18  3:18                               ` oza Pawandeep
@ 2011-11-19  9:43                               ` oza Pawandeep
  2011-11-19 11:39                                 ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-19  9:43 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

I have fixed most of your comments.
as far as formatting is concerned, I am still trying to hard to get it
right. but at the end mailer ends up messing it up :(
following are the comments.

We try not to put FIXME comments into new code.
Nobody ever fixes them.

You can just write an informative comment instead: "We have no way to
read the SPSR value".  Assuming that is accurate.

Oza >> removed FIX ME comments and put appropriate comments.

The enclosing function, arm_record_extension_space, takes care to return
a value, but (1) the meaning of the return value is not documented in
the function's introductory comment (this problems affects many of the
new functions), and (2) the only caller does not check it.

oza >> thanks for pointing that out, I have added descirption and
caler must be checking return value which I have corrected.

What happens if the user hits an instruction which is not handled?
Right now a message is printed.  But shouldn't it abort the operation in
some other way?  That is, is emitting a message really sufficient?

Oza >> I have chaged the description a bit, the abort message is
printed, but at the same time return value is -1, which will cause gdb
standard stack unwinding, with error(...) symentics.


Formatting looks weird.
A typedef for the function type would probably make this look less
strange.

oza >> converted to typedef defination, it looks simpler now.

No need for this backslash.

Oza >> removed.


oza> +  if (arm_record.arm_regs)
oza> +    xfree (arm_record.arm_regs);
oza> +  if (arm_record.arm_mems)
oza> +    xfree (arm_record.arm_mems);

This is fine as long as you have proved that nothing in any possible
call path here can throw an exception.  If anything throws an exception,
then you are leaking memory and should instead use a cleanup.



Oza >> I have added a new function deallocate_reg_arm....
the design is in such a way, that any function goes for allocation
until and unless it supports the insn; otherwise memory is always
local/cache, so in case of exception it simply unwinds wihtout
affecting dymanic memory.
and in case we have allocated memory, we make sure that we come to the
end of the process_record funntion and we free them irrespective of
success or failure;

oza> +   /* Parse swi insn args, sycall record.  */
oza> +  int (*arm_swi_record) (struct regcache *regcache);

Since this is only used in your Phase 3 patch, it belongs there.

Oza >> In my thinking, it was necessary to add this function pointer
because I had already added logic of decoding insn in phase 2, where I
am just checking if this fp is NULL.
where this fp was initialised to NULL, which will be replaced with
valid fp in phase 3.
wihtout including this, phase 2 would have missed on insn decoding.



Regards,
Oza.


On Fri, Nov 18, 2011 at 2:10 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the latest patch below.
>
> No ChangeLog entry.
>
> No NEWS entry.
>
> Patch got mangled by your mailer again.
>
> oza> +        memcpy(&REGS[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>
> Wrong spacing.
>
> oza> +        memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>
> Likewise.
>
> oza> +}arm_record_strx_t;
>
> Spacing.
>
> oza> +}record_type_t;
>
> Again.
>
> oza> +
> oza> +static int
> oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> oza> +    uint32_t *record_buf_mem, arm_record_strx_t str_type)
>
> Indentation.
>
> oza> +   if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>
> Too many parens.
>
> oza> +  else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>
> Again.
>
> oza> +  else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> oza> +    || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>
> Again, plus indentation.
>
> oza> +      regcache_raw_read_unsigned (reg_cache, reg_src1
> oza> +                                 , &u_regval[0]);
>
> Formatting -- "," is on the wrong line.
>
> I see most of these issues multiple times.  Please go over the entire
> patch and fix them all.  I feel like I asked this before.
>
> oza> +                  /* FIX ME: How to read SPSR value?  */
>
> We try not to put FIXME comments into new code.
> Nobody ever fixes them.
>
> You can just write an informative comment instead: "We have no way to
> read the SPSR value".  Assuming that is accurate.
>
> The enclosing function, arm_record_extension_space, takes care to return
> a value, but (1) the meaning of the return value is not documented in
> the function's introductory comment (this problems affects many of the
> new functions), and (2) the only caller does not check it.
>
> What happens if the user hits an instruction which is not handled?
> Right now a message is printed.  But shouldn't it abort the operation in
> some other way?  That is, is emitting a message really sufficient?
>
> oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> oza> dispatch it.  */
> oza> +
> oza> +static int
> oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> oza> +                uint32_t insn_size)
>
> E.g., here the return value should be documented.
>
> oza> +  static int (*const arm_handle_insn[8])
> oza> +                                      (insn_decode_record*) =
>
> Formatting looks weird.
> A typedef for the function type would probably make this look less
> strange.
>
> oza> +      /* if this insn has fallen into extension space then we need
> oza> not decode it anymore.  */
> oza> +      if (!INSN_RECORDED(arm_record))
> oza> +        {
> oza> +          arm_handle_insn[insn_id] (arm_record);
>
> ... it seems like there should be a check of the return value here.
> I don't understand this.
>
> oza> +              if (record_arch_list_add_mem \
>
> No need for this backslash.
>
> oza> +                ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> oza> +                arm_record.arm_mems[no_of_rec].len))
>
> Really messed up formatting.
>
> oza> +  if (arm_record.arm_regs)
> oza> +    xfree (arm_record.arm_regs);
> oza> +  if (arm_record.arm_mems)
> oza> +    xfree (arm_record.arm_mems);
>
> This is fine as long as you have proved that nothing in any possible
> call path here can throw an exception.  If anything throws an exception,
> then you are leaking memory and should instead use a cleanup.
>
> oza> +   /* Parse swi insn args, sycall record.  */
> oza> +  int (*arm_swi_record) (struct regcache *regcache);
>
> Since this is only used in your Phase 3 patch, it belongs there.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-19  9:43                               ` oza Pawandeep
@ 2011-11-19 11:39                                 ` oza Pawandeep
  2011-12-02 18:36                                   ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-19 11:39 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

please find the updated patch; I have tried my level best to take care
the most to get formatting right.
And also, all extra parentheses removed.
please have a look.  (hope mailer does not do anything)

PATCH STARTS
------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c	2011-11-19 16:57:58.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

 static int arm_debug;
@@ -8821,3 +8823,2060 @@
 			   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)
+
+#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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;  /* function 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;
+
+  /* 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
+     xtension 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;
+}
+
+
+
+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.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+            , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      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))
+        {
+          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;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              THUMB_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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 (0);
+    }
+
+  return ret;
+}
+
+
+/* cleans up local record registers and memory allocations.  */
+void deallocate_reg_mem(insn_decode_record *record)
+{
+  if (record->arm_regs)
+    xfree (record->arm_regs);
+  if (record->arm_mems)
+    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;  /* function 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));
+    }
+
+  /* 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,
THUMB_INSN_SIZE_BYTES);
+        }
+      else
+        {
+          /* We are decoding thumb insn.  */
+          ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+        }
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h	2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -331,6 +334,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-11-19 11:39                                 ` oza Pawandeep
@ 2011-12-02 18:36                                   ` Tom Tromey
  2011-12-03  8:20                                     ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-12-02 18:36 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

oza> please find the updated patch; I have tried my level best to take care
oza> the most to get formatting right.
oza> And also, all extra parentheses removed.

Thanks.

oza> please have a look.  (hope mailer does not do anything)

Your mailer is still screwed up.

You didn't write a ChangeLog entry or a NEWS entry.
Please do this.  I have asked at least once now.  These are just
baseline things for getting patches into gdb; if you don't respond to
these requests it makes me tend to prioritize other patches over yours.
FYI.

oza> +      /* if this insn has fallen into extension space
oza> +         then we need not decode it anymore.  */
oza> +      if (ret != -1 && !INSN_RECORDED(arm_record))
oza> +        {
oza> +          arm_handle_insn[insn_id] (arm_record);

Still not checking the return value.

oza> +/* cleans up local record registers and memory allocations.  */

Should start with a capital letter.
Blank line between comment and function.

oza> +void deallocate_reg_mem(insn_decode_record *record)

Newline after void.
Space before open paren.

oza> +{
oza> +  if (record->arm_regs)
oza> +    xfree (record->arm_regs);
oza> +  if (record->arm_mems)
oza> +    xfree (record->arm_mems);
oza> +}

You can call xfree on a NULL pointer.  Just remove those ifs.

oza> +          for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
oza> no_of_rec++)
oza> +          {

Brace indentation looks wrong.

There are still other minor formatting issues.  I saw 21 places where
there is a comma at the start of a line, please fix all of these.
I think there were some other problems, too, but at this point I have
stopped caring.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-02 18:36                                   ` Tom Tromey
@ 2011-12-03  8:20                                     ` oza Pawandeep
  2011-12-03 14:18                                       ` oza Pawandeep
                                                         ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03  8:20 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

Thanks for the comments.

1) I have been trying to fix all formatting, it looks better now and
fixed all comments you had.
I am sorry that on formatting both of our efforts are going;
excuse me as every time mailer spoils the things; probably copy from
xemacs editor to chrome/firefox in plain text and the other mailer
gets it. though I am not sure.

2) I could not write changelog entry because I have been getting
commments, and moreover I was not sure whether I should get changelog
entry from latest gdb 7.3 or latest current working version of gdb ? I
think later is true in my understanding.
I will include changelog this time; sorry for having you point it out
in all reviews.

3) will post the latest patch, with possible correction of formatting
issues; and will include changelog from current branch.

Regards,
Oza.



On Sat, Dec 3, 2011 at 12:06 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the updated patch; I have tried my level best to take care
> oza> the most to get formatting right.
> oza> And also, all extra parentheses removed.
>
> Thanks.
>
> oza> please have a look.  (hope mailer does not do anything)
>
> Your mailer is still screwed up.
>
> You didn't write a ChangeLog entry or a NEWS entry.
> Please do this.  I have asked at least once now.  These are just
> baseline things for getting patches into gdb; if you don't respond to
> these requests it makes me tend to prioritize other patches over yours.
> FYI.
>
> oza> +      /* if this insn has fallen into extension space
> oza> +         then we need not decode it anymore.  */
> oza> +      if (ret != -1 && !INSN_RECORDED(arm_record))
> oza> +        {
> oza> +          arm_handle_insn[insn_id] (arm_record);
>
> Still not checking the return value.
>
> oza> +/* cleans up local record registers and memory allocations.  */
>
> Should start with a capital letter.
> Blank line between comment and function.
>
> oza> +void deallocate_reg_mem(insn_decode_record *record)
>
> Newline after void.
> Space before open paren.
>
> oza> +{
> oza> +  if (record->arm_regs)
> oza> +    xfree (record->arm_regs);
> oza> +  if (record->arm_mems)
> oza> +    xfree (record->arm_mems);
> oza> +}
>
> You can call xfree on a NULL pointer.  Just remove those ifs.
>
> oza> +          for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
> oza> no_of_rec++)
> oza> +          {
>
> Brace indentation looks wrong.
>
> There are still other minor formatting issues.  I saw 21 places where
> there is a comma at the start of a line, please fix all of these.
> I think there were some other problems, too, but at this point I have
> stopped caring.
>
> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03  8:20                                     ` oza Pawandeep
@ 2011-12-03 14:18                                       ` oza Pawandeep
  2011-12-03 16:32                                         ` Petr Hluzín
  2011-12-03 15:06                                       ` oza Pawandeep
  2011-12-20 19:05                                       ` Tom Tromey
  2 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 14:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

please find the updated patch below.
note: have derived this patch and Changelog from gdb-7.3.50.20111203.


diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-03 18:10:34.000000000 +0530
@@ -1,3 +1,8 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+	* arm-linux-tdep.c: Added arm-reversible and process record
+	* arm-tdep.c: arm-reversible-debugging implementation
+	* arm-tdep.h: arm-reversible data structures
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-03 17:52:28.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2041 @@
 			   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)
+
+#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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;
+
+  /* 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;
+}
+
+
+
+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.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              ARM_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              THUMB_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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 (0);
+    }
+
+  return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations.  */
+
+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;  /* function 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));
+    }
+
+  /* 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,
THUMB_INSN_SIZE_BYTES);
+        }
+      else
+        {
+          /* We are decoding thumb insn.  */
+          ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+        }
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03  8:20                                     ` oza Pawandeep
  2011-12-03 14:18                                       ` oza Pawandeep
@ 2011-12-03 15:06                                       ` oza Pawandeep
  2011-12-20 19:05                                       ` Tom Tromey
  2 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 15:06 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

please ignore the previous mail
(forgot add new line in Change log which I is corrected in this mail)
note: the patch is derived from current snapshot gdb-7.3.50.20111203
and Change log as well.
please find the patch below.

diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-03 19:48:56.000000000 +0530
@@ -1,3 +1,9 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c: Added arm-reversible and process record
+	* arm-tdep.c: arm-reversible-debugging implementation
+	* arm-tdep.h: arm-reversible data structures
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-03 20:27:30.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2041 @@
 			   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)
+
+#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) = 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) = 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) = 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) = 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) = 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) = 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) = 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) = 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;
+
+  /* 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;
+}
+
+
+
+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.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              ARM_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              THUMB_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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 (0);
+    }
+
+  return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations.  */
+
+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;  /* function 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));
+    }
+
+  /* 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,
THUMB_INSN_SIZE_BYTES);
+        }
+      else
+        {
+          /* We are decoding thumb insn.  */
+          ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+        }
+    }
+
+  if (0 == ret)
+    {
+      /* Record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03 14:18                                       ` oza Pawandeep
@ 2011-12-03 16:32                                         ` Petr Hluzín
  2011-12-03 18:46                                           ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-12-03 16:32 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa

I did not review the 2011-11-19 nor 2011-11-09 patch.

Tom:
> Yeah, it is a bit of a pain.  I wish we had a tool that could reformat
> the code according to our standards.

I guess 'indent' could do that. Its default settings formats using GNU
guidelines.
Some editors can be configured to automatically format new lines and
have a button to reformat existing lines. I suppose no editor can
autodetect the style from file yet.


Review of the 2011-11-03 patch:

In arm_process_record():
Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
of `arm_record.arm_insn'
which is always zero. When you moved the test from decode_insn() I
guess forgot to copy these lines:
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+           THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));


Remaining from previous reviews:

Macro INSN_RECORDED:
I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
Tromey did not comment on that, Oza left the name as is. Well, it is
not a big deal.
However arguments of macros should be surrounded by parentheses - like this:
(ARM_RECORD)->reg_rec_count
This is necessary if INSN_RECORDED() is passed more complex expression
when the order of evaluation matters. This is a common C issue and
customary solution, it is not GDB specific.

> Petr >>In arm_record_strx()
> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>
> because calling function takes care of REG_ALLOC routine calls.
> I did not want ALLOC calls to be scattered into any other function
> other than main decoding functions.

The lines can be converted from `*(record_buf_mem + 1)' to
`record_buf_mem[1]' with no changes to REG_ALLOC() calls. The
allocation calls would remain unscattered in main decoding functions.
The code is correct, but I do not understand why you use the unusual
syntax.

Have you considered adding the assertions I suggested in [2]? They are
not necessary but they improve understanding of code.

[2] http://sourceware.org/ml/gdb-patches/2011-10/msg00617.html

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03 16:32                                         ` Petr Hluzín
@ 2011-12-03 18:46                                           ` oza Pawandeep
  2011-12-03 19:02                                             ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 18:46 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa

Hi Petr,

I have updated the patch with your comments; please find the explanation below.

> In arm_process_record():
> Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
> of `arm_record.arm_insn'
> which is always zero. When you moved the test from decode_insn() I
> guess forgot to copy these lines:
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
> (&u_buf.buf[0],
> +           THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));
>
>
Oza : done, corrected, thanks for this comment.

> Macro INSN_RECORDED:
> I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
> Tromey did not comment on that, Oza left the name as is. Well, it is
> not a big deal.
> However arguments of macros should be surrounded by parentheses - like this:
> (ARM_RECORD)->reg_rec_count
> This is necessary if INSN_RECORDED() is passed more complex expression
> when the order of evaluation matters. This is a common C issue and
> customary solution, it is not GDB specific.
Oza: have taken care of parenthesis stuff and added; and comment is
also added to make it more clear.

>> Petr >>In arm_record_strx()
>> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>>
>> because calling function takes care of REG_ALLOC routine calls.
>> I did not want ALLOC calls to be scattered into any other function
>> other than main decoding functions.

oza: Ahhhh.....I got you now; I have changed, but personally my coding
style have never let me think that pointer style is unusual as
pointers make the things more clear in my mind. because it always
reminds me when i look at the code after a long time that I am playing
with address : )    [of course your array syntax is also nothing but
address, but probably its just my mind thinks that way)
I have changed it as you suggested.

>
> Have you considered adding the assertions I suggested in [2]? They are
> not necessary but they improve understanding of code.

Oza: yes I have added assert as you suggested.
arm_record_extension_space already returns positive/negative value
and decode_insn already catching the return value, and one more point
is some insns may not be supported so in that case the code must reach
back to process_record and its caller to throw correct record error.

PS: next mail will contain the latest patch

Regards,
Oza.

On Sat, Dec 3, 2011 at 10:01 PM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
> I did not review the 2011-11-19 nor 2011-11-09 patch.
>
> Tom:
>> Yeah, it is a bit of a pain.  I wish we had a tool that could reformat
>> the code according to our standards.
>
> I guess 'indent' could do that. Its default settings formats using GNU
> guidelines.
> Some editors can be configured to automatically format new lines and
> have a button to reformat existing lines. I suppose no editor can
> autodetect the style from file yet.
>
>
> Review of the 2011-11-03 patch:
>
> In arm_process_record():
> Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
> of `arm_record.arm_insn'
> which is always zero. When you moved the test from decode_insn() I
> guess forgot to copy these lines:
> +      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
> (&u_buf.buf[0],
> +           THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));
>
>
> Remaining from previous reviews:
>
> Macro INSN_RECORDED:
> I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
> Tromey did not comment on that, Oza left the name as is. Well, it is
> not a big deal.
> However arguments of macros should be surrounded by parentheses - like this:
> (ARM_RECORD)->reg_rec_count
> This is necessary if INSN_RECORDED() is passed more complex expression
> when the order of evaluation matters. This is a common C issue and
> customary solution, it is not GDB specific.
>
>> Petr >>In arm_record_strx()
>> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>>
>> because calling function takes care of REG_ALLOC routine calls.
>> I did not want ALLOC calls to be scattered into any other function
>> other than main decoding functions.
>
> The lines can be converted from `*(record_buf_mem + 1)' to
> `record_buf_mem[1]' with no changes to REG_ALLOC() calls. The
> allocation calls would remain unscattered in main decoding functions.
> The code is correct, but I do not understand why you use the unusual
> syntax.
>
> Have you considered adding the assertions I suggested in [2]? They are
> not necessary but they improve understanding of code.
>
> [2] http://sourceware.org/ml/gdb-patches/2011-10/msg00617.html
>
> --
> Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03 18:46                                           ` oza Pawandeep
@ 2011-12-03 19:02                                             ` oza Pawandeep
  2011-12-03 20:30                                               ` Petr Hluzín
  2011-12-04  1:47                                               ` Yao Qi
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 19:02 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa

Hi Tom and Petr,

This patch includes both of your comments; I have worked both on
formatting and comments, and try to make the patch look ok.
the patch is derived from gdb-7.3.50.20111203 current snapshot.


diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-03 19:48:56.000000000 +0530
@@ -1,3 +1,9 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c: Added arm-reversible and process record
+	* arm-tdep.c: arm-reversible-debugging implementation
+	* arm-tdep.h: arm-reversible data structures
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-03 22:11:33.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2053 @@
 			   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;
+}
+
+
+
+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.  */
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              ARM_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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;
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+                              THUMB_INSN_SIZE_BYTES ,
+                              gdbarch_byte_order (arm_record->gdbarch));
+      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 (0);
+    }
+
+  return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations.  */
+
+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;  /* function return value: -1:record failure ;
0:success  */
+  ULONGEST t_bit = 0, insn_id = 0;
+
+  ULONGEST u_regval = 0;
+
+  insn_decode_record arm_record;
+
+  struct
+      {
+        gdb_byte buf[2];
+      } u_buf;
+
+  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));
+    }
+
+  /* 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);
+
+  arm_record.arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0],
+                                   THUMB_INSN_SIZE_BYTES ,
+                                   gdbarch_byte_order (arm_record.gdbarch));
+
+  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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03 19:02                                             ` oza Pawandeep
@ 2011-12-03 20:30                                               ` Petr Hluzín
       [not found]                                                 ` <1322975560.12415.YahooMailNeo@web112518.mail.gq1.yahoo.com>
  2011-12-04  1:47                                               ` Yao Qi
  1 sibling, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-12-03 20:30 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa

On 3 December 2011 20:01, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom and Petr,
>
> This patch includes both of your comments; I have worked both on
> formatting and comments, and try to make the patch look ok.
> the patch is derived from gdb-7.3.50.20111203 current snapshot.
>

In function decode_insn:
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))

I wonder why is there a `struct u_buf'. Having local variable
`buf[insn_size];' would be sufficient and obvious. I am sorry to not
discover that earlier. The same thing applies to arm_process_record().

In arm_process_record ()
> +
> +  struct
> +      {
> +        gdb_byte buf[2];
> +      } u_buf;
> +
> +  ...
> +
> +  arm_record.arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0],
> +                                   THUMB_INSN_SIZE_BYTES ,
> +                                   gdbarch_byte_order (arm_record.gdbarch));

Well, when I said that you probably forgot to copy
extract_unsigned_integer() I should have also said that you should
have also copied the line
target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size)
Right now extract_unsigned_integer() reads an uninitialized buffer. :-T

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03 19:02                                             ` oza Pawandeep
  2011-12-03 20:30                                               ` Petr Hluzín
@ 2011-12-04  1:47                                               ` Yao Qi
  2011-12-04  8:26                                                 ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04  1:47 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

On 12/04/2011 03:01 AM, oza Pawandeep wrote:
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog	2011-12-03 19:48:56.000000000 +0530
> @@ -1,3 +1,9 @@
> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
> +
> +	* arm-linux-tdep.c: Added arm-reversible and process record
> +	* arm-tdep.c: arm-reversible-debugging implementation
> +	* arm-tdep.h: arm-reversible data structures
> +	

ChangeLog like this is not accurate to reflect your changes.  "Add
reverse debugging and process record for ARM" is sort of summary of your
patch, but in ChangeLog, we usually need more details on function level.

Please read other ChangeLog entries in ChangeLog, and see how it is
written.  Or, you can read this

http://www.gnu.org/prep/standards/standards.html#Change-Logs

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]                                                 ` <1322975560.12415.YahooMailNeo@web112518.mail.gq1.yahoo.com>
@ 2011-12-04  7:09                                                   ` paawan oza
  0 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-12-04  7:09 UTC (permalink / raw)
  To: Petr Hluzín, oza Pawandeep
  Cc: Tom Tromey, gdb-patches, chandra krishnappa

Hi Tom, Petr and Yao,

I am working on following:

1) petr's comments, which I am planning to make new function now.

2) yao's comment on Changelog detailed stuff which I shall prepare seeing the guidelines.

3) Tom's comments are already fixed  (hope there are not much formatting issues).

will post the patch in a day or so. 
Thanks for your comments to make this patch look ok.

Regards,
Oza.


________________________________
From: Petr Hluzín <petr.hluzin@gmail.com>
To: oza Pawandeep <oza.pawandeep@gmail.com> 
Cc: Tom Tromey <tromey@redhat.com>; paawan oza <paawan1982@yahoo.com>; "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>; chandra krishnappa <chandra_roadking@yahoo.com> 
Sent: Sunday, 4 December 2011 2:00 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

On 3 December 2011 20:01, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom and Petr,
>
> This patch includes both of your comments; I have worked both on
> formatting and comments, and try to make the patch look ok.
> the patch is derived from gdb-7.3.50.20111203 current snapshot.
>

In function decode_insn:
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))

I wonder why is there a `struct u_buf'. Having local variable
`buf[insn_size];' would be sufficient and obvious. I am sorry to not
discover that earlier. The same thing applies to arm_process_record().

In
arm_process_record ()
> +
> +  struct
> +      {
> +        gdb_byte buf[2];
> +      } u_buf;
> +
> +  ...
> +
> +  arm_record.arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0],
> +                                   THUMB_INSN_SIZE_BYTES ,
> +                                   gdbarch_byte_order (arm_record.gdbarch));

Well, when I said that you probably forgot to copy
extract_unsigned_integer() I should have also said that you should
have also copied the line
target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size)
Right now extract_unsigned_integer() reads an uninitialized buffer. :-T

-- 
Petr
Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04  1:47                                               ` Yao Qi
@ 2011-12-04  8:26                                                 ` oza Pawandeep
  2011-12-04 11:33                                                   ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04  8:26 UTC (permalink / raw)
  To: Yao Qi
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

Hi Yao and Tom,

please have a look at sample changlog below.
let me know whether this much detailed explanation is sufficient ?

2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>

	* arm-linux-tdep.c: arm_linux_init_abi modified to include
	   arm reversible debugging feature.
          registered arm_process_record to gdb_arch
	   syscall pointer initialization.

	* arm-tdep.c: arm-reversible-debugging implementation.
	  newly added functions are as follows.
	
          > arm_process_record: handles basic initialization and record
             summarisation, decodes basic insn ids, on which it hands over
             controls to decode_insn.
          > deallocate_reg_mem : clean up function
          > decode_insn: Decodes arm/thumb insn and calls appropriate
             decoding routine to record the change.
          > thumb_record_branch: branch insn reording (thumb)
          > thumb_record_ldm_stm_swi: load, store and sycall insn
             recoding  (thumb)
          > thumb_record_misc: misc insn recording  (thumb)
          > thumb_record_ld_st_stack: store and stack insn recording  (thumb)
          > thumb_record_ld_st_imm_offset: load, store with immediate offset
             insn recording  (thumb)
          > thumb_record_ld_st_reg_offset: load, store with register offset
             recording  (thumb)
          > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
             and move insn recording  (thumb)
          > thumb_record_shift_add_sub: shift, add and sub insn recording
             (thumb)
          > arm_record_coproc_data_proc: coprocessor and data processing
             recording (partially implemented) (arm)
          > arm_record_coproc: coprocessor insn recording
             (partially implemented) (arm)
          > arm_record_b_bl: branch insn recording (arm)
          > arm_record_ld_st_multiple: load and store multiple insn recording
             (arm)
          > arm_record_ld_st_reg_offset: load and store reg offset recording
             (arm)
          > arm_record_ld_st_imm_offset: load and store immediate offset
             recording (arm)
          > arm_record_data_proc_imm: data processing insn recording  (arm)
          > arm_record_data_proc_misc_ld_str: data processing, misc, load and
             store insn recording  (arm)
          > arm_record_extension_space:arm extension space insn recording
             (arm)
          > arm_record_strx: str(X) type insn recording  (arm)
          > sbo_sbz: checks for mendatory sbo and sbz fields in insn,

          added new data structures:
          > insn_decode_record_t: local record structure which contains insn's
          record, which includes both reg and memory.

          REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
          in local record which is finally processed by arm_rocess_record.

	* arm-tdep.h: arm-reversible data structures

	  > modified gdbarch_tdep: added member (function pointer) arm_swi_record
	     which is supposed to be recording system calls
	  > arm_process_record externed.
	

Regards,
Oza.
On Sun, Dec 4, 2011 at 7:16 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 12/04/2011 03:01 AM, oza Pawandeep wrote:
>> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
>> --- arm_orig/ChangeLog        2011-12-03 18:05:04.000000000 +0530
>> +++ arm_new/ChangeLog 2011-12-03 19:48:56.000000000 +0530
>> @@ -1,3 +1,9 @@
>> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
>> +
>> +     * arm-linux-tdep.c: Added arm-reversible and process record
>> +     * arm-tdep.c: arm-reversible-debugging implementation
>> +     * arm-tdep.h: arm-reversible data structures
>> +
>
> ChangeLog like this is not accurate to reflect your changes.  "Add
> reverse debugging and process record for ARM" is sort of summary of your
> patch, but in ChangeLog, we usually need more details on function level.
>
> Please read other ChangeLog entries in ChangeLog, and see how it is
> written.  Or, you can read this
>
> http://www.gnu.org/prep/standards/standards.html#Change-Logs
>
> --
> Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04  8:26                                                 ` oza Pawandeep
@ 2011-12-04 11:33                                                   ` oza Pawandeep
  2011-12-04 13:29                                                     ` Petr Hluzín
  2011-12-04 14:46                                                     ` Yao Qi
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04 11:33 UTC (permalink / raw)
  To: Yao Qi, Petr Hluzín, Tom Tromey
  Cc: paawan oza, gdb-patches, chandra krishnappa

Hi,

Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
Change log is elaborated; I am looking forwarding to adding more
details if need. seeking for your feedback on the same.

diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-04 16:45:00.000000000 +0530
@@ -1,3 +1,65 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c: arm_linux_init_abi modified to include
+	   arm reversible debugging feature.
+          registered arm_process_record to gdb_arch
+	   syscall pointer initialization.
+
+	* arm-tdep.c: arm-reversible-debugging implementation.
+	  newly added functions are as follows.
+	
+          > arm_process_record: handles basic initialization and record
+             summarisation, decodes basic insn ids, on which it hands over
+             controls to decode_insn.
+          > deallocate_reg_mem : clean up function
+          > decode_insn: Decodes arm/thumb insn and calls appropriate
+             decoding routine to record the change.
+          > thumb_record_branch: branch insn reording (thumb)
+          > thumb_record_ldm_stm_swi: load, store and sycall insn
+             recoding  (thumb)
+          > thumb_record_misc: misc insn recording  (thumb)
+          > thumb_record_ld_st_stack: store and stack insn recording  (thumb)
+          > thumb_record_ld_st_imm_offset: load, store with immediate offset
+             insn recording  (thumb)
+          > thumb_record_ld_st_reg_offset: load, store with register offset
+             recording  (thumb)
+          > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
+             and move insn recording  (thumb)
+          > thumb_record_shift_add_sub: shift, add and sub insn recording
+             (thumb)
+          > arm_record_coproc_data_proc: coprocessor and data processing
+             recording (partially implemented) (arm)
+          > arm_record_coproc: coprocessor insn recording
+             (partially implemented) (arm)
+          > arm_record_b_bl: branch insn recording (arm)
+          > arm_record_ld_st_multiple: load and store multiple insn recording
+             (arm)
+          > arm_record_ld_st_reg_offset: load and store reg offset recording
+             (arm)
+          > arm_record_ld_st_imm_offset: load and store immediate offset
+             recording (arm)
+          > arm_record_data_proc_imm: data processing insn recording  (arm)
+          > arm_record_data_proc_misc_ld_str: data processing, misc, load and
+             store insn recording  (arm)
+          > arm_record_extension_space:arm extension space insn recording
+             (arm)
+          > arm_record_strx: str(X) type insn recording  (arm)
+          > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
+
+          added new data structures:
+          > insn_decode_record_t: local record structure which contains insn's
+          record, which includes both reg and memory.
+
+          REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
+          in local record which is finally processed by arm_rocess_record.
+
+	* arm-tdep.h: arm-reversible data structures
+
+	  > modified gdbarch_tdep: added member (function pointer) arm_swi_record
+	     which is supposed to be recording system calls
+	  > arm_process_record externed.
+	
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-04 13:02:15.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
 			   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 (0);
+    }
+
+  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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04 11:33                                                   ` oza Pawandeep
@ 2011-12-04 13:29                                                     ` Petr Hluzín
  2011-12-04 14:46                                                     ` Yao Qi
  1 sibling, 0 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-12-04 13:29 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Yao Qi, Tom Tromey, paawan oza, gdb-patches, chandra krishnappa

2011/12/4 oza Pawandeep <oza.pawandeep@gmail.com>:
> Hi,
>
> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
> Change log is elaborated; I am looking forwarding to adding more
> details if need. seeking for your feedback on the same.
>
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog  2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog   2011-12-04 16:45:00.000000000 +0530
> @@ -1,3 +1,65 @@
> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
> +
> +       * arm-linux-tdep.c: arm_linux_init_abi modified to include
> +          arm reversible debugging feature.
> +          registered arm_process_record to gdb_arch
> +          syscall pointer initialization.
> +
> +       * arm-tdep.c: arm-reversible-debugging implementation.
> +         newly added functions are as follows.
> +
> +          > arm_process_record: handles basic initialization and record
> +             summarisation, decodes basic insn ids, on which it hands over
> +             controls to decode_insn.
> +          > deallocate_reg_mem : clean up function
> +          > decode_insn: Decodes arm/thumb insn and calls appropriate
> +             decoding routine to record the change.
> +          > thumb_record_branch: branch insn reording (thumb)
> +          > thumb_record_ldm_stm_swi: load, store and sycall insn
> +             recoding  (thumb)
> +          > thumb_record_misc: misc insn recording  (thumb)
> +          > thumb_record_ld_st_stack: store and stack insn recording  (thumb)
> +          > thumb_record_ld_st_imm_offset: load, store with immediate offset
> +             insn recording  (thumb)
> +          > thumb_record_ld_st_reg_offset: load, store with register offset
> +             recording  (thumb)
> +          > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
> +             and move insn recording  (thumb)
> +          > thumb_record_shift_add_sub: shift, add and sub insn recording
> +             (thumb)
> +          > arm_record_coproc_data_proc: coprocessor and data processing
> +             recording (partially implemented) (arm)
> +          > arm_record_coproc: coprocessor insn recording
> +             (partially implemented) (arm)
> +          > arm_record_b_bl: branch insn recording (arm)
> +          > arm_record_ld_st_multiple: load and store multiple insn recording
> +             (arm)
> +          > arm_record_ld_st_reg_offset: load and store reg offset recording
> +             (arm)
> +          > arm_record_ld_st_imm_offset: load and store immediate offset
> +             recording (arm)
> +          > arm_record_data_proc_imm: data processing insn recording  (arm)
> +          > arm_record_data_proc_misc_ld_str: data processing, misc, load and
> +             store insn recording  (arm)
> +          > arm_record_extension_space:arm extension space insn recording
> +             (arm)
> +          > arm_record_strx: str(X) type insn recording  (arm)
> +          > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
> +
> +          added new data structures:
> +          > insn_decode_record_t: local record structure which contains insn's
> +          record, which includes both reg and memory.
> +
> +          REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
> +          in local record which is finally processed by arm_rocess_record.
> +
> +       * arm-tdep.h: arm-reversible data structures
> +
> +         > modified gdbarch_tdep: added member (function pointer) arm_swi_record
> +            which is supposed to be recording system calls
> +         > arm_process_record externed.
> +
> +

WOW, thats a lot of text. Other people's changelog entries are more
terse. For example the GNU guidelines say "For example, “New function”
is enough for the change log when you add a function, because there
should be a comment before the function definition to explain what it
does."

In function decode_insn():
> +
> +  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;
> +        }
> +    }

If the extract_arm_insn() call fails then the function returns only if
`record_debug' is true. This is strange. Enabling debugging traces
usually expected to only affect printing, here it affects behavior of
the decode_insn() function. Plus the rest of the function seems to
misbehave if it is passed failed result in `arm_record'. I guess the
`return -1;' statement should be moved outside of body of condition
`if (record_debug)'. Unortunatelly I did not notice that earlier.

In arm_process_record():
> +
> +  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;
> +        }
> +    }

The same applies here.

Except the one last thing the patch looks good to me now. My previous
suggestions have been resolved.
As always, I did not check whitespace, ARM semantics and Changelog entries.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04 11:33                                                   ` oza Pawandeep
  2011-12-04 13:29                                                     ` Petr Hluzín
@ 2011-12-04 14:46                                                     ` Yao Qi
  2011-12-04 17:00                                                       ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04 14:46 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

On 12/04/2011 07:32 PM, oza Pawandeep wrote:
> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
> Change log is elaborated; I am looking forwarding to adding more
> details if need. seeking for your feedback on the same.
> 

The format of ChangeLog looks odd to me.  Some comments below,

> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog	2011-12-04 16:45:00.000000000 +0530
> @@ -1,3 +1,65 @@
> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
> +
> +	* arm-linux-tdep.c: arm_linux_init_abi modified to include
> +	   arm reversible debugging feature.
> +          registered arm_process_record to gdb_arch
> +	   syscall pointer initialization.

It can be

	* arm-linux-tdep.c (arm_linux_init_abi): Call
	set_gdbarch_process_record.
	Initialize `arm_swi_record' field.

Please care about the format of changelog entry, usually it is like this,

[tab]	* file-you-modified.c (function-you-modified): What is your
[tab]	Change.

Note that we write "what is changed" in ChangeLog, instead of "why is
changed".

> +
> +	* arm-tdep.c: arm-reversible-debugging implementation.
> +	  newly added functions are as follows.
> +	
> +          > arm_process_record: handles basic initialization and record
> +             summarisation, decodes basic insn ids, on which it hands over
> +             controls to decode_insn.

So, we don't need so much details in changelog like this, we can write
it in this way,

	* arm-tdep.c (arm_process_record): New.

There are still many new added functions, and I think they can
documented in ChangeLog in the same way.

> +          > deallocate_reg_mem : clean up function
> +          > decode_insn: Decodes arm/thumb insn and calls appropriate
> +             decoding routine to record the change.
> +          > thumb_record_branch: branch insn reording (thumb)
> +          > thumb_record_ldm_stm_swi: load, store and sycall insn
> +             recoding  (thumb)
> +          > thumb_record_misc: misc insn recording  (thumb)
> +          > thumb_record_ld_st_stack: store and stack insn recording  (thumb)
> +          > thumb_record_ld_st_imm_offset: load, store with immediate offset
> +             insn recording  (thumb)
> +          > thumb_record_ld_st_reg_offset: load, store with register offset
> +             recording  (thumb)
> +          > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
> +             and move insn recording  (thumb)
> +          > thumb_record_shift_add_sub: shift, add and sub insn recording
> +             (thumb)
> +          > arm_record_coproc_data_proc: coprocessor and data processing
> +             recording (partially implemented) (arm)
> +          > arm_record_coproc: coprocessor insn recording
> +             (partially implemented) (arm)
> +          > arm_record_b_bl: branch insn recording (arm)
> +          > arm_record_ld_st_multiple: load and store multiple insn recording
> +             (arm)
> +          > arm_record_ld_st_reg_offset: load and store reg offset recording
> +             (arm)
> +          > arm_record_ld_st_imm_offset: load and store immediate offset
> +             recording (arm)
> +          > arm_record_data_proc_imm: data processing insn recording  (arm)
> +          > arm_record_data_proc_misc_ld_str: data processing, misc, load and
> +             store insn recording  (arm)
> +          > arm_record_extension_space:arm extension space insn recording
> +             (arm)
> +          > arm_record_strx: str(X) type insn recording  (arm)
> +          > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
> +
> +          added new data structures:
> +          > insn_decode_record_t: local record structure which contains insn's
> +          record, which includes both reg and memory.
> +
> +          REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
> +          in local record which is finally processed by arm_rocess_record.
> +
> +	* arm-tdep.h: arm-reversible data structures
> +
> +	  > modified gdbarch_tdep: added member (function pointer) arm_swi_record
> +	     which is supposed to be recording system calls

This can be written in this way,

	* arm-tdep.h (struct gdbarch_tdep): New field `arm_swi_record'.

> +	  > arm_process_record externed.
> +	
> +	

Again, reading other existing changelog entries must be helpful for you
to write your own in a correct way/format. :)

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04 14:46                                                     ` Yao Qi
@ 2011-12-04 17:00                                                       ` oza Pawandeep
  2011-12-04 23:46                                                         ` Yao Qi
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04 17:00 UTC (permalink / raw)
  To: Yao Qi
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

Hi Yao,

I have modified it; please have a look below.
I have observed that some people have given little description about
functions: but some places its missing.
I think it is better to give small description:

2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>

	* arm-linux-tdep.c (arm_linux_init_abi): Call
       set_gdbarch_process_record.
       Initialize `arm_swi_record' field.

	* arm-tdep.c (arm_process_record): New function.
	(deallocate_reg_mem): New function.
	(decode_insn): New function.
	(thumb_record_branch): New function.
	(thumb_record_ldm_stm_swi(): New function.
	(thumb_record_misc): New function.
	(thumb_record_ld_st_stack): New function.
	(thumb_record_ld_st_imm_offset): New function.
	(thumb_record_ld_st_reg_offset(): New function.
	(thumb_record_add_sub_cmp_mov): New function.
	(thumb_record_shift_add_sub): New function.
	(arm_record_coproc_data_proc): New function.
	(arm_record_coproc): New function.
	(arm_record_b_bl): New function.
	(arm_record_ld_st_multiple): New function.
	(arm_record_ld_st_reg_offset): New function.
	(arm_record_ld_st_imm_offset): New function.
	(arm_record_data_proc_imm): New function.
	(arm_record_data_proc_misc_ld_str): New function.
	(arm_record_extension_space): New function.
	(arm_record_strx): New function.
	(sbo_sbz): New function.
	(struct insn_decode_record): New Structure. arm insn record
	(REG_ALLOC): New Macros. use it for reg allocations
	(MEM_ALLOC): New Macros. use it for memory allocations

	* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'


Regards,
Oza.

On Sun, Dec 4, 2011 at 8:15 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 12/04/2011 07:32 PM, oza Pawandeep wrote:
>> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
>> Change log is elaborated; I am looking forwarding to adding more
>> details if need. seeking for your feedback on the same.
>>
>
> The format of ChangeLog looks odd to me.  Some comments below,
>
>> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
>> --- arm_orig/ChangeLog        2011-12-03 18:05:04.000000000 +0530
>> +++ arm_new/ChangeLog 2011-12-04 16:45:00.000000000 +0530
>> @@ -1,3 +1,65 @@
>> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
>> +
>> +     * arm-linux-tdep.c: arm_linux_init_abi modified to include
>> +        arm reversible debugging feature.
>> +          registered arm_process_record to gdb_arch
>> +        syscall pointer initialization.
>
> It can be
>
>        * arm-linux-tdep.c (arm_linux_init_abi): Call
>        set_gdbarch_process_record.
>        Initialize `arm_swi_record' field.
>
> Please care about the format of changelog entry, usually it is like this,
>
> [tab]   * file-you-modified.c (function-you-modified): What is your
> [tab]   Change.
>
> Note that we write "what is changed" in ChangeLog, instead of "why is
> changed".
>
>> +
>> +     * arm-tdep.c: arm-reversible-debugging implementation.
>> +       newly added functions are as follows.
>> +
>> +          > arm_process_record: handles basic initialization and record
>> +             summarisation, decodes basic insn ids, on which it hands over
>> +             controls to decode_insn.
>
> So, we don't need so much details in changelog like this, we can write
> it in this way,
>
>        * arm-tdep.c (arm_process_record): New.
>
> There are still many new added functions, and I think they can
> documented in ChangeLog in the same way.
>
>> +          > deallocate_reg_mem : clean up function
>> +          > decode_insn: Decodes arm/thumb insn and calls appropriate
>> +             decoding routine to record the change.
>> +          > thumb_record_branch: branch insn reording (thumb)
>> +          > thumb_record_ldm_stm_swi: load, store and sycall insn
>> +             recoding  (thumb)
>> +          > thumb_record_misc: misc insn recording  (thumb)
>> +          > thumb_record_ld_st_stack: store and stack insn recording  (thumb)
>> +          > thumb_record_ld_st_imm_offset: load, store with immediate offset
>> +             insn recording  (thumb)
>> +          > thumb_record_ld_st_reg_offset: load, store with register offset
>> +             recording  (thumb)
>> +          > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
>> +             and move insn recording  (thumb)
>> +          > thumb_record_shift_add_sub: shift, add and sub insn recording
>> +             (thumb)
>> +          > arm_record_coproc_data_proc: coprocessor and data processing
>> +             recording (partially implemented) (arm)
>> +          > arm_record_coproc: coprocessor insn recording
>> +             (partially implemented) (arm)
>> +          > arm_record_b_bl: branch insn recording (arm)
>> +          > arm_record_ld_st_multiple: load and store multiple insn recording
>> +             (arm)
>> +          > arm_record_ld_st_reg_offset: load and store reg offset recording
>> +             (arm)
>> +          > arm_record_ld_st_imm_offset: load and store immediate offset
>> +             recording (arm)
>> +          > arm_record_data_proc_imm: data processing insn recording  (arm)
>> +          > arm_record_data_proc_misc_ld_str: data processing, misc, load and
>> +             store insn recording  (arm)
>> +          > arm_record_extension_space:arm extension space insn recording
>> +             (arm)
>> +          > arm_record_strx: str(X) type insn recording  (arm)
>> +          > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
>> +
>> +          added new data structures:
>> +          > insn_decode_record_t: local record structure which contains insn's
>> +          record, which includes both reg and memory.
>> +
>> +          REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
>> +          in local record which is finally processed by arm_rocess_record.
>> +
>> +     * arm-tdep.h: arm-reversible data structures
>> +
>> +       > modified gdbarch_tdep: added member (function pointer) arm_swi_record
>> +          which is supposed to be recording system calls
>
> This can be written in this way,
>
>        * arm-tdep.h (struct gdbarch_tdep): New field `arm_swi_record'.
>
>> +       > arm_process_record externed.
>> +
>> +
>
> Again, reading other existing changelog entries must be helpful for you
> to write your own in a correct way/format. :)
>
> --
> Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04 17:00                                                       ` oza Pawandeep
@ 2011-12-04 23:46                                                         ` Yao Qi
  2011-12-05  5:35                                                           ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04 23:46 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

On 12/05/2011 01:00 AM, oza Pawandeep wrote:
> 	(struct insn_decode_record): New Structure. arm insn record

ChangeLog entry can not be a sentence, but it should be ended with "."
We can say "New structure for arm insn record" or just "New".

> 	(REG_ALLOC): New Macros. use it for reg allocations

"New macro for reg allocations."

> 	(MEM_ALLOC): New Macros. use it for memory allocations

"New macro for memory allocations."

The rest of ChangeLog looks right to me, so I don't have any other
comments on ChangeLog.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-04 23:46                                                         ` Yao Qi
@ 2011-12-05  5:35                                                           ` oza Pawandeep
  2011-12-05  8:12                                                             ` Yao Qi
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-05  5:35 UTC (permalink / raw)
  To: Yao Qi
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

Hi Tom, Yao and Petr,

This patch includes your final comments implemented; and Change log
corrected as well.
If there are any more formatting issues, I will be happy to correct them.
please find the last patch below.



diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c (arm_linux_init_abi): Call
+       set_gdbarch_process_record.
+       Initialize `arm_swi_record' field.
+
+	* arm-tdep.c (arm_process_record): New function.
+	(deallocate_reg_mem): New function.
+	(decode_insn): New function.
+	(thumb_record_branch): New function.
+	(thumb_record_ldm_stm_swi(): New function.
+	(thumb_record_misc): New function.
+	(thumb_record_ld_st_stack): New function.
+	(thumb_record_ld_st_imm_offset): New function.
+	(thumb_record_ld_st_reg_offset(): New function.
+	(thumb_record_add_sub_cmp_mov): New function.
+	(thumb_record_shift_add_sub): New function.
+	(arm_record_coproc_data_proc): New function.
+	(arm_record_coproc): New function.
+	(arm_record_b_bl): New function.
+	(arm_record_ld_st_multiple): New function.
+	(arm_record_ld_st_reg_offset): New function.
+	(arm_record_ld_st_imm_offset): New function.
+	(arm_record_data_proc_imm): New function.
+	(arm_record_data_proc_misc_ld_str): New function.
+	(arm_record_extension_space): New function.
+	(arm_record_strx): New function.
+	(sbo_sbz): New function.
+	(struct insn_decode_record): New Structure for arm insn record.
+	(REG_ALLOC): New Macro for reg allocations.
+	(MEM_ALLOC): New Macro for memory allocations.
+
+	* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
 			   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 (0);
+    }
+
+  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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-05  5:35                                                           ` oza Pawandeep
@ 2011-12-05  8:12                                                             ` Yao Qi
  2011-12-05 16:02                                                               ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-05  8:12 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

On 12/05/2011 01:35 PM, oza Pawandeep wrote:
> +	(struct insn_decode_record): New Structure for arm insn record.
> +	(REG_ALLOC): New Macro for reg allocations.
> +	(MEM_ALLOC): New Macro for memory allocations.

Any reason to capitalize "S" in "Structure" and "M" in "Macro"?  I think
they should be lower-case'ed.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-05  8:12                                                             ` Yao Qi
@ 2011-12-05 16:02                                                               ` oza Pawandeep
  2011-12-19  6:26                                                                 ` oza Pawandeep
  2011-12-20 19:11                                                                 ` Tom Tromey
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-05 16:02 UTC (permalink / raw)
  To: Yao Qi
  Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
	chandra krishnappa

Hi Yao,

here is the latest patch with Changelog comment fixed.

diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c (arm_linux_init_abi): Call
+       set_gdbarch_process_record.
+       Initialize `arm_swi_record' field.
+
+	* arm-tdep.c (arm_process_record): New function.
+	(deallocate_reg_mem): New function.
+	(decode_insn): New function.
+	(thumb_record_branch): New function.
+	(thumb_record_ldm_stm_swi(): New function.
+	(thumb_record_misc): New function.
+	(thumb_record_ld_st_stack): New function.
+	(thumb_record_ld_st_imm_offset): New function.
+	(thumb_record_ld_st_reg_offset(): New function.
+	(thumb_record_add_sub_cmp_mov): New function.
+	(thumb_record_shift_add_sub): New function.
+	(arm_record_coproc_data_proc): New function.
+	(arm_record_coproc): New function.
+	(arm_record_b_bl): New function.
+	(arm_record_ld_st_multiple): New function.
+	(arm_record_ld_st_reg_offset): New function.
+	(arm_record_ld_st_imm_offset): New function.
+	(arm_record_data_proc_imm): New function.
+	(arm_record_data_proc_misc_ld_str): New function.
+	(arm_record_extension_space): New function.
+	(arm_record_strx): New function.
+	(sbo_sbz): New function.
+	(struct insn_decode_record): New structure for arm insn record.
+	(REG_ALLOC): New macro for reg allocations.
+	(MEM_ALLOC): New macro for memory allocations.
+
+	* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
 			   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 (0);
+    }
+
+  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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-05 16:02                                                               ` oza Pawandeep
@ 2011-12-19  6:26                                                                 ` oza Pawandeep
  2011-12-20 19:11                                                                 ` Tom Tromey
  1 sibling, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-19  6:26 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa, Yao Qi

Hi Tom,

I suppose you have no more comment for the latest patch, and rest of
the comments are closed
too. Changelog is attached too.

please let me know the next step;

Regards,
Oza.


On Mon, Dec 5, 2011 at 9:05 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> here is the latest patch with Changelog comment fixed.
>
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog  2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog   2011-12-04 23:36:50.000000000 +0530
> @@ -1,3 +1,37 @@
> +2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
> +
> +       * arm-linux-tdep.c (arm_linux_init_abi): Call
> +       set_gdbarch_process_record.
> +       Initialize `arm_swi_record' field.
> +
> +       * arm-tdep.c (arm_process_record): New function.
> +       (deallocate_reg_mem): New function.
> +       (decode_insn): New function.
> +       (thumb_record_branch): New function.
> +       (thumb_record_ldm_stm_swi(): New function.
> +       (thumb_record_misc): New function.
> +       (thumb_record_ld_st_stack): New function.
> +       (thumb_record_ld_st_imm_offset): New function.
> +       (thumb_record_ld_st_reg_offset(): New function.
> +       (thumb_record_add_sub_cmp_mov): New function.
> +       (thumb_record_shift_add_sub): New function.
> +       (arm_record_coproc_data_proc): New function.
> +       (arm_record_coproc): New function.
> +       (arm_record_b_bl): New function.
> +       (arm_record_ld_st_multiple): New function.
> +       (arm_record_ld_st_reg_offset): New function.
> +       (arm_record_ld_st_imm_offset): New function.
> +       (arm_record_data_proc_imm): New function.
> +       (arm_record_data_proc_misc_ld_str): New function.
> +       (arm_record_extension_space): New function.
> +       (arm_record_strx): New function.
> +       (sbo_sbz): New function.
> +       (struct insn_decode_record): New structure for arm insn record.
> +       (REG_ALLOC): New macro for reg allocations.
> +       (MEM_ALLOC): New macro for memory allocations.
> +
> +       * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
> +
>  2011-11-09  Roland McGrath  <mcgrathr@google.com>
>
>        * configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c   2011-12-03 18:06:39.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-12-03 19:28:27.000000000 +0530
> @@ -1148,8 +1148,14 @@
>                                           simple_displaced_step_free_closure);
>   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
>
> +  /* Reversible debugging, process record.  */
> +  set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>
>   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  /* Syscall record.  */
> +  tdep->arm_swi_record = NULL;
>  }
>
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
> +++ arm_new/arm-tdep.c  2011-12-04 22:04:36.000000000 +0530
> @@ -55,6 +55,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
>
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
>  #include "features/arm-with-iwmmxt.c"
>  #include "features/arm-with-vfpv2.c"
> @@ -10175,3 +10177,2063 @@
>                           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 (0);
> +    }
> +
> +  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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
> no_of_rec++)
> +            {
> +              if (record_arch_list_add_reg (arm_record.regcache ,
> +                                            arm_record.arm_regs[no_of_rec]))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +
> +  deallocate_reg_mem (&arm_record);
> +
> +  return ret;
> +}
> +
> +
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
> +++ arm_new/arm-tdep.h  2011-12-03 17:52:28.000000000 +0530
> @@ -201,6 +201,9 @@
>   /* Return the expected next PC if FRAME is stopped at a syscall
>      instruction.  */
>   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
>
>  /* Structures used for displaced stepping.  */
> @@ -330,6 +333,8 @@
>    instruction?  */
>  extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> +                               struct regcache *regcache, CORE_ADDR addr);
>  /* Functions exported from armbsd-tdep.h.  */
>
>  /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-03  8:20                                     ` oza Pawandeep
  2011-12-03 14:18                                       ` oza Pawandeep
  2011-12-03 15:06                                       ` oza Pawandeep
@ 2011-12-20 19:05                                       ` Tom Tromey
  2 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-12-20 19:05 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> 2) I could not write changelog entry because I have been getting
Oza> commments, and moreover I was not sure whether I should get changelog
Oza> entry from latest gdb 7.3 or latest current working version of gdb ? I
Oza> think later is true in my understanding.
Oza> I will include changelog this time; sorry for having you point it out
Oza> in all reviews.

Yeah, ChangeLogs are a bit of a pain.  There are various ways to deal
with them, e.g., keeping them in a separate file until checkin time.
I use different techniques depending on the context.  Anyway, I'm sorry
about it, but for the time being it is just a cost of working on GDB.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-05 16:02                                                               ` oza Pawandeep
  2011-12-19  6:26                                                                 ` oza Pawandeep
@ 2011-12-20 19:11                                                                 ` Tom Tromey
  2011-12-28 12:43                                                                   ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-12-20 19:11 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> here is the latest patch with Changelog comment fixed.

One last little nit...

Oza> +      gdb_assert (0);

Please change this to gdb_assert_not_reached.

This is ok with this change.

Could you write a NEWS entry for this change?

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-20 19:11                                                                 ` Tom Tromey
@ 2011-12-28 12:43                                                                   ` oza Pawandeep
  2012-01-05 11:01                                                                     ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-28 12:43 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

Thank you for your feedback;
I have fixed your comment, and also written NEWS entry; please have a look.

PATCH STARTS
--------------------------

diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c (arm_linux_init_abi): Call
+       set_gdbarch_process_record.
+       Initialize `arm_swi_record' field.
+
+	* arm-tdep.c (arm_process_record): New function.
+	(deallocate_reg_mem): New function.
+	(decode_insn): New function.
+	(thumb_record_branch): New function.
+	(thumb_record_ldm_stm_swi(): New function.
+	(thumb_record_misc): New function.
+	(thumb_record_ld_st_stack): New function.
+	(thumb_record_ld_st_imm_offset): New function.
+	(thumb_record_ld_st_reg_offset(): New function.
+	(thumb_record_add_sub_cmp_mov): New function.
+	(thumb_record_shift_add_sub): New function.
+	(arm_record_coproc_data_proc): New function.
+	(arm_record_coproc): New function.
+	(arm_record_b_bl): New function.
+	(arm_record_ld_st_multiple): New function.
+	(arm_record_ld_st_reg_offset): New function.
+	(arm_record_ld_st_imm_offset): New function.
+	(arm_record_data_proc_imm): New function.
+	(arm_record_data_proc_misc_ld_str): New function.
+	(arm_record_extension_space): New function.
+	(arm_record_strx): New function.
+	(sbo_sbz): New function.
+	(struct insn_decode_record): New structure for arm insn record.
+	(REG_ALLOC): New macro for reg allocations.
+	(MEM_ALLOC): New macro for memory allocations.
+
+	* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/NEWS arm_new/NEWS
--- arm_orig/NEWS	2011-12-28 12:25:47.000000000 +0530
+++ arm_new/NEWS	2011-12-28 12:32:10.000000000 +0530
@@ -3,6 +3,10 @@

 *** Changes since GDB 7.3.1

+* GDB now supports reversible debugging on ARM, it allows you to
+  debug basic ARM and THUMB instructions, and provides
+  record/replay support.
+
 * GDB now allows you to skip uninteresting functions and files when
   stepping with the "skip function" and "skip file" commands.

diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
 			   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 arm 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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-12-28 12:43                                                                   ` oza Pawandeep
@ 2012-01-05 11:01                                                                     ` oza Pawandeep
  2012-01-05 12:03                                                                       ` Eli Zaretskii
  2012-01-05 16:17                                                                       ` Tom Tromey
  0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2012-01-05 11:01 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

Latest patch after own review.

PATCH STARTS
------------------------

diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog	2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog	2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03  Oza Pawandeep   <oza.pawandeep@gmail.com>
+
+	* arm-linux-tdep.c (arm_linux_init_abi): Call
+       set_gdbarch_process_record.
+       Initialize `arm_swi_record' field.
+
+	* arm-tdep.c (arm_process_record): New function.
+	(deallocate_reg_mem): New function.
+	(decode_insn): New function.
+	(thumb_record_branch): New function.
+	(thumb_record_ldm_stm_swi(): New function.
+	(thumb_record_misc): New function.
+	(thumb_record_ld_st_stack): New function.
+	(thumb_record_ld_st_imm_offset): New function.
+	(thumb_record_ld_st_reg_offset(): New function.
+	(thumb_record_add_sub_cmp_mov): New function.
+	(thumb_record_shift_add_sub): New function.
+	(arm_record_coproc_data_proc): New function.
+	(arm_record_coproc): New function.
+	(arm_record_b_bl): New function.
+	(arm_record_ld_st_multiple): New function.
+	(arm_record_ld_st_reg_offset): New function.
+	(arm_record_ld_st_imm_offset): New function.
+	(arm_record_data_proc_imm): New function.
+	(arm_record_data_proc_misc_ld_str): New function.
+	(arm_record_extension_space): New function.
+	(arm_record_strx): New function.
+	(sbo_sbz): New function.
+	(struct insn_decode_record): New structure for arm insn record.
+	(REG_ALLOC): New macro for reg allocations.
+	(MEM_ALLOC): New macro for memory allocations.
+
+	* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+	
 2011-11-09  Roland McGrath  <mcgrathr@google.com>

 	* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/NEWS arm_new/NEWS
--- arm_orig/NEWS	2011-12-28 12:25:47.000000000 +0530
+++ arm_new/NEWS	2011-12-28 12:32:10.000000000 +0530
@@ -3,6 +3,10 @@

 *** Changes since GDB 7.3.1

+* GDB now supports reversible debugging on ARM, it allows you to
+  debug basic ARM and THUMB instructions, and provides
+  record/replay support.
+
 * GDB now allows you to skip uninteresting functions and files when
   stepping with the "skip function" and "skip file" commands.

diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c	2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);

+  /* Reversible debugging, process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+

   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  /* Syscall record.  */
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c	2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c	2012-01-05 16:24:25.000000000 +0530
@@ -55,6 +55,8 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"
 #include "features/arm-with-iwmmxt.c"
 #include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
 			   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_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache ,
+                                            arm_record.arm_regs[no_of_rec]))
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+
+  deallocate_reg_mem (&arm_record);
+
+  return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h	2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h	2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -330,6 +333,8 @@
    instruction?  */
 extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                               struct regcache *regcache, CORE_ADDR addr);
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-05 11:01                                                                     ` oza Pawandeep
@ 2012-01-05 12:03                                                                       ` Eli Zaretskii
  2012-01-05 16:17                                                                       ` Tom Tromey
  1 sibling, 0 replies; 128+ messages in thread
From: Eli Zaretskii @ 2012-01-05 12:03 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: tromey, yao, petr.hluzin, paawan1982, gdb-patches, chandra_roadking

> Date: Thu, 5 Jan 2012 16:30:26 +0530
> From: oza Pawandeep <oza.pawandeep@gmail.com>
> Cc: Yao Qi <yao@codesourcery.com>, Petr Hluzín <petr.hluzin@gmail.com>, 	paawan oza <paawan1982@yahoo.com>, 	"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, 	chandra krishnappa <chandra_roadking@yahoo.com>
> 
> diff -urN arm_orig/NEWS arm_new/NEWS
> --- arm_orig/NEWS	2011-12-28 12:25:47.000000000 +0530
> +++ arm_new/NEWS	2011-12-28 12:32:10.000000000 +0530
> @@ -3,6 +3,10 @@
> 
>  *** Changes since GDB 7.3.1
> 
> +* GDB now supports reversible debugging on ARM, it allows you to
> +  debug basic ARM and THUMB instructions, and provides
> +  record/replay support.
> +
>  * GDB now allows you to skip uninteresting functions and files when
>    stepping with the "skip function" and "skip file" commands.

This part is OK.  Thanks.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-05 11:01                                                                     ` oza Pawandeep
  2012-01-05 12:03                                                                       ` Eli Zaretskii
@ 2012-01-05 16:17                                                                       ` Tom Tromey
  2012-01-05 18:17                                                                         ` oza Pawandeep
  1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-05 16:17 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

oza> Latest patch after own review.

Great, you can commit it now.

Thanks for persevering.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-05 16:17                                                                       ` Tom Tromey
@ 2012-01-05 18:17                                                                         ` oza Pawandeep
  2012-01-06  8:06                                                                           ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-05 18:17 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

My last patch was committed by Michael Snyder.
I believe neither do I have a way nor have an access for check-in.
please guide me with the same.

Regards,
Oza.


On Thu, Jan 5, 2012 at 9:47 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> Latest patch after own review.
>
> Great, you can commit it now.
>
> Thanks for persevering.
>
> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-05 18:17                                                                         ` oza Pawandeep
@ 2012-01-06  8:06                                                                           ` oza Pawandeep
  2012-01-06 19:13                                                                             ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-06  8:06 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

If I understood you correctly, I should be submitting copyright
information, and changes.
Am I getting it right ?

Regards,
Oza.

On Thu, Jan 5, 2012 at 11:47 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> My last patch was committed by Michael Snyder.
> I believe neither do I have a way nor have an access for check-in.
> please guide me with the same.
>
> Regards,
> Oza.
>
>
> On Thu, Jan 5, 2012 at 9:47 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>>
>> oza> Latest patch after own review.
>>
>> Great, you can commit it now.
>>
>> Thanks for persevering.
>>
>> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-06  8:06                                                                           ` oza Pawandeep
@ 2012-01-06 19:13                                                                             ` Tom Tromey
  2012-01-07  6:31                                                                               ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-06 19:13 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> If I understood you correctly, I should be submitting copyright
Oza> information, and changes.

Do you have paperwork on file with the FSF already?
You ought to, given that you have another patch in the tree; though
perhaps it was not big enough.

If you do not have paperwork, then you must file it before we can put
your change in.

If you do have paperwork, I can put it in soon.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-06 19:13                                                                             ` Tom Tromey
@ 2012-01-07  6:31                                                                               ` oza Pawandeep
  2012-01-09 16:25                                                                                 ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-07  6:31 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

Yes, I have paperwork with FSF; as last change was considerably big enough.
Now I am in a process of getting disclaimer from my new firm;
Will post the things along with necessary paperwork.
Thanks for your quick response Tom.

PS: I will be taking phase 3 of the same soon.

Regards,
Oza.

On Fri, Jan 6, 2012 at 11:21 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> Oza> If I understood you correctly, I should be submitting copyright
> Oza> information, and changes.
>
> Do you have paperwork on file with the FSF already?
> You ought to, given that you have another patch in the tree; though
> perhaps it was not big enough.
>
> If you do not have paperwork, then you must file it before we can put
> your change in.
>
> If you do have paperwork, I can put it in soon.
>
> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-07  6:31                                                                               ` oza Pawandeep
@ 2012-01-09 16:25                                                                                 ` Tom Tromey
  2012-02-02  6:29                                                                                   ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-09 16:25 UTC (permalink / raw)
  To: oza Pawandeep
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

oza> Yes, I have paperwork with FSF; as last change was considerably big enough.
oza> Now I am in a process of getting disclaimer from my new firm;
oza> Will post the things along with necessary paperwork.

Ok.  In this case I think we can't put it in until your status is
cleared up.  Please let us know when this happens.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-01-09 16:25                                                                                 ` Tom Tromey
@ 2012-02-02  6:29                                                                                   ` oza Pawandeep
       [not found]                                                                                     ` <m38vkfoiut.fsf@fleche.redhat.com>
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-02-02  6:29 UTC (permalink / raw)
  To: Tom Tromey
  Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa

Hi Tom,

The paperwork is over, and Donlad from FSF has confirmed the same.
I have done basic testing of this final patch and everything looks ok.

The patch is ready to go in, please let me know if I have to attach
any paperwork to the mail.
please let me know, how to proceed further.

Regards,
Oza.



On Mon, Jan 9, 2012 at 9:54 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> Yes, I have paperwork with FSF; as last change was considerably big enough.
> oza> Now I am in a process of getting disclaimer from my new firm;
> oza> Will post the things along with necessary paperwork.
>
> Ok.  In this case I think we can't put it in until your status is
> cleared up.  Please let us know when this happens.
>
> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]                                                                                           ` <CAK1A=4w+yq9AvRMukPcKpZnGjrVnPbE3zdScwRd1Skubt0KHWA@mail.gmail.com>
@ 2012-03-07  5:35                                                                                             ` oza Pawandeep
  2012-03-08 16:32                                                                                               ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-03-07  5:35 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

Hi Tom,

I am afraid as my mails are reaching to you or not, so including patch
mailing list.
I am waiting for the instructions for write-after-approval.
please do the needful.

Regards,
Oza.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-07  5:35                                                                                             ` oza Pawandeep
@ 2012-03-08 16:32                                                                                               ` Tom Tromey
  2012-03-09  9:30                                                                                                 ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-03-08 16:32 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: gdb-patches

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> I am afraid as my mails are reaching to you or not, so including
Oza> patch mailing list.  I am waiting for the instructions for
Oza> write-after-approval.  please do the needful.

Sorry, they got buried in the flood and I then forgot.

Your sourceware account seems to be ready.
So what you must do is:

1. Check out a writeable copy of gdb from CVS

2. Edit gdb/MAINTAINERS to add yourself to the write-after-approval
   section.  Write a ChangeLog entry for this change.  Then post the
   resulting patch as an "FYI" to gdb-patches and commit it.

3. Apply your approved patch and check it in.

In both cases use the ChangeLog entry as the commit message.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-08 16:32                                                                                               ` Tom Tromey
@ 2012-03-09  9:30                                                                                                 ` oza Pawandeep
  2012-03-09 16:47                                                                                                   ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-03-09  9:30 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

Hi Tom,

1 ) How do I check out the writable copy ?

with following ?

Read-write CVS (GDB developers only):
CVS_RSH=ssh ; export CVS_RSH
cvs -d :ext:YOURACCOUNT@sourceware.org:/cvs/gdb co htdocs

2) what is my acount@sourceware.org ?

3) I think I need to install cvs client or cvs package on linux ?

Regards,
Oza.


On Thu, Mar 8, 2012 at 10:01 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> Oza> I am afraid as my mails are reaching to you or not, so including
> Oza> patch mailing list.  I am waiting for the instructions for
> Oza> write-after-approval.  please do the needful.
>
> Sorry, they got buried in the flood and I then forgot.
>
> Your sourceware account seems to be ready.
> So what you must do is:
>
> 1. Check out a writeable copy of gdb from CVS
>
> 2. Edit gdb/MAINTAINERS to add yourself to the write-after-approval
>   section.  Write a ChangeLog entry for this change.  Then post the
>   resulting patch as an "FYI" to gdb-patches and commit it.
>
> 3. Apply your approved patch and check it in.
>
> In both cases use the ChangeLog entry as the commit message.
>
> Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-09  9:30                                                                                                 ` oza Pawandeep
@ 2012-03-09 16:47                                                                                                   ` Tom Tromey
  2012-03-12  6:23                                                                                                     ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-03-09 16:47 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: gdb-patches

>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

Oza> 1 ) How do I check out the writable copy ?
Oza> with following ?

Oza> Read-write CVS (GDB developers only):
Oza> CVS_RSH=ssh ; export CVS_RSH
Oza> cvs -d :ext:YOURACCOUNT@sourceware.org:/cvs/gdb co htdocs

No, this is for the web pages.

Oza> 2) what is my acount@sourceware.org ?

It is the account name you applied for...

Try

cvs -d :ext:ozapawandeep@sourceware.org:/cvs/src co gdb

Oza> 3) I think I need to install cvs client or cvs package on linux ?

Any cvs client should work.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-09 16:47                                                                                                   ` Tom Tromey
@ 2012-03-12  6:23                                                                                                     ` oza Pawandeep
  2012-03-12  6:55                                                                                                       ` Yao Qi
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-03-12  6:23 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

I am trying following.

linux-ghot:/home/oza/mk_patch/gdb # cvs -d
:ext:ozapawandeep@sourceware.org:/cvs/src co gdb
ssh: connect to host sourceware.org port 22: Connection timed out
cvs [checkout aborted]: end of file from server (consult above messages if any)

looks like ssh is returning with some error. would you guide me with the same ?

Regards,
Oza.




On 3/9/12, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> Oza> 1 ) How do I check out the writable copy ?
> Oza> with following ?
>
> Oza> Read-write CVS (GDB developers only):
> Oza> CVS_RSH=ssh ; export CVS_RSH
> Oza> cvs -d :ext:YOURACCOUNT@sourceware.org:/cvs/gdb co htdocs
>
> No, this is for the web pages.
>
> Oza> 2) what is my acount@sourceware.org ?
>
> It is the account name you applied for...
>
> Try
>
> cvs -d :ext:ozapawandeep@sourceware.org:/cvs/src co gdb
>
> Oza> 3) I think I need to install cvs client or cvs package on linux ?
>
> Any cvs client should work.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-12  6:23                                                                                                     ` oza Pawandeep
@ 2012-03-12  6:55                                                                                                       ` Yao Qi
  2012-03-12  9:14                                                                                                         ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Yao Qi @ 2012-03-12  6:55 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Tom Tromey, gdb-patches

On 03/12/2012 02:23 PM, oza Pawandeep wrote:
> I am trying following.
> 
> linux-ghot:/home/oza/mk_patch/gdb # cvs -d
> :ext:ozapawandeep@sourceware.org:/cvs/src co gdb
> ssh: connect to host sourceware.org port 22: Connection timed out
> cvs [checkout aborted]: end of file from server (consult above messages if any)
> 
> looks like ssh is returning with some error. would you guide me with the same ?

I used to get some timeout errors on Monday morning (my time), but CVS
works for me now.

$ cvs -d :ext:qiyao@sourceware.org:/cvs/src co gdb
cvs checkout: Updating src/gdb
U src/gdb/.gitignore
U src/gdb/CONTRIBUTE
....

Your command looks right to me, so could you try again to check code
out?  If you have multiple ssh keys, please make sure you (or cvs) are
using the right key (which is used in your sourceware account
application).  If you still see errors, I have no idea.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-12  6:55                                                                                                       ` Yao Qi
@ 2012-03-12  9:14                                                                                                         ` oza Pawandeep
  2012-03-12 15:32                                                                                                           ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-03-12  9:14 UTC (permalink / raw)
  To: Yao Qi; +Cc: Tom Tromey, gdb-patches

Hi Yao,

From my virtual machine (linux console) ssh sourceware.org is not connecting.
while ssh from same console to any other machine in the nework is connecting.
while from outside [host] sourceware.org is getting connected using putty.
I think I have put my dsa key in the form, which seems to be ok to me.

Regards,
Oza.


On Mon, Mar 12, 2012 at 12:24 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 03/12/2012 02:23 PM, oza Pawandeep wrote:
>> I am trying following.
>>
>> linux-ghot:/home/oza/mk_patch/gdb # cvs -d
>> :ext:ozapawandeep@sourceware.org:/cvs/src co gdb
>> ssh: connect to host sourceware.org port 22: Connection timed out
>> cvs [checkout aborted]: end of file from server (consult above messages if any)
>>
>> looks like ssh is returning with some error. would you guide me with the same ?
>
> I used to get some timeout errors on Monday morning (my time), but CVS
> works for me now.
>
> $ cvs -d :ext:qiyao@sourceware.org:/cvs/src co gdb
> cvs checkout: Updating src/gdb
> U src/gdb/.gitignore
> U src/gdb/CONTRIBUTE
> ....
>
> Your command looks right to me, so could you try again to check code
> out?  If you have multiple ssh keys, please make sure you (or cvs) are
> using the right key (which is used in your sourceware account
> application).  If you still see errors, I have no idea.
>
> --
> Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-12  9:14                                                                                                         ` oza Pawandeep
@ 2012-03-12 15:32                                                                                                           ` oza Pawandeep
  2012-03-12 19:43                                                                                                             ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-03-12 15:32 UTC (permalink / raw)
  To: Yao Qi; +Cc: Tom Tromey, gdb-patches

Hi Tom,

I am still unable to checkout the code. getting timeout errors.
any inputs ?

Regards,
Oza.

On Mon, Mar 12, 2012 at 2:44 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> From my virtual machine (linux console) ssh sourceware.org is not connecting.
> while ssh from same console to any other machine in the nework is connecting.
> while from outside [host] sourceware.org is getting connected using putty.
> I think I have put my dsa key in the form, which seems to be ok to me.
>
> Regards,
> Oza.
>
>
> On Mon, Mar 12, 2012 at 12:24 PM, Yao Qi <yao@codesourcery.com> wrote:
>> On 03/12/2012 02:23 PM, oza Pawandeep wrote:
>>> I am trying following.
>>>
>>> linux-ghot:/home/oza/mk_patch/gdb # cvs -d
>>> :ext:ozapawandeep@sourceware.org:/cvs/src co gdb
>>> ssh: connect to host sourceware.org port 22: Connection timed out
>>> cvs [checkout aborted]: end of file from server (consult above messages if any)
>>>
>>> looks like ssh is returning with some error. would you guide me with the same ?
>>
>> I used to get some timeout errors on Monday morning (my time), but CVS
>> works for me now.
>>
>> $ cvs -d :ext:qiyao@sourceware.org:/cvs/src co gdb
>> cvs checkout: Updating src/gdb
>> U src/gdb/.gitignore
>> U src/gdb/CONTRIBUTE
>> ....
>>
>> Your command looks right to me, so could you try again to check code
>> out?  If you have multiple ssh keys, please make sure you (or cvs) are
>> using the right key (which is used in your sourceware account
>> application).  If you still see errors, I have no idea.
>>
>> --
>> Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-12 15:32                                                                                                           ` oza Pawandeep
@ 2012-03-12 19:43                                                                                                             ` Tom Tromey
  2012-03-13  5:41                                                                                                               ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-03-12 19:43 UTC (permalink / raw)
  To: oza Pawandeep; +Cc: Yao Qi, gdb-patches

>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:

oza> I am still unable to checkout the code. getting timeout errors.
oza> any inputs ?

I don't, sorry.  You could perhaps email me your public key and I could
check it against the key stored on sourceware.  Otherwise, sourceware
ssh works fine for many people, so I presume the difficulty is on your
end.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2012-03-12 19:43                                                                                                             ` Tom Tromey
@ 2012-03-13  5:41                                                                                                               ` oza Pawandeep
  0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2012-03-13  5:41 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Yao Qi, gdb-patches

It looks like VM layer seems to be having the problem.

the results of
'strace ssh sourceware.org'
where connect syscall is failing as below.
connect(3, {sa_family=AF_INET, sin_port=htons(22),
sin_addr=inet_addr("209.132.180.131")}, 16) = -1 ETIMEDOUT (Connection
timed out)

I will try from bare linux machine. for a cross check I am just
pasting public key.

linux-ghot:~/.ssh # cat id_dsa.pub
ssh-dss AAAAB3NzaC1kc3MAAAEBAM1ueRXJ9iKY5gi/hJrLNFCddcnaPrpCj5o5u2cGQj57eXAbS70JZSSZp2ShvF1KilaApaz04dyZCJehcH4XZNXqoRpiIkosXbswp34x8iM8J5eZXvo1L99hpuAmx2AKRrzJNKAt2/L9ozNM6Tn7qvvgxDfqK6IbRuxPWi6EfZq9qsxshn/T18gudMmifji+mbSQGGAk+GrTKTkij06KTeQIKxCK4jyiXo+YCPUzvF8JSgVoNOzgNkpEaU3Z3PCGUeHbTPqLOK1SYVAVcIvGAA3axzC4VLTElVJpL5KbHm7tKBGuVzQjrMOVuHQkT4XkxxFoCL8Aft94vKd8GG5SZjMAAAAVALgm3ZRWX/P/FFrANd+RhEEUBVA1AAABAQCl7F5Fl+kumX/ijijhYv/7WNNR20yzZFioEBJs6LkOidaBffEx48sB0+ACl35LVQegl5ivIdO5se6NdsEPr7BOVKRmgvNcH5qb+rVV95rffpC70MYesB8pmIETaHK20O++MWqXjA2wCmg0Sx/zfr0P55rY4MS81iTiolP66c8q9x9qDAYBgw7G4xCWdllHoKdQ9T60u9NjYR+BxXKz5SRAh9ZSz8iicML91rXQpEPb3hwatyAyl+OUjJsCIC8P4fWvIKst2ljrhhkh+kaF1c62sLIzyLsTrIxXO53MH8fCRCOxz3XqXQyS6MFtrEwF6GotVV4vK3GZc5Z+oY+uWat+AAABAQC6qlRsu6CBYRDXOIqj7lQ6qWtzhH5WHNzVW6/CKxhIEZ+EnwOviGoyBhmyHCf0iMJIVualoq+RR87JvUzenogG20NG8LthymwlQiy9pLmBTzwh/8hqwOlGbCFQX3XA+CktP8KUWgyp2/HrCiCh3r2AyaKvVpVr1rZxLctTZhLp5rsFTQbPMCnm+zcsG8CDaVwXTNF/Z91wZ3QiUroYnXbXvhli7e+nLB1PBy8mQEsST8poYb8KFpCuKLjQkAOh3MgUaeC0aogO51mA6yqVnbYM6NxPcFVHTsmyHOtMr0pPsQM34gopOGwaT1imio0I1FK3IQ/olUhrjBsYbNAFytpd
root@linux-ghot

linux-ghot:~/.ssh # cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0U7Vtqm5P8bApRWNoqNRazVG6ihJ1t31m2cCfpxu44Yo16j/l+W5MLm+1W3KxSJXG/e76OdNwN0hfMqJeL7AiKovbTVLfMmNDn73YvxALuzZz1YTuRLkVaLtja4cUnBCPU9QG0GYxh2A426ov65n6YkE4vYLcteMlgnfXcCJGO9uxjmdSP9renhUK6c0N/m4X+oOWcjME0JTk4KxF4bCxYxspmWExXN5rIf3UhI352VQO8p9eSioGCsEWBokxjN86t5KOHDM+PVCP9Q2/f4flKTtzfhmhcgYQ4x2/g1YDjXdGXYDYTU1eFa1G5dj9klohIqPrb9TA4VBVP5REwkPKQ==
root@linux-ghot


If I change the system and find out ssh is happening to
sourceware.org, I will end up mailing you new public key,

sorry for inconvenience.

Regards,
Oza.


On 3/13/12, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> I am still unable to checkout the code. getting timeout errors.
> oza> any inputs ?
>
> I don't, sorry.  You could perhaps email me your public key and I could
> check it against the key stored on sourceware.  Otherwise, sourceware
> ssh works fine for many people, so I presume the difficulty is on your
> end.
>
> Tom
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-08-10 17:09 chandra krishnappa
@ 2011-08-11  1:34 ` Yao Qi
  0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-08-11  1:34 UTC (permalink / raw)
  To: chandra krishnappa; +Cc: gdb-patches

On 08/11/2011 01:08 AM, chandra krishnappa wrote:
> Kindly suggest some steps or operations which confirms the basic host and target communication is working fine..
> 
> I am stuck up with connection itself....
> 
> 1. Copied "gdbserver" ( ARM compiled ) on to target board.
> ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
> 
> 2. start gdb from host system
> personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
> GNU gdb (GDB) 7.3
> Copyright (C) 2011 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>.
> (gdb) target remote 192.168.1.6:9876
> Remote debugging using 192.168.1.6:9876
> warning: Can not parse XML target description; XML support was disabled at compile time
> 0x400007b0 in ?? ()
> (gdb) continue
> Continuing.
> Cannot access memory at address 0x0
> [Inferior 1 (Remote target) exited normally]
> 
> 

Your step 2 looks incorrect to me.  You should fire gdb with debuggee
program, like ./gdb test_arm.

> 
> On the remote target the complete program is just executing and showing the results...
> 
> Not able to debug the program step by step not even any break..
> 
> Am searching for some step by step host : target gdb setup through cris-cross cables...
> 
> I dont have serial port on my laptop, generally there are more articles on serial connections... seems that used by most ..
> 

Your connection between host gdb and gdbserver works.  serial port is
usually used to connect with bare mental board which doesn't have
network connection.  You don't need to have a serial port in this case.

> 
> Parallel I am looking at running dejagnu testsuite for x86 locally.. thinking of extend the x86 execution method of connection of host and target for ARM Board..
> 

dejagnu naturally supports remote testing, so you don't have to invent
the wheel again.  What you need here is a board file.  Here is an example,

# gdbserver running over ssh.
load_generic_config "gdbserver"
process_multilib_options ""

# The default compiler for this target on host machine.
set_board_info compiler
"/home/yao/toolchain/fsf-gcc-trunk/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc"

set_board_info rsh_prog /usr/bin/ssh
set_board_info rcp_prog /usr/bin/scp
set_board_info protocol standard
set_board_info hostname your.target.host.name or ip address
set_board_info username yao
# gdbserver's location on your target board.
set_board_info gdb_server_prog /home/yao/gdbserver
# We will be using the standard GDB remote protocol
set_board_info gdb_protocol "remote"
# Use techniques appropriate to a stub
set_board_info use_gdb_stub 1
# This gdbserver can only run a process once per session.
set_board_info gdb,do_reload_on_run 1
# There's no support for argument-passing (yet).
set_board_info noargs 1
# Can't do input (or output) in the current gdbserver.
set_board_info gdb,noinferiorio 1
# Can't do hardware watchpoints, in general
set_board_info gdb,no_hardware_watchpoints 1

If your board has ssh, you can use this board file with minor changes
(such as location of gdbserver and gcc).  If your board doesn't have
ssh, IIRC, dejagnu also support telnet and rsh to access remote boards.
 You can find more from google.

You can save the board file as arm.exp, or whatever you prefer, and set
dejagnu a little bit so that this board file can be used when you run
`make check'.  Please reference this wiki page on how to use a new board
file in gdb tests.

  Testing gdbserver in a native configuration

http://sourceware.org/gdb/wiki/TestingGDB#Testing_gdbserver_in_a_native_configuration

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-08-10 17:09 chandra krishnappa
  2011-08-11  1:34 ` Yao Qi
  0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-08-10 17:09 UTC (permalink / raw)
  To: gdb-patches, Yao Qi

[-- Attachment #1: Type: text/plain, Size: 2450 bytes --]

Kindly suggest some steps or operations which confirms the basic host and target communication is working fine..

I am stuck up with connection itself....

1. Copied "gdbserver" ( ARM compiled ) on to target board.
./gdbserver 192.168.1.2:9876 ../from_host/test_arm

2. start gdb from host system
personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()
(gdb) continue
Continuing.
Cannot access memory at address 0x0
[Inferior 1 (Remote target) exited normally]



On the remote target the complete program is just executing and showing the results...

Not able to debug the program step by step not even any break..

Am searching for some step by step host : target gdb setup through cris-cross cables...

I dont have serial port on my laptop, generally there are more articles on serial connections... seems that used by most ..


Parallel I am looking at running dejagnu testsuite for x86 locally.. thinking of extend the x86 execution method of connection of host and target for ARM Board..

http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_130.html
the things in the above link, I have followed... later stuffs are not clear to me.. Logs attached for the reference...
Thanks & Regards,
-Chandra K


--- On Thu, 7/14/11, Yao Qi <yao@codesourcery.com> wrote:

> From: Yao Qi <yao@codesourcery.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: gdb-patches@sourceware.org
> Date: Thursday, July 14, 2011, 11:57 AM
> On 07/14/2011 09:39 AM, chandra
> krishnappa wrote:
> > 2. gdb test development active members, with whom I
> may seek help??
> 
> You may have a look at this page about writing test cases
> for gdb
> http://sourceware.org/gdb/wiki/GDBTestcaseCookbook
> 
> -- 
> Yao (齐尧)
>

[-- Attachment #2: Debugging_Process --]
[-- Type: application/octet-stream, Size: 302 bytes --]

test.c  
compile c program and copy on to target board.
( linux$ arm-none-linux-gnueabi-gcc-4.5.1 -g test.c -o test_arm )

--------

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int i=0;
	int j;

	for (j=0;j<=10;j++) {
		i=(int)random();
		printf("i=%d when j=%d\n",i,j);
	}
	
return 0;
}

[-- Attachment #3: Host_messages --]
[-- Type: application/octet-stream, Size: 3319 bytes --]

Host PC ( 192.168.1.2 )

personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.

(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()

(gdb) break main
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) n

(gdb) bt
#0  0x400007b0 in ?? ()
Cannot access memory at address 0x0
#1  0x00000000 in ?? ()

(gdb) target record
(gdb) break main
No symbol table is loaded.  Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) continue
Continuing.
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) y

regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n

personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()
(gdb) continue
Continuing.
Cannot access memory at address 0x0
[Inferior 1 (Remote target) exited normally]

(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
0x400007b0 in ?? ()

(gdb) target record

(gdb) continue
Continuing.
Cannot access memory at address 0x0
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n

regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
0x400007b0 in ?? ()



[-- Attachment #4: Target_messages --]
[-- Type: application/octet-stream, Size: 2084 bytes --]

Target Board ( ARM ) 192.168.1.6

-----


[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm 
Process ../from_host/test_arm created; pid = 644
Listening on port 9876
Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10

Child exited with status 0
GDBserver exiting

[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm 
Process ../from_host/test_arm created; pid = 648
Listening on port 9876
Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10

Child exited with status 0
GDBserver exiting

[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm 
Process ../from_host/test_arm created; pid = 652
Listening on port 9876
Remote debugging from host 192.168.1.2
Killing all inferiors

[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm 
Process ../from_host/test_arm created; pid = 656
Listening on port 9876
Remote debugging from host 192.168.1.2
readchar: Got EOF
Remote side has terminated connection.  GDBserver will reopen the connection.
Listening on port 9876


Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10

Child exited with status 0
GDBserver exiting

[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm 
Process ../from_host/test_arm created; pid = 660
Listening on port 9876
Remote debugging from host 192.168.1.2
Killing all inferiors
[root@EmbedSky gdbserver]# 


^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-06-06 17:42 ` chandra krishnappa
@ 2011-07-05  8:47   ` oza Pawandeep
  0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-07-05  8:47 UTC (permalink / raw)
  To: gdb-patches; +Cc: paawan oza, chandra krishnappa

Hi all,

can anybody from ARM background review the code with functional perspective ?
Chandra K, is assisting for gdb automated testsuite for arm
reversible, but review is equally important specially if ARM folk
could have a look at the patch at functional perspective.

Thanks & Regards,
Oza.


>
> --- On Fri, 3/6/11, "paawan oza" <paawan1982@yahoo.com> wrote:
>> From: paawan oza <paawan1982@yahoo.com>
>> Date: Fri, Jun 3, 2011 at 1:21 PM
>> Subject: Re: [PATCH] arm reversible :
>> <phase_2_complete>
>> To: Tom Tromey <tromey@redhat.com>
>> Cc: gdb-patches@sourceware.org,
>> Petr Hluzín <petr.hluzin@gmail.com>
>>
>>
>> Hi Tom,
>>
>> Fixed almost all comments.
>> any more comments are welcome make this patch ok, if ARM
>> person can have a look
>> at it it would be great.
>>
>> PATCH STARTS
>> ------------------------------------diff -urN
>> arm_orig/arm-linux-tdep.c
>> arm_new/arm-linux-tdep.c
>> --- arm_orig/arm-linux-tdep.c    2011-03-03
>> 09:21:13.000000000 +0530
>> +++ arm_new/arm-linux-tdep.c    2011-05-07
>> 14:20:31.000000000 +0530
>> @@ -998,6 +998,9 @@
>>   set_gdbarch_fetch_tls_load_module_address (gdbarch,
>>
>>      svr4_fetch_objfile_link_map);
>>
>> +  /* Enable process record.  */
>> +  set_gdbarch_process_record (gdbarch,
>> arm_process_record);
>> +
>>   tramp_frame_prepend_unwinder (gdbarch,
>>
>> &arm_linux_sigreturn_tramp_frame);
>>   tramp_frame_prepend_unwinder (gdbarch,
>> @@ -1025,6 +1028,8 @@
>>
>>
>>   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>> +
>> +  tdep->arm_swi_record = NULL;
>>  }
>>
>>  /* Provide a prototype to silence -Wmissing-prototypes.
>>  */
>> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
>> --- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.c    2011-06-03 13:16:35.000000000
>> +0530
>> @@ -54,6 +54,8 @@
>>  #include "gdb_assert.h"
>>  #include "vec.h"
>>
>> +#include "record.h"
>> +
>>  #include "features/arm-with-m.c"
>>
>>  static int arm_debug;
>> @@ -7929,3 +7931,1763 @@
>>                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 = 0; reg_len = LENGTH; \
>> +    if (reg_len) \
>> +      { \
>> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) *
>> (reg_len)); \
>> +        while (reg_len) \
>> +          { \
>> +            REGS[reg_len - 1] = RECORD_BUF[reg_len -
>> 1];  \
>> +            reg_len--;  \
>> +          } \
>> +      } \
>> +  } \
>> +while (0)
>> +
>> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>> +do  \
>> +  { \
>> +    unsigned int mem_len = 0; mem_len = LENGTH; \
>> +    if (mem_len) \
>> +      { \
>> +        MEMS = (struct arm_mem_r *)xmalloc \
>> +               (sizeof(struct arm_mem_r) *
>> (mem_len)); \
>> +        while (mem_len) \
>> +          { \
>> +            MEMS[mem_len - 1].addr =
>> RECORD_BUF[(mem_len * 2) - 1]; \
>> +            MEMS[mem_len - 1].len =
>> RECORD_BUF[(mem_len * 2) - 2]; \
>> +            mem_len--;   \
>> +          } \
>> +      } \
>> +  } \
>> +while (0)
>> +
>> +
>> +/* 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 recors
>> */
>> +  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 mendatory 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;
>> +}
>> +
>> +/* Handling ARM extension space insns.  */
>> +
>> +static int
>> +handle_extension_space (insn_decode_record *arm_insn_r)
>> +{
>> +  uint32_t ret = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0;
>> +
>> +  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.  */
>> +    }
>> +
>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> +  if ((!opcode1) && (9 == opcode2))
>> +    {
>> +      ret = -1;
>> +      /* Handle arithmetic insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> +  if ((!opcode1) && (2 == opcode2) &&
>> (!bit (arm_insn_r->arm_insn, 20)))
>> +    {
>> +      ret = -1;
>> +      /* Handle control insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> +  if ((!opcode1) && (bit
>> (arm_insn_r->arm_insn, 7)) \
>> +                 &&
>> (bit(arm_insn_r->arm_insn, 4)))
>> +    {
>> +      ret = -1;
>> +      /* Handle load/store insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>> +  if ((24 == opcode1) && (bit
>> (arm_insn_r->arm_insn, 21)))
>> +    {
>> +      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 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
>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +
>> +  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;
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +
>> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.
>>  */
>> +      /* Accorindly to high vector configuration PC is
>> set accordingly */
>> +      /* What if 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)
>> +           let us begin according to addressing modes
>> for store insns
>> +           STRH insn, addresing modes are taken
>> following.  */
>> +    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_buf[0].unsigned_regval);
>> +        if (15 == reg_src1)
>> +          {
>> +            /* If R15 was used as Rn, hence current
>> PC+8.  */
>> +            u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +          }
>> +        offset_8 = (immed_high << 4) |
>> immed_low;
>> +        /* Calculate target store address.  */
>> +        if (14 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +      }
>> +    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_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                    ,
>> &u_buf[1].unsigned_regval);
>>
>> +        if (15 == reg_src2)
>> +          {
>> +            /* If R15 was used as Rn, hence current
>> PC+8.  */
>> +            u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +          }
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if (12 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +      }
>> +    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_buf[0].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if ((15 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = 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_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                    ,
>> &u_buf[1].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if ((13 == arm_insn_r->opcode) || (4 ==
>> arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> +        arm_insn_r->reg_rec_count = 1;
>> +      }
>> +    /* DSP insns (e.g. LDRD)  TBD.  */
>> +  }
>> +  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
>> +    {
>> +      gdb_assert_not_reached ("no decoding pattern
>> found");
>> +    }
>> +
>> +  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_handle_data_proc_imm_insn (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
>> +    {
>> +      gdb_assert_not_reached ("no decoding pattern
>> found");
>> +    }
>> +
>> +  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_handle_ld_st_imm_offset_insn (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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +  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 (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 ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> +      || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> +      || (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))
>> +        {
>> +          /* 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_buf.unsigned_regval);
>> +          /* U == 1 */
>> +          if (bit (arm_insn_r->arm_insn, 23))
>> +            {
>> +              tgt_mem_addr = u_buf.unsigned_regval
>> + offset_12;
>> +            }
>> +          else
>> +            {
>> +             tgt_mem_addr = u_buf.unsigned_regval -
>> offset_12;
>> +            }
>> +
>> +          switch(arm_insn_r->opcode)
>> +            {
>> +              case 8:
>> +              case 12:
>> +              case 9:
>> +              case 13:
>> +              case 1:
>> +              case 5:
>> +                /* STR insn, STRT insn.  */
>> +                record_buf_mem[0] = 4;
>> +              break;
>> +
>> +              case 10:
>> +              case 14:
>> +              case 11:
>> +              case 15:
>> +              case 3:
>> +              case 7:
>> +                /* STRB insn, STRBT insn.  */
>> +                record_buf_mem[0] = 1;
>> +              break;
>> +
>> +              default:
>> +                gdb_assert_not_reached ("Invalid
>> addressing mode for insn");
>> +              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0,
>> tgt_mem_addr = 0;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      LONGEST signed_word;
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +  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,
>> +        let us begin 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 ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> +    || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> +    || (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))
>> +      {
>> +        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_buf[0].unsigned_regval);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  ,
>> &u_buf[1].unsigned_regval);
>>
>> +            if (15 == reg_src2)
>> +              {
>> +                /* If R15 was used as Rn, hence
>> current PC+8.  */
>> +                /* Pre-indexed mode doesnt reach
>> here ; illegal insn.  */
>> +                u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +              }
>> +            /* Calculate target store address, Rn
>> +/- Rm, register offset.  */
>> +            /* U == 1.  */
>> +            if (bit (arm_insn_r->arm_insn, 23))
>> +              {
>> +                tgt_mem_addr =
>> u_buf[0].unsigned_regval +
>> u_buf[1].unsigned_regval;
>> +              }
>> +            else
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval -
>> u_buf[0].unsigned_regval;
>> +              }
>> +
>> +            switch(arm_insn_r->opcode)
>> +              {
>> +                case 8:
>> +                case 12:
>> +                case 9:
>> +                case 13:
>> +                case 1:
>> +                case 5:
>> +                  /* STR insn, STRT insn.  */
>> +                  record_buf_mem[0] = 4;
>> +                break;
>> +
>> +                case 10:
>> +                case 14:
>> +                case 11:
>> +                case 15:
>> +                case 3:
>> +                case 7:
>> +                  /* STRB insn, STRBT insn.  */
>> +                  record_buf_mem[0] = 1;
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                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_buf[0].unsigned_regval);
>> +            regcache_raw_read_signed (reg_cache,
>> reg_src1
>> +
>>  , &u_buf[0].signed_word);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  , &u_buf[1].unsigned_regval);
>> +            /* Offset_12 used as shift.  */
>> +            switch(offset_12)
>> +              {
>> +                case 0:
>> +                  /* Offset_12 used as index.
>>  */
>> +                  offset_12 =
>> u_buf[0].unsigned_regval << shift_imm;
>> +                break;
>> +
>> +                case 1:
>> +                  offset_12 =
>> (!shift_imm)?0:u_buf[0].unsigned_regval >>
>> shift_imm;
>>
>> +                break;
>> +
>> +                case 2:
>> +                  if (!shift_imm)
>> +                    {
>> +                      if (bit
>> (u_buf[0].unsigned_regval, 31))
>> +                        {
>> +                          offset_12 =
>> 0xFFFFFFFF;
>> +                        }
>> +                      else
>> +                        {
>> +                          offset_12 = 0;
>> +                        }
>> +                    }
>> +                  else
>> +                    {
>> +                      /* This is arithmetic
>> shift.  */
>> +                      offset_12 =
>> u_buf[0].signed_word >> shift_imm;
>> +                    }
>> +                  break;
>> +
>> +                case 3:
>> +                  if (!shift_imm)
>> +                    {
>> +
>>  regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
>> +
>>            , &u_buf[1].unsigned_regval);
>> +                      /* Get C flag value and
>> shift it by 31.  */
>> +                      offset_12 = (((bit
>> (u_buf[1].unsigned_regval, 29)) << 31)
>> \
>> +                                    |
>> (u_buf[0].unsigned_regval) >> 1);
>> +                    }
>> +                  else
>> +                    {
>> +                      offset_12 =
>> (u_buf[0].unsigned_regval >> shift_imm) \
>> +                         |
>> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
>> shift_imm));
>> +                    }
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                break;
>> +              }
>> +
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  , &u_buf[1].unsigned_regval);
>> +            /* U == 1 */
>> +            if (bit (arm_insn_r->arm_insn, 23))
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval + offset_12;
>> +              }
>> +            else
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval - offset_12;
>> +              }
>> +
>> +            switch (arm_insn_r->opcode)
>> +              {
>> +                case 8:
>> +                case 12:
>> +                case 9:
>> +                case 13:
>> +                case 1:
>> +                case 5:
>> +                  /* STR insn, STRT insn.  */
>> +                  record_buf_mem[0] = 4;
>> +                break;
>> +
>> +                case 10:
>> +                case 14:
>> +                case 11:
>> +                case 15:
>> +                case 3:
>> +                case 7:
>> +                  /* STRB insn, STRBT insn.  */
>> +                  record_buf_mem[0] = 1;
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                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_handle_ld_st_multiple_insn (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 shift_imm = 0;
>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
>> no_of_regs = 0;
>> +  uint32_t start_address = 0, index = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +
>> +  /* 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 optmization.  */
>> +
>> +  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 optmization.  */
>> +        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_buf[0].unsigned_regval);
>> +    while (register_bits)
>> +      {
>> +        if (register_bits & 0x00000001)
>> +           register_count++;
>> +        register_bits = register_bits >> 1;
>> +      }
>> +
>> +    switch(addr_mode)
>> +      {
>> +        /* Decrement after.  */
>> +        case 0:
>> +          start_address = (u_buf[0].unsigned_regval)
>> - (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_buf[0].unsigned_regval;
>> +          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_buf[0].unsigned_regval)
>> - (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_buf[0].unsigned_regval +
>> 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 ("Invalid addressing
>> mode for insn");
>> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
>> +{
>> +
>> +  uint32_t record_buf[8];
>> +
>> +  /* Handle B, BL, BLX(1) insns.  */
>> +  /* Wihtout optmization we save link register,
>> +        CSPR for the insn which changes T bit.  */
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = ARM_LR_REGNUM;
>> +  arm_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>> +{
>> +  printf_unfiltered (_("Process record does not support
>> instruction "
>> +                     "0x%0x at address %s.\n"),
>> +                     arm_insn_r->arm_insn,
>> +                     paddress
>> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>> +
>> +   return -1;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_data_proc_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +   struct gdbarch_tdep *tdep = gdbarch_tdep
>> (arm_insn_r->gdbarch);
>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +   uint32_t shift_imm = 0;
>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
>> +   uint32_t start_address = 0;
>> +
>> +   /* 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)
>> +          {
>> +            tdep->arm_swi_record(reg_cache);
>> +          }
>> +        else
>> +          {
>> +            printf_unfiltered (_("no syscall record
>> support\n"));
>> +            return -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 -1;
>> +}
>> +
>> +/* Handling opcode 000 insns.  */
>> +
>> +static int
>> +thumb_handle_shift_add_sub_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_src1 = 0;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +      gdb_byte buf[4];
>> +    } u_buf[2];
>> +
>> +  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_buf[0].unsigned_regval);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                      ,
>> &u_buf[1].unsigned_regval);
>> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>
>> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_5 = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
>> +      record_buf_mem[0] = 2;
>> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
>> = 0, immed_5 = 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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_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.
>>  */
>> +      /* Accorindly to high vector configuration PC is
>> set accordingly.  */
>> +      /* FIX ME ?  what if 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;
>> +      thumb_insn_r->reg_rec_count = 2;
>> +      /* Save SPSR also; how?.  */
>> +      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_handle_swi_insn (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 reg_val1 = 0;
>> +  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];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  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_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_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)
>> +          {
>> +            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 0;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +thumb_handle_branch_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> +  /* BL , 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;
>> +}
>> +
>> +
>> +/* Decode arm/thumb insn depending on condition cods and
>> opcodes; and dispatch
>> it.  */
>> +
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t
>> insn_size)
>> +{
>> +
>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes
>> type of arm
>> instruction.  */
>> +  static int (*const arm_handle_insn[8])
>> +
>>  (insn_decode_record*) =
>> +  {
>> +      arm_handle_data_proc_misc_ld_str_insn,    /*
>> 000.  */
>> +      arm_handle_data_proc_imm_insn,
>>  /* 001.  */
>> +      arm_handle_ld_st_imm_offset_insn,         /*
>> 010.  */
>> +      arm_handle_ld_st_reg_offset_insn,         /*
>> 011.  */
>> +      arm_handle_ld_st_multiple_insn,           /*
>> 100.  */
>> +      arm_handle_brn_insn,
>>    /* 101.  */
>> +      arm_handle_coproc_insn,
>>   /* 110.  */
>> +      arm_handle_coproc_data_proc_insn          /*
>> 111.  */
>> +  };
>> +
>> +  /* (Starting from numerical 0); bits 13,14,15 decodes
>> type of thumb
>> instruction.  */
>> +  static int (*const thumb_handle_insn[8])
>> +
>>    (insn_decode_record*) =
>> +  { \
>> +      thumb_handle_shift_add_sub_insn,         /*
>> 000.  */
>> +      thumb_handle_add_sub_cmp_mov_insn,       /*
>> 001.  */
>> +      thumb_handle_ld_st_reg_offset_insn,      /*
>> 010.  */
>> +      thumb_handle_ld_st_imm_offset_insn,      /*
>> 011.  */
>> +      thumb_handle_ld_st_stack_insn,           /*
>> 100.  */
>> +      thumb_handle_misc_insn,
>>  /* 101.  */
>> +      thumb_handle_swi_insn,
>> /* 110.  */
>> +      thumb_handle_branch_insn
>> /* 111.  */
>> +  };
>> +
>> +  struct
>> +    {
>> +      gdb_byte buf[insn_size];
>> +    } u_buf;
>> +
>> +  uint32_t ret=0, insn_id = 0;
>> +
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +  if (target_read_memory (arm_record->this_addr,
>> &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> +             , ARM_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>>
>> +      arm_record->cond = bits
>> (arm_record->arm_insn, 28, 31);
>> +      insn_id = bits (arm_record->arm_insn, 25,
>> 27);
>> +      ret = (0x0F != arm_record->cond)
>> +            ? arm_handle_insn[insn_id] (arm_record)
>> +            : handle_extension_space (arm_record);
>> +    }
>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* As thumb does not have condition codes,
>> following field is useless.
>> */
>> +      arm_record->cond = -1;
>> +      arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> +           , THUMB_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>> +
>> +      insn_id = bits (arm_record->arm_insn, 13,
>> 15);
>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>> +    }
>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* Yet to be implemented; handle thumb2 part
>> here.  */
>> +      printf_unfiltered (_("Process record does not
>> support 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(0);
>> +    }
>> +
>> +  return ret;
>> +}
>> +
>> +/* 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;
>> +  ULONGEST t_bit = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  insn_decode_record arm_record;
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +
>> +  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));
>> +    }
>> +
>> +  /* 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_buf.unsigned_regval);
>> +
>> +  if (!(u_buf.unsigned_regval & t_bit))
>> +    {
>> +      /* We are decoding arm insn.  */
>> +      ret = decode_insn (&arm_record,
>> ARM_INSN_SIZE_BYTES);
>> +    }
>> +  else
>> +    {
>> +      /* We are decoding thumb insn.  */
>> +      ret = decode_insn (&arm_record,
>> THUMB_INSN_SIZE_BYTES);
>> +    }
>> +
>> +  if (0 == ret)
>> +    {
>> +      /* Record registers.  */
>> +      record_arch_list_add_reg (arm_record.regcache,
>> ARM_PC_REGNUM);
>> +      if (arm_record.arm_regs)
>> +        {
>> +          for (no_of_rec = 0; no_of_rec <
>> arm_record.reg_rec_count;
>> no_of_rec++)
>> +            {
>> +              if (record_arch_list_add_reg
>> (arm_record.regcache \
>> +
>>     , (arm_record.arm_regs[no_of_rec])))
>> +              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_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_arch_list_add_end ())
>> +        ret = -1;
>> +    }
>> +
>> +  if (arm_record.arm_regs)
>> +    xfree (arm_record.arm_regs);
>> +  if (arm_record.arm_mems)
>> +    xfree (arm_record.arm_mems);
>> +
>> +  return ret;
>> +}
>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>> --- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000
>> +0530
>> @@ -200,6 +200,9 @@
>>   /* Return the expected next PC if FRAME is stopped at a
>> syscall
>>      instruction.  */
>>   CORE_ADDR (*syscall_next_pc) (struct frame_info
>> *frame);
>> +
>> +   /* Parse swi insn args, sycall record.  */
>> +  int (*arm_swi_record) (struct regcache *regcache);
>>  };
>>
>>  /* Structures used for displaced stepping.  */
>> @@ -310,6 +313,10 @@
>>                       struct
>> displaced_step_closure *,
>>                       CORE_ADDR, CORE_ADDR,
>> struct regcache *);
>>
>> +extern int arm_process_record (struct gdbarch *gdbarch,
>> +                                struct
>> regcache *regcache, CORE_ADDR addr);
>> +
>> +
>>  /* Functions exported from armbsd-tdep.h.  */
>>
>>  /* Return the appropriate register set for the core
>> section identified
>>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found] <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>
@ 2011-06-06 17:42 ` chandra krishnappa
  2011-07-05  8:47   ` oza Pawandeep
  0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-06-06 17:42 UTC (permalink / raw)
  To: paawan oza, gdb-patches


Hi,

I will be working for testing the patch of ARM reversible debugging feature. Will be sending the test code for review once I develop the same.

This is to inform that I will be working on this task, and anybody has any pointers or comments to provide, its welcome.

I will pick up the patch from here from the mailing list or will work with Paawan Oza to get the latest build of arm reversible.


Thanks & Regards,
-Chandra K


--- On Fri, 3/6/11, "paawan oza" <paawan1982@yahoo.com> wrote:
> From: paawan oza <paawan1982@yahoo.com>
> Date: Fri, Jun 3, 2011 at 1:21 PM
> Subject: Re: [PATCH] arm reversible :
> <phase_2_complete>
> To: Tom Tromey <tromey@redhat.com>
> Cc: gdb-patches@sourceware.org,
> Petr Hluzín <petr.hluzin@gmail.com>
> 
> 
> Hi Tom,
> 
> Fixed almost all comments.
> any more comments are welcome make this patch ok, if ARM
> person can have a look
> at it it would be great.
> 
> PATCH STARTS
> ------------------------------------diff -urN
> arm_orig/arm-linux-tdep.c
> arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c    2011-03-03
> 09:21:13.000000000 +0530
> +++ arm_new/arm-linux-tdep.c    2011-05-07
> 14:20:31.000000000 +0530
> @@ -998,6 +998,9 @@
>   set_gdbarch_fetch_tls_load_module_address (gdbarch,
>                                        
>      svr4_fetch_objfile_link_map);
> 
> +  /* Enable process record.  */
> +  set_gdbarch_process_record (gdbarch,
> arm_process_record);
> +
>   tramp_frame_prepend_unwinder (gdbarch,
>                
> &arm_linux_sigreturn_tramp_frame);
>   tramp_frame_prepend_unwinder (gdbarch,
> @@ -1025,6 +1028,8 @@
> 
> 
>   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> +  tdep->arm_swi_record = NULL;
>  }
> 
>  /* Provide a prototype to silence -Wmissing-prototypes.
>  */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000
> +0530
> +++ arm_new/arm-tdep.c    2011-06-03 13:16:35.000000000
> +0530
> @@ -54,6 +54,8 @@
>  #include "gdb_assert.h"
>  #include "vec.h"
> 
> +#include "record.h"
> +
>  #include "features/arm-with-m.c"
> 
>  static int arm_debug;
> @@ -7929,3 +7931,1763 @@
>                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 = 0; reg_len = LENGTH; \
> +    if (reg_len) \
> +      { \
> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) *
> (reg_len)); \
> +        while (reg_len) \
> +          { \
> +            REGS[reg_len - 1] = RECORD_BUF[reg_len -
> 1];  \
> +            reg_len--;  \
> +          } \
> +      } \
> +  } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do  \
> +  { \
> +    unsigned int mem_len = 0; mem_len = LENGTH; \
> +    if (mem_len) \
> +      { \
> +        MEMS = (struct arm_mem_r *)xmalloc \
> +               (sizeof(struct arm_mem_r) *
> (mem_len)); \
> +        while (mem_len) \
> +          { \
> +            MEMS[mem_len - 1].addr =
> RECORD_BUF[(mem_len * 2) - 1]; \
> +            MEMS[mem_len - 1].len =
> RECORD_BUF[(mem_len * 2) - 2]; \
> +            mem_len--;   \
> +          } \
> +      } \
> +  } \
> +while (0)
> +
> +
> +/* 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 recors
> */
> +  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 mendatory 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;
> +}
> +
> +/* Handling ARM extension space insns.  */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> +  uint32_t ret = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  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.  */
> +    }
> +
> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> +  if ((!opcode1) && (9 == opcode2))
> +    {
> +      ret = -1;
> +      /* Handle arithmetic insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> +  if ((!opcode1) && (2 == opcode2) &&
> (!bit (arm_insn_r->arm_insn, 20)))
> +    {
> +      ret = -1;
> +      /* Handle control insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> +  if ((!opcode1) && (bit
> (arm_insn_r->arm_insn, 7)) \
> +                 &&
> (bit(arm_insn_r->arm_insn, 4)))
> +    {
> +      ret = -1;
> +      /* Handle load/store insn extension space.  */
> +    }
> +
> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> +  if ((24 == opcode1) && (bit
> (arm_insn_r->arm_insn, 21)))
> +    {
> +      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 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
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
> *arm_insn_r)
> +{
> +  struct regcache *reg_cache = arm_insn_r->regcache;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +
> +  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;
> +
> +  memset(&u_buf, 0, sizeof (u_buf));
> +
> +  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 preccedded 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 insns, 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_buf[0].unsigned_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_buf[0].unsigned_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 ((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.
>  */
> +      /* Accorindly to high vector configuration PC is
> set accordingly */
> +      /* What if 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)
> +           let us begin according to addressing modes
> for store insns
> +           STRH insn, addresing modes are taken
> following.  */
> +    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_buf[0].unsigned_regval);
> +        if (15 == reg_src1)
> +          {
> +            /* If R15 was used as Rn, hence current
> PC+8.  */
> +            u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +          }
> +        offset_8 = (immed_high << 4) |
> immed_low;
> +        /* Calculate target store address.  */
> +        if (14 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                    ,
> &u_buf[1].unsigned_regval);
> 
> +        if (15 == reg_src2)
> +          {
> +            /* If R15 was used as Rn, hence current
> PC+8.  */
> +            u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +          }
> +        /* Calculate target store address, Rn +/- Rm,
> register offset.  */
> +        if (12 == arm_insn_r->opcode)
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval
> - u_buf[0].unsigned_regval;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +      }
> +    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_buf[0].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm,
> register offset.  */
> +        if ((15 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> + offset_8;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> - offset_8;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = 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_buf[0].unsigned_regval);
> +        regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                    ,
> &u_buf[1].unsigned_regval);
> +        /* Calculate target store address, Rn +/- Rm,
> register offset.  */
> +        if ((13 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> +          {
> +            tgt_mem_addr = u_buf[0].unsigned_regval
> + u_buf[1].unsigned_regval;
> +          }
> +        else
> +          {
> +            tgt_mem_addr = u_buf[1].unsigned_regval
> - u_buf[0].unsigned_regval;
> +          }
> +        record_buf_mem[0] = 2;
> +        record_buf_mem[1] = tgt_mem_addr;
> +        arm_insn_r->mem_rec_count = 1;
> +        /* Record Rn also as it changes.  */
> +        record_buf[0] = bits (arm_insn_r->arm_insn,
> 16, 19);
> +        arm_insn_r->reg_rec_count = 1;
> +      }
> +    /* DSP insns (e.g. LDRD)  TBD.  */
> +  }
> +  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
> +    {
> +      gdb_assert_not_reached ("no decoding pattern
> found");
> +    }
> +
> +  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_handle_data_proc_imm_insn (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
> +    {
> +      gdb_assert_not_reached ("no decoding pattern
> found");
> +    }
> +
> +  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_handle_ld_st_imm_offset_insn (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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  memset(&u_buf, 0, sizeof (u_buf));
> +  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 (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 ((8 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> +      || (12 == arm_insn_r->opcode) || (14 ==
> arm_insn_r->opcode)
> +      || (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))
> +        {
> +          /* 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_buf.unsigned_regval);
> +          /* U == 1 */
> +          if (bit (arm_insn_r->arm_insn, 23))
> +            {
> +              tgt_mem_addr = u_buf.unsigned_regval
> + offset_12;
> +            }
> +          else
> +            {
> +             tgt_mem_addr = u_buf.unsigned_regval -
> offset_12;
> +            }
> +
> +          switch(arm_insn_r->opcode)
> +            {
> +              case 8:
> +              case 12:
> +              case 9:
> +              case 13:
> +              case 1:
> +              case 5:
> +                /* STR insn, STRT insn.  */
> +                record_buf_mem[0] = 4;
> +              break;
> +
> +              case 10:
> +              case 14:
> +              case 11:
> +              case 15:
> +              case 3:
> +              case 7:
> +                /* STRB insn, STRBT insn.  */
> +                record_buf_mem[0] = 1;
> +              break;
> +
> +              default:
> +                gdb_assert_not_reached ("Invalid
> addressing mode for insn");
> +              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0,
> tgt_mem_addr = 0;
> +  uint32_t record_buf[8], record_buf_mem[8];
> +
> +  struct
> +    {
> +      LONGEST signed_word;
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset(&u_buf, 0, sizeof (u_buf));
> +  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,
> +        let us begin 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 ((8 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> +    || (12 == arm_insn_r->opcode) || (14 ==
> arm_insn_r->opcode)
> +    || (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))
> +      {
> +        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_buf[0].unsigned_regval);
> +            regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      
>  ,
> &u_buf[1].unsigned_regval);
> 
> +            if (15 == reg_src2)
> +              {
> +                /* If R15 was used as Rn, hence
> current PC+8.  */
> +                /* Pre-indexed mode doesnt reach
> here ; illegal insn.  */
> +                u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> +              }
> +            /* Calculate target store address, Rn
> +/- Rm, register offset.  */
> +            /* U == 1.  */
> +            if (bit (arm_insn_r->arm_insn, 23))
> +              {
> +                tgt_mem_addr =
> u_buf[0].unsigned_regval +
> u_buf[1].unsigned_regval;
> +              }
> +            else
> +              {
> +                tgt_mem_addr =
> u_buf[1].unsigned_regval -
> u_buf[0].unsigned_regval;
> +              }
> +
> +            switch(arm_insn_r->opcode)
> +              {
> +                case 8:
> +                case 12:
> +                case 9:
> +                case 13:
> +                case 1:
> +                case 5:
> +                  /* STR insn, STRT insn.  */
> +                  record_buf_mem[0] = 4;
> +                break;
> +
> +                case 10:
> +                case 14:
> +                case 11:
> +                case 15:
> +                case 3:
> +                case 7:
> +                  /* STRB insn, STRBT insn.  */
> +                  record_buf_mem[0] = 1;
> +                break;
> +
> +                default:
> +                  gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> +                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_buf[0].unsigned_regval);
> +            regcache_raw_read_signed (reg_cache,
> reg_src1
> +                                      
>  , &u_buf[0].signed_word);
> +            regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      
>  , &u_buf[1].unsigned_regval);
> +            /* Offset_12 used as shift.  */
> +            switch(offset_12)
> +              {
> +                case 0:
> +                  /* Offset_12 used as index.
>  */
> +                  offset_12 =
> u_buf[0].unsigned_regval << shift_imm;
> +                break;
> +
> +                case 1:
> +                  offset_12 =
> (!shift_imm)?0:u_buf[0].unsigned_regval >>
> shift_imm;
> 
> +                break;
> +
> +                case 2:
> +                  if (!shift_imm)
> +                    {
> +                      if (bit
> (u_buf[0].unsigned_regval, 31))
> +                        {
> +                          offset_12 =
> 0xFFFFFFFF;
> +                        }
> +                      else
> +                        {
> +                          offset_12 = 0;
> +                        }
> +                    }
> +                  else
> +                    {
> +                      /* This is arithmetic
> shift.  */
> +                      offset_12 =
> u_buf[0].signed_word >> shift_imm;
> +                    }
> +                  break;
> +
> +                case 3:
> +                  if (!shift_imm)
> +                    {
> +                    
>  regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> +                                      
>            , &u_buf[1].unsigned_regval);
> +                      /* Get C flag value and
> shift it by 31.  */
> +                      offset_12 = (((bit
> (u_buf[1].unsigned_regval, 29)) << 31)
> \
> +                                    |
> (u_buf[0].unsigned_regval) >> 1);
> +                    }
> +                  else
> +                    {
> +                      offset_12 =
> (u_buf[0].unsigned_regval >> shift_imm) \
> +                         |
> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
> shift_imm));
> +                    }
> +                break;
> +
> +                default:
> +                  gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> +                break;
> +              }
> +
> +            regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      
>  , &u_buf[1].unsigned_regval);
> +            /* U == 1 */
> +            if (bit (arm_insn_r->arm_insn, 23))
> +              {
> +                tgt_mem_addr =
> u_buf[1].unsigned_regval + offset_12;
> +              }
> +            else
> +              {
> +                tgt_mem_addr =
> u_buf[1].unsigned_regval - offset_12;
> +              }
> +
> +            switch (arm_insn_r->opcode)
> +              {
> +                case 8:
> +                case 12:
> +                case 9:
> +                case 13:
> +                case 1:
> +                case 5:
> +                  /* STR insn, STRT insn.  */
> +                  record_buf_mem[0] = 4;
> +                break;
> +
> +                case 10:
> +                case 14:
> +                case 11:
> +                case 15:
> +                case 3:
> +                case 7:
> +                  /* STRB insn, STRBT insn.  */
> +                  record_buf_mem[0] = 1;
> +                break;
> +
> +                default:
> +                  gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> +                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_handle_ld_st_multiple_insn (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 shift_imm = 0;
> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
> no_of_regs = 0;
> +  uint32_t start_address = 0, index = 0;
> +  uint32_t record_buf[24], record_buf_mem[48];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf[2];
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  /* 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 optmization.  */
> +
> +  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 optmization.  */
> +        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_buf[0].unsigned_regval);
> +    while (register_bits)
> +      {
> +        if (register_bits & 0x00000001)
> +           register_count++;
> +        register_bits = register_bits >> 1;
> +      }
> +
> +    switch(addr_mode)
> +      {
> +        /* Decrement after.  */
> +        case 0:
> +          start_address = (u_buf[0].unsigned_regval)
> - (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_buf[0].unsigned_regval;
> +          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_buf[0].unsigned_regval)
> - (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_buf[0].unsigned_regval +
> 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 ("Invalid addressing
> mode for insn");
> +        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_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> +  uint32_t record_buf[8];
> +
> +  /* Handle B, BL, BLX(1) insns.  */
> +  /* Wihtout optmization we save link register,
> +        CSPR for the insn which changes T bit.  */
> +  record_buf[0] = ARM_PS_REGNUM;
> +  record_buf[1] = ARM_LR_REGNUM;
> +  arm_insn_r->reg_rec_count = 2;
> +
> +  REG_ALLOC (arm_insn_r->arm_regs,
> arm_insn_r->reg_rec_count, record_buf);
> +
> +  return 0;
> +}
> +
> +/* Handling opcode 110 insns.  */
> +
> +static int
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> +  printf_unfiltered (_("Process record does not support
> instruction "
> +                     "0x%0x at address %s.\n"),
> +                     arm_insn_r->arm_insn,
> +                     paddress
> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
> +
> +   return -1;
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int
> +arm_handle_coproc_data_proc_insn (insn_decode_record
> *arm_insn_r)
> +{
> +   struct gdbarch_tdep *tdep = gdbarch_tdep
> (arm_insn_r->gdbarch);
> +   struct regcache *reg_cache = arm_insn_r->regcache;
> +
> +   uint32_t shift_imm = 0;
> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
> +   uint32_t start_address = 0;
> +
> +   /* 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)
> +          {
> +            tdep->arm_swi_record(reg_cache);
> +          }
> +        else
> +          {
> +            printf_unfiltered (_("no syscall record
> support\n"));
> +            return -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 -1;
> +}
> +
> +/* Handling opcode 000 insns.  */
> +
> +static int
> +thumb_handle_shift_add_sub_insn (insn_decode_record
> *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_src1 = 0;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
> +
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +      gdb_byte buf[4];
> +    } u_buf[2];
> +
> +  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_buf[0].unsigned_regval);
> +          regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +                                      ,
> &u_buf[1].unsigned_regval);
> +          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
> 
> +          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      record_buf_mem[0] = 4;
> +      record_buf_mem[1] = u_buf.unsigned_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_buf.unsigned_regval);
> +      record_buf_mem[0] = 2;
> +      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> +  struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
> = 0, immed_5 = 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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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.
>  */
> +      /* Accorindly to high vector configuration PC is
> set accordingly.  */
> +      /* FIX ME ?  what if 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;
> +      thumb_insn_r->reg_rec_count = 2;
> +      /* Save SPSR also; how?.  */
> +      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_handle_swi_insn (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 reg_val1 = 0;
> +  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];
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  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_buf.unsigned_regval);
> +      while (register_bits)
> +        {
> +          if (register_bits & 0x00000001)
> +             register_count++;
> +          register_bits = register_bits >> 1;
> +        }
> +      start_address = u_buf.unsigned_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)
> +          {
> +            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 0;
> +}
> +
> +/* Handling opcode 111 insns.  */
> +
> +static int
> +thumb_handle_branch_insn (insn_decode_record
> *thumb_insn_r)
> +{
> +  uint32_t record_buf[8];
> +  uint32_t reg_val1 = 0;
> +  uint32_t reg_src1 = 0;
> +  uint32_t opcode = 0, immed_5 = 0;
> +
> +
> +  /* BL , 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;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and
> opcodes; and dispatch
> it.  */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t
> insn_size)
> +{
> +
> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes
> type of arm
> instruction.  */
> +  static int (*const arm_handle_insn[8])
> +                                    
>  (insn_decode_record*) =
> +  {
> +      arm_handle_data_proc_misc_ld_str_insn,    /*
> 000.  */
> +      arm_handle_data_proc_imm_insn,          
>  /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /*
> 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /*
> 011.  */
> +      arm_handle_ld_st_multiple_insn,           /*
> 100.  */
> +      arm_handle_brn_insn,                  
>    /* 101.  */
> +      arm_handle_coproc_insn,                
>   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /*
> 111.  */
> +  };
> +
> +  /* (Starting from numerical 0); bits 13,14,15 decodes
> type of thumb
> instruction.  */
> +  static int (*const thumb_handle_insn[8])
> +                                      
>    (insn_decode_record*) =
> +  { \
> +      thumb_handle_shift_add_sub_insn,         /*
> 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /*
> 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /*
> 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /*
> 011.  */
> +      thumb_handle_ld_st_stack_insn,           /*
> 100.  */
> +      thumb_handle_misc_insn,                
>  /* 101.  */
> +      thumb_handle_swi_insn,                  
> /* 110.  */
> +      thumb_handle_branch_insn                
> /* 111.  */
> +  };
> +
> +  struct
> +    {
> +      gdb_byte buf[insn_size];
> +    } u_buf;
> +
> +  uint32_t ret=0, insn_id = 0;
> +
> +  memset (&u_buf, 0, sizeof(u_buf));
> +  if (target_read_memory (arm_record->this_addr,
> &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
> +    {
> +      arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> +             , ARM_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> 
> +      arm_record->cond = bits
> (arm_record->arm_insn, 28, 31);
> +      insn_id = bits (arm_record->arm_insn, 25,
> 27);
> +      ret = (0x0F != arm_record->cond)
> +            ? arm_handle_insn[insn_id] (arm_record)
> +            : handle_extension_space (arm_record);
> +    }
> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* As thumb does not have condition codes,
> following field is useless.
> */
> +      arm_record->cond = -1;
> +      arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> +           , THUMB_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> +
> +      insn_id = bits (arm_record->arm_insn, 13,
> 15);
> +      ret = thumb_handle_insn[insn_id] (arm_record);
> +    }
> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> +    {
> +      /* Yet to be implemented; handle thumb2 part
> here.  */
> +      printf_unfiltered (_("Process record does not
> support 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(0);
> +    }
> +
> +  return ret;
> +}
> +
> +/* 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;
> +  ULONGEST t_bit = 0;
> +
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* 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_buf.unsigned_regval);
> +
> +  if (!(u_buf.unsigned_regval & t_bit))
> +    {
> +      /* We are decoding arm insn.  */
> +      ret = decode_insn (&arm_record,
> ARM_INSN_SIZE_BYTES);
> +    }
> +  else
> +    {
> +      /* We are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record,
> THUMB_INSN_SIZE_BYTES);
> +    }
> +
> +  if (0 == ret)
> +    {
> +      /* Record registers.  */
> +      record_arch_list_add_reg (arm_record.regcache,
> ARM_PC_REGNUM);
> +      if (arm_record.arm_regs)
> +        {
> +          for (no_of_rec = 0; no_of_rec <
> arm_record.reg_rec_count;
> no_of_rec++)
> +            {
> +              if (record_arch_list_add_reg
> (arm_record.regcache \
> +                                      
>     , (arm_record.arm_regs[no_of_rec])))
> +              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_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_arch_list_add_end ())
> +        ret = -1;
> +    }
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +
> +  return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000
> +0530
> +++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000
> +0530
> @@ -200,6 +200,9 @@
>   /* Return the expected next PC if FRAME is stopped at a
> syscall
>      instruction.  */
>   CORE_ADDR (*syscall_next_pc) (struct frame_info
> *frame);
> +
> +   /* Parse swi insn args, sycall record.  */
> +  int (*arm_swi_record) (struct regcache *regcache);
>  };
> 
>  /* Structures used for displaced stepping.  */
> @@ -310,6 +313,10 @@
>                       struct
> displaced_step_closure *,
>                       CORE_ADDR, CORE_ADDR,
> struct regcache *);
> 
> +extern int arm_process_record (struct gdbarch *gdbarch,
> +                                struct
> regcache *regcache, CORE_ADDR addr);
> +
> +
>  /* Functions exported from armbsd-tdep.h.  */
> 
>  /* Return the appropriate register set for the core
> section identified
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-05-24  7:19 paawan oza
  0 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-24  7:19 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb-patches

Hi,

please find the updated patch below. except one, all from Petr are implemented 
in this.
execuse me for typo if any,do not hesitate to point it out.

PATCH STARTS
---------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-05-24 12:43:20.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1736 @@
                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 GET_REG_VAL(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            REGS[LENGTH - 1] = RECORD_BUF[LENGTH - 1];  \
+            LENGTH--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            MEMS[LENGTH - 1].addr = RECORD_BUF[(LENGTH * 2) - 1]; \
+            MEMS[LENGTH - 1].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+            LENGTH--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* 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 recors */
+  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 mendatory 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;
+}
+
+/* handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      ret = -1;
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      ret = -1;
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      ret = -1;
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      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 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 
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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 preccedded 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 insns, 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); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* what if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, 
&u_buf[0].unsigned_regval);            

+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = 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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_data_proc_imm_insn (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.  */
+           /* Oza: FIX ME ? how to read SPSR value?  */
+        }
+    }   
+  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
+    {
+      gdb_assert_not_reached ("no decoding pattern found");
+    }
+
+  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_handle_ld_st_imm_offset_insn (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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].unsigned_regval + 
u_buf[1].unsigned_regval;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - 
u_buf[0].unsigned_regval;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL_SIGNED (reg_cache, reg_src1, &u_buf[0].signed_word);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].unsigned_regval << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> 
shift_imm; 

+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].unsigned_regval, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, 
&u_buf[1].unsigned_regval);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) 
\
+                                    | (u_buf[0].unsigned_regval) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                         | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - 
shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_handle_ld_st_multiple_insn (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 shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        record_buf[register_count] = reg_src1;
+        record_buf[register_count + 1] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; 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++;
+              }
+          }
+        arm_insn_r->reg_rec_count = register_count + 2;
+    }
+  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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 
4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].unsigned_regval;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].unsigned_regval + 4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        default:
+          gdb_assert_not_reached ("Invalid addressing mode for insn");
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction "
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;   
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 

+          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_handle_ld_st_imm_offset_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (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_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+      thumb_insn_r->reg_rec_count = register_count + 2;
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_regval -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + 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--;
+        }
+      thumb_insn_r->mem_rec_count = 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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* save SPSR also; how?.  */
+      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_handle_swi_insn (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 reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+        thumb_insn_r->reg_rec_count = register_count + 1;
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_regval;
+      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--;
+        }
+      thumb_insn_r->mem_rec_count = register_count;
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            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 0;
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[8]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_ld_str_insn,    /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[8]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 

+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) 
+            ? arm_handle_insn[insn_id] (arm_record) 
+            : handle_extension_space (arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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(0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; 
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , 
(arm_record.arm_regs[no_of_rec])));
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-12 21:21                     ` Petr Hluzín
@ 2011-05-24  6:44                       ` paawan oza
  0 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-24  6:44 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb-patches

Hi Peter,

thank you again for your comments.
please find my comments inlined below.
patch is coming in next mails.



Fri, May 13, 2011 2:50:26 AMRe: [PATCH] arm reversible : <phase_2_complete>
From: Petr Hluzín<petr.hluzin@gmail.com>   
To: paawan oza<paawan1982@yahoo.com>   
Cc: gdb-patches@sourceware.org   

________________________________
 
Hi

On 7 May 2011 15:49, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr and Tom,
>
> I have implemented most of your comments..
> The comments which I could not put it in are below with explanation.
>
> 1) ARM_RECORD_ARCH_LIST_ADD_REG is used only at 2 places, but probably I 
wanted
> to
>
> give clear interface where it just takes only one argument, register number.
> I should have done it for memory, but have not done yet.
>
> sure, it hides local variable usage and it doesnt look good, but my intension
> was to give clear interface
>
> to function process_record modifiers.
>
> I am still thinking over it.

(The third revision (2011-05-12) of the patch no longer uses the macro. Good.)

Clear interface... yes, the macro hides one parameter, but I do not
see it as an advantage. In fact the hiding looks more like an
disadvantage - it is harder to reason what the code does. (This would
apply to its memory variant if you did one.)

Why do you think there is an use for an interface?
Are there going to be more register-memory-recording implementations
behind the interface?

If not then the interface would be only a scaffolding prepared for an
event which will not happen. Sure, the need to add another
implementation of change-recording may arise one day but it may not
and if it does then altering the code is matter of doing "find all
references" in IDE. In theory any part of a program can have an
alternate implementation.
 
Oza: this is taken care.

> 2) > +   uint32_t opcode;              /* insn opcode.  */
>
> I understand that above is one of the fields of arm_insn_record, but why I am
> usiong it as global field,
> because the decoding bits by this field kind of global and common to most of 
>the
> insns.
>
> probably I would like to just extract it once and use anywhere, but
> unfortunately I have extracted in every function
> and seems local, will work on that though.

FYI: The struct field is always initialized by "bits
(arm_insn_r->arm_insn, 21, 24)" - except in
arm_handle_coproc_data_proc_insn(). If it is not a bug then the
initializations cannot be merged to one place.
 
(For me: the 3rd revision of the patch still uses the opcode and decode fields.)
 
Oza: yes, I agree, but still I am considering it as global though I have local 
usage because it makes an ARM_RECORD, and later in future we can pass whole 
structure info to any other function, where opcode might be useful. Currently it 
seems local and may be it will remain local, but probably it was just the design 
in that way.


> 3)
> + start_address = start_address + 4
> - start_address = start_address - 4
> in two of the four cases.
>
> If you have a look at the code, start_address initialization is the key factor
> for addressing mode.
> not how start_address later gets incremented.. so even in decrement mode,
> increment is necessary but
> initialization is different.

Oh, I now see. You are right. I was confused because I would wrote
that differently, but your version is good.
 
Oza: thanks.

> 4)
> In arm_handle_coproc_data_proc_insn():
>> +            tdep->arm_swi_record(reg_cache);
>
> When this line is executed this function still returns -1 (i.e. failure).
> I guess the two if's are intended to return success then.
>
> oza: the coprocessor insns are not implemented and syscall record too. so in
> both cases we return
> -1.

But when it does become implemented the branch will incorrectly return
a failing value.

I assume the recording of the instruction OS-dependent, right?
And OS-kind will be run-time configurable?

If yes, then I suggest documenting the variability, e.g.:
-/* Parse swi insn args, sycall record.  */
+/* Parse swi insn args, OS-dependent.  */
 
Oza: if (15 == arm_insn_r->opcode) is only for systemcalls, nothing else.
So anyother coprocessor branch will not fall into if. Once they are implemented 
no more need to return -1.
I can document it if you like.
And swi args and parsing is doen in another file which is not yet taken, so all 
os depedent stuff will be in linux file.
If you see this file is arm-tdep (target depedent, not OS depedent).


> 5)
> The return value is never tested. What is its meaning?
>
> The parsed args seem to be stored as a side-effect. Where are they stored?
> (Answers should go to comments.)
> (Since this is an indirect call, the documentation should be more
> verbose than usual cases.)
>
> Oza: swi basically equivalent to sysenter an int80 insn on x86, so systemcall 
>is
> implemented that way.
> I am going to work on that implementation in phase 3.
> phase 2 does not support it.

OK. I guess it will use `arm_insn_r' to record the changes - which
would have to be added as an argument. FYI.


Oza : ok I guess here I have nothing to change.
 
 

Moving on.
Comments on the version 3 (2011-05-12) of the patch.
http://sources.redhat.com/ml/gdb/2011-05/msg00028.html

Typos: recors, mendatory,
preccedded (-> preceded), accorindly, addresing - addressing,
wihtout optmization
(Some typos were fixed in v3 before I could reply to v2. Good.)

A function arm_handle_data_pro_mic_load_str_insn() in old patch is named as
arm_handle_data_pro_mic_load_str_insn()
in the last patch. The previous name contained more familiar
word/contractions ("misc", "proc")
Was that accidental?
 
Oza: corrected back, I was trying to take care of 80 line limit, taken care and 
changed to more meaning ful.

+#define GET_REG_VAL(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);

What do you gain by hiding calls by the macros?
E.g. do you expect the the function to be changed?

My concern is the slight difficulty reading the code: a reader is more
likely to be familiar with the regcache_raw_read..() functions than
the macros.


Oza: I understand your point. There are many versions of regcache_raw_read….so 
just was trying to apply clear interface to the next developers, probably they 
can go for any read API technically, but this is just to restrict them using 
only single API for record code.

In arm_handle_data_pro_mic_load_str_insn()
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];

You can get the same result (and simpler code) with
ULONGEST u_buf[2];
or maybe also better name with
ULONGEST u_regvals[2];

The same applies to other functions.
 
Oza: It is correct, it was mis-evolved as inistially it was union with 2 members 
and I fixed Tom’s review comments for endianness. I will change this, but pelase 
do not mind if it is not there in the immediate versions of patch, eventually 
after testing it will be changed.

in handle_extension_space():
+    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));

The `arm_insn_r->arm_insn' is a block of 4 bytes (ARM), not a classical number.
Therefore I feel its more appropriate to include leading zeroes, i.e.
use "0x%08x" format.
Which formating prefer other fellows?
(Does have '0' in "%0x" have any effect?)
(In multiple functions.)


Oza: well, this is directly taken from x86 code directly as it seems standard 
way of throwing this type of error.

In arm_handle_data_pro_mic_load_str_insn()
>+  /* following is always true, in case none of the above conditions meet, it 
>will */
>+  else if (arm_insn_r->opcode <= 15)

You can add "else assert(false)" branch and get rid of the comment.
The assert statement has exact meaning, the meaning is faster to read
and machines check it. (Even some tools may understand it.)
A comment may go wrong over time as a code is changed (and may be
wrong even now).


Oza: done

The same goes for arm_handle_data_proc_imm_insn().
 
 
Oza: done.

>+#define NO_OF_TYPE_OF_ARM_INSNS 8
>+#define NO_OF_TYPE_OF_THUMB_INSNS 8

These are used only for arm_handle_insn[] and thumb_handle_insn[]
array initializations.
So far they have the meaning of "the size of the arrays" - which can
be easily deduced from the arrays itself.
Plus they are fixed by the instruction set architecture - not
configurable, unlikely to change, perhaps not to be used on more
places - therefore the usual guideline of not embedding magic
constants does not apply here.
It is a minor point.
 
How do other people feel about it (an identifier which does not have to exist)?
Oza, do you plan to use them at more places?
 
Oza: point taken and removed, I suppose not going to use it.


> > > +  struct regcache *regcache;
> >
> > Many functions use unnecesary cast to init local var, e.g. `(struct
> > regcache*) thumb_insn_r->regcache'.
> > Most functions do not actually use the var.

This is still true.
 
Oza: done and corrected. Thanks.


In arm_handle_ld_st_imm_offset_insn()
>+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
>+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>+  uint32_t record_buf[8], record_buf_mem[8];

Vars reg_src2, immed_high, immed_low are unused.
There are also some unused variables with whole-function scope in
other functions. Should I report them?
 
Oza: please report as I don’t have any automated tool which reports them, if it 
is not effort for you please report all if possible. Gcc also give some warning 
about unused one, but not sure about gdb warning suppression.


> > The ? and : should be at the begging.
> > GNU style guideline: "When you split an expression into multiple
> > lines, split it before an operator, not after one."
> > Also I find it more readable.
>
>+      ret = (0x0F != arm_record->cond) \
>+            ? \
>+            arm_handle_insn[insn_id] (arm_record) \
>+            : \
>+            handle_extension_space(arm_record);

Erm, this is even weirder. It is supposed to look like:
      ret = (0x0F != arm_record->cond)
            ? arm_handle_insn[insn_id] (arm_record)
            : handle_extension_space(arm_record);

Also the patch seems to have extra slashes ('\') at the end.
They are unnecessary. Maybe even incorrect. (Did an email client do that?)


Oza: corrected.

In thumb_handle_ld_st_reg_offset_insn ():
Consider applying this change:
-    }
-
-  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
-  if (opcode1)
+  } else if(bits (thumb_insn_r->arm_insn, 10, 12))

This would allow you to get rid of the `goto' statements.
 
Oza: good one, thanks, done.


In decode_insn()
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +      gdb_byte buf[insn_size];
> +    } u_buf;

The `unsigned_regval' field is not referenced.


Oza: corrected.
-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-07 13:50                   ` paawan oza
  2011-05-09 14:57                     ` Tom Tromey
@ 2011-05-12 21:21                     ` Petr Hluzín
  2011-05-24  6:44                       ` paawan oza
  1 sibling, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-05-12 21:21 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb-patches

Hi

On 7 May 2011 15:49, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr and Tom,
>
> I have implemented most of your comments..
> The comments which I could not put it in are below with explanation.
>
> 1) ARM_RECORD_ARCH_LIST_ADD_REG is used only at 2 places, but probably I wanted
> to
>
> give clear interface where it just takes only one argument, register number.
> I should have done it for memory, but have not done yet.
>
> sure, it hides local variable usage and it doesnt look good, but my intension
> was to give clear interface
>
> to function process_record modifiers.
>
> I am still thinking over it.

(The third revision (2011-05-12) of the patch no longer uses the macro. Good.)

Clear interface... yes, the macro hides one parameter, but I do not
see it as an advantage. In fact the hiding looks more like an
disadvantage - it is harder to reason what the code does. (This would
apply to its memory variant if you did one.)

Why do you think there is an use for an interface?
Are there going to be more register-memory-recording implementations
behind the interface?

If not then the interface would be only a scaffolding prepared for an
event which will not happen. Sure, the need to add another
implementation of change-recording may arise one day but it may not
and if it does then altering the code is matter of doing "find all
references" in IDE. In theory any part of a program can have an
alternate implementation.

> 2) > +   uint32_t opcode;              /* insn opcode.  */
>
> I understand that above is one of the fields of arm_insn_record, but why I am
> usiong it as global field,
> because the decoding bits by this field kind of global and common to most of the
> insns.
>
> probably I would like to just extract it once and use anywhere, but
> unfortunately I have extracted in every function
> and seems local, will work on that though.

FYI: The struct field is always initialized by "bits
(arm_insn_r->arm_insn, 21, 24)" - except in
arm_handle_coproc_data_proc_insn(). If it is not a bug then the
initializations cannot be merged to one place.

(For me: the 3rd revision of the patch still uses the opcode and decode fields.)

> 3)
> + start_address = start_address + 4
> - start_address = start_address - 4
> in two of the four cases.
>
> If you have a look at the code, start_address initialization is the key factor
> for addressing mode.
> not how start_address later gets incremented.. so even in decrement mode,
> increment is necessary but
> initialization is different.

Oh, I now see. You are right. I was confused because I would wrote
that differently, but your version is good.

> 4)
> In arm_handle_coproc_data_proc_insn():
>> +            tdep->arm_swi_record(reg_cache);
>
> When this line is executed this function still returns -1 (i.e. failure).
> I guess the two if's are intended to return success then.
>
> oza: the coprocessor insns are not implemented and syscall record too. so in
> both cases we return
> -1.

But when it does become implemented the branch will incorrectly return
a failing value.

I assume the recording of the instruction OS-dependent, right?
And OS-kind will be run-time configurable?

If yes, then I suggest documenting the variability, e.g.:
-/* Parse swi insn args, sycall record.  */
+/* Parse swi insn args, OS-dependent.  */

> 5)
> The return value is never tested. What is its meaning?
>
> The parsed args seem to be stored as a side-effect. Where are they stored?
> (Answers should go to comments.)
> (Since this is an indirect call, the documentation should be more
> verbose than usual cases.)
>
> Oza: swi basically equivalent to sysenter an int80 insn on x86, so systemcall is
> implemented that way.
> I am going to work on that implementation in phase 3.
> phase 2 does not support it.

OK. I guess it will use `arm_insn_r' to record the changes - which
would have to be added as an argument. FYI.

Moving on.
Comments on the version 3 (2011-05-12) of the patch.
http://sources.redhat.com/ml/gdb/2011-05/msg00028.html

Typos: recors, mendatory,
preccedded (-> preceded), accorindly, addresing - addressing,
wihtout optmization
(Some typos were fixed in v3 before I could reply to v2. Good.)

A function arm_handle_data_pro_mic_load_str_insn() in old patch is named as
arm_handle_data_pro_mic_load_str_insn()
in the last patch. The previous name contained more familiar
word/contractions ("misc", "proc")
Was that accidental?

+#define GET_REG_VAL(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);

What do you gain by hiding calls by the macros?
E.g. do you expect the the function to be changed?

My concern is the slight difficulty reading the code: a reader is more
likely to be familiar with the regcache_raw_read..() functions than
the macros.


In arm_handle_data_pro_mic_load_str_insn()
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];

You can get the same result (and simpler code) with
ULONGEST u_buf[2];
or maybe also better name with
ULONGEST u_regvals[2];

The same applies to other functions.

in handle_extension_space():
+    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));

The `arm_insn_r->arm_insn' is a block of 4 bytes (ARM), not a classical number.
Therefore I feel its more appropriate to include leading zeroes, i.e.
use "0x%08x" format.
Which formating prefer other fellows?
(Does have '0' in "%0x" have any effect?)
(In multiple functions.)


In arm_handle_data_pro_mic_load_str_insn()
>+   /* following is always true, in case none of the above conditions meet, it will */
>+  else if (arm_insn_r->opcode <= 15)

You can add "else assert(false)" branch and get rid of the comment.
The assert statement has exact meaning, the meaning is faster to read
and machines check it. (Even some tools may understand it.)
A comment may go wrong over time as a code is changed (and may be
wrong even now).

The same goes for arm_handle_data_proc_imm_insn().

>+#define NO_OF_TYPE_OF_ARM_INSNS 8
>+#define NO_OF_TYPE_OF_THUMB_INSNS 8

These are used only for arm_handle_insn[] and thumb_handle_insn[]
array initializations.
So far they have the meaning of "the size of the arrays" - which can
be easily deduced from the arrays itself.
Plus they are fixed by the instruction set architecture - not
configurable, unlikely to change, perhaps not to be used on more
places - therefore the usual guideline of not embedding magic
constants does not apply here.
It is a minor point.

How do other people feel about it (an identifier which does not have to exist)?
Oza, do you plan to use them at more places?


> > > +  struct regcache *regcache;
> >
> > Many functions use unnecesary cast to init local var, e.g. `(struct
> > regcache*) thumb_insn_r->regcache'.
> > Most functions do not actually use the var.

This is still true.


In arm_handle_ld_st_imm_offset_insn()
>+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
>+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>+  uint32_t record_buf[8], record_buf_mem[8];

Vars reg_src2, immed_high, immed_low are unused.
There are also some unused variables with whole-function scope in
other functions. Should I report them?


> > The ? and : should be at the begging.
> > GNU style guideline: "When you split an expression into multiple
> > lines, split it before an operator, not after one."
> > Also I find it more readable.
>
>+      ret = (0x0F != arm_record->cond) \
>+            ? \
>+            arm_handle_insn[insn_id] (arm_record) \
>+            : \
>+            handle_extension_space(arm_record);

Erm, this is even weirder. It is supposed to look like:
      ret = (0x0F != arm_record->cond)
            ? arm_handle_insn[insn_id] (arm_record)
            : handle_extension_space(arm_record);

Also the patch seems to have extra slashes ('\') at the end.
They are unnecessary. Maybe even incorrect. (Did an email client do that?)


In thumb_handle_ld_st_reg_offset_insn ():
Consider applying this change:
-    }
-
-  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
-  if (opcode1)
+  } else if(bits (thumb_insn_r->arm_insn, 10, 12))

This would allow you to get rid of the `goto' statements.


In decode_insn()
> +  struct
> +    {
> +      ULONGEST unsigned_regval;
> +      gdb_byte buf[insn_size];
> +    } u_buf;

The `unsigned_regval' field is not referenced.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-10 15:37                         ` Tom Tromey
@ 2011-05-12  5:06                           ` paawan oza
  0 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-12  5:06 UTC (permalink / raw)
  To: Tom Tromey, Petr Hluzín, gdb-patches

Hi All,

please find the updated patch below.

PATCH STARTS
--------------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-05-12 09:04:48.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1735 @@
                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 NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+    
+#define GET_REG_VAL(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL)  \
+        regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            REGS[LENGTH - 1] = RECORD_BUF[LENGTH - 1];  \
+            LENGTH--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            MEMS[LENGTH - 1].addr = RECORD_BUF[(LENGTH * 2) - 1]; \
+            MEMS[LENGTH - 1].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+            LENGTH--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* 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 recors */
+  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 mendatory 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;
+}
+
+/* handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t ret = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  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.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      ret = -1;
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      ret = -1;
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      ret = -1;
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      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 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 
+arm_handle_data_pro_mic_load_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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 preccedded 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 insns, 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); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_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_buf[0].unsigned_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 ((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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* what if 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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, 
&u_buf[0].unsigned_regval);            

+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = 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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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;
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  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;
+    }
+
+  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_handle_data_proc_imm_insn (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.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }   
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  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;
+    }
+
+  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_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  struct
+    {
+      ULONGEST signed_word;
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].unsigned_regval);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].unsigned_regval + 
u_buf[1].unsigned_regval;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - 
u_buf[0].unsigned_regval;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+            GET_REG_VAL_SIGNED (reg_cache, reg_src1, &u_buf[0].signed_word);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].unsigned_regval << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> 
shift_imm; 

+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].unsigned_regval, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, 
&u_buf[1].unsigned_regval);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) 
\
+                                    | (u_buf[0].unsigned_regval) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+                         | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - 
shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_handle_ld_st_multiple_insn (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 shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        record_buf[register_count] = reg_src1;
+        record_buf[register_count + 1] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; 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++;
+              }
+          }
+        arm_insn_r->reg_rec_count = register_count + 2;
+    }
+  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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 
4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].unsigned_regval;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].unsigned_regval + 4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        default:
+          gdb_assert_not_reached ("Invalid addressing mode for insn");
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+  printf_unfiltered (_("Process record does not support instruction "
+                     "0x%0x at address %s.\n"),
+                     arm_insn_r->arm_insn,
+                     paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr));
+
+   return -1;   
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            printf_unfiltered (_("no syscall record support\n"));
+            return -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 -1;   
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+          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_buf[0].unsigned_regval+u_buf[1].unsigned_regval; 

+          thumb_insn_r->mem_rec_count = 1;
+        }                 
+      goto end;
+    }            
+  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;
+      goto end;
+    }
+    
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  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;
+    }  
+
+  end:
+
+  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_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{ 
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.unsigned_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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.unsigned_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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+      thumb_insn_r->reg_rec_count = register_count + 2;
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_regval -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + 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--;
+        }
+      thumb_insn_r->mem_rec_count = 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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* save SPSR also; how?.  */
+      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_handle_swi_insn (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  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];
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+        thumb_insn_r->reg_rec_count = register_count + 1;
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.unsigned_regval;
+      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--;
+        }
+      thumb_insn_r->mem_rec_count = register_count;
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            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 0;
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+
+  /* BL , 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;     
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_pro_mic_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+             , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch)); 

+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) \
+            ? \
+            arm_handle_insn[insn_id] (arm_record) \
+            : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+           , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+      
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* yet to be implemented; handle thumb2 part here.  */
+      printf_unfiltered (_("Process record does not support 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(0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  struct
+    {
+      ULONGEST unsigned_regval;
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.unsigned_regval);
+    
+  if (!(u_buf.unsigned_regval & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  if (0 == ret)
+    {
+      /* record registers.  */
+      record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; 
no_of_rec++)
+            {
+              if (record_arch_list_add_reg (arm_record.regcache \
+                                           , 
(arm_record.arm_regs[no_of_rec])));
+              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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified





Regards,
Oza.



----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb-patches@sourceware.org
Sent: Tue, May 10, 2011 9:06:45 PM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> phase 2 is independent of phase 3. and I would like to have it
Oza> checked wihtout waiting for end.  I have just changed the patch
Oza> which now takes care of endianness.

Ok, thanks.  This plan sounds good to me.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-10  5:42                       ` paawan oza
@ 2011-05-10 15:37                         ` Tom Tromey
  2011-05-12  5:06                           ` paawan oza
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-05-10 15:37 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> phase 2 is independent of phase 3. and I would like to have it
Oza> checked wihtout waiting for end.  I have just changed the patch
Oza> which now takes care of endianness.

Ok, thanks.  This plan sounds good to me.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-09 14:57                     ` Tom Tromey
  2011-05-10  5:42                       ` paawan oza
@ 2011-05-10  5:50                       ` paawan oza
  1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-10  5:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb-patches

one more thing I would like to tell which is bit emotional for me.
as my contributions started because of Michael Snyder and he gave his first 
review comments on this patch months back.
so I would like to dedicate all my work for arm-reversible to him, and to his 
gracious support to me.

Thanks & Regards,
Oza.



----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb-patches@sourceware.org
Sent: Mon, May 9, 2011 8:27:21 PM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

I think for patch discussion we can stop CCing gdb@.

Oza> Tom: I still need to take care of endianess issue, which I will in
Oza> the coming stage.

If your plan is to check in phase 2 before working on phase 3, then I
think this should be addressed first.

If the phases are personal milestones and you don't want to check-in
before the end, then that is of course fine.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-09 14:57                     ` Tom Tromey
@ 2011-05-10  5:42                       ` paawan oza
  2011-05-10 15:37                         ` Tom Tromey
  2011-05-10  5:50                       ` paawan oza
  1 sibling, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-05-10  5:42 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb-patches

Hi Tom,

yes; 
phase 2 is independent of phase 3. and I would like to have it checked wihtout 
waiting for end.
I have just changed the patch which now takes care of endianness.

finally I have found function which takes care of host-target differences. which 
is
'regcache_raw_read_unsigned'.

I will post the patch soon with that and some minor changes. 

Regards,
Oza.




----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb-patches@sourceware.org
Sent: Mon, May 9, 2011 8:27:21 PM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

I think for patch discussion we can stop CCing gdb@.

Oza> Tom: I still need to take care of endianess issue, which I will in
Oza> the coming stage.

If your plan is to check in phase 2 before working on phase 3, then I
think this should be addressed first.

If the phases are personal milestones and you don't want to check-in
before the end, then that is of course fine.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-07 13:50                   ` paawan oza
@ 2011-05-09 14:57                     ` Tom Tromey
  2011-05-10  5:42                       ` paawan oza
  2011-05-10  5:50                       ` paawan oza
  2011-05-12 21:21                     ` Petr Hluzín
  1 sibling, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-05-09 14:57 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb-patches

I think for patch discussion we can stop CCing gdb@.

Oza> Tom: I still need to take care of endianess issue, which I will in
Oza> the coming stage.

If your plan is to check in phase 2 before working on phase 3, then I
think this should be addressed first.

If the phases are personal milestones and you don't want to check-in
before the end, then that is of course fine.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
  2011-05-07 13:50                   ` paawan oza
@ 2011-05-07 13:56                   ` paawan oza
  2 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-07 13:56 UTC (permalink / raw)
  To: Petr Hluzín, gdb, gdb-patches

Hi,

With almost all the comments resolved posting the updated patch..
if there are still typos I will try to do it with more spelling enforcements.

thanks to Tom, Petr, Pedro and Yao for their valuable comments to make this 
patch better.
I am still looking for more comments, so I can still shape it further.
.

ARM-REVERSIBLE PATCH
------------------------------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1708 @@
                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 NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t)*(LENGTH)); \
+        while(LENGTH) \
+          { \
+            REGS[LENGTH -1] = RECORD_BUF[LENGTH-1];  \
+            LENGTH--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            MEMS[LENGTH - 1].addr = RECORD_BUF[(LENGTH * 2) - 1]; \
+            MEMS[LENGTH - 1].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+            LENGTH--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* ARM memory record strcuture/  */
+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 recors */
+  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;
+
+
+/* checkes ARM SBZ and SBO mendatory 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;
+}
+
+/* handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+arm_handle_data_pro_mic_load_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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 preccedded 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 ?  */
+          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 insns, 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); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[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_buf[0].s_word;
+      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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
+      
+      /* save SPSR also; how?  */
+      return -1;
+    }  
+  else if ((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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = 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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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;
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  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;
+    }
+
+  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_handle_data_proc_imm_insn (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.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }   
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  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;
+    }
+
+  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_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              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_handle_ld_st_reg_offset_insn (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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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 ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                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_handle_ld_st_multiple_insn (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 shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* 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 optmization.  */
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        record_buf[register_count] = reg_src1;
+        record_buf[register_count + 1] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; 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++;
+              }
+          }
+        arm_insn_r->reg_rec_count = register_count + 2;
+    }
+  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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[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_buf[0].s_word) - (register_count * 4) + 4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          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--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        default:
+          gdb_assert_not_reached ("Invalid addressing mode for insn");
+        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_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+   return -1;   
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+     
+   return -1;   
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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_handle_add_sub_cmp_mov_insn (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_handle_ld_st_reg_offset_insn (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;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          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_buf[0].s_word+u_buf[1].s_word; 
+          thumb_insn_r->mem_rec_count = 1;
+        }                 
+      goto end;
+    }            
+  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;
+      goto end;
+    }
+    
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  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;
+    }  
+
+  end:
+
+  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_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.s_word + (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_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{ 
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.s_word + (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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.s_word + (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_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 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];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+      thumb_insn_r->reg_rec_count = register_count + 2;
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + 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--;
+        }
+      thumb_insn_r->mem_rec_count = 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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if 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;
+      thumb_insn_r->reg_rec_count = 2;
+      /* save SPSR also; how?.  */
+      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_handle_swi_insn (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  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];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+        thumb_insn_r->reg_rec_count = register_count + 1;
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      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--;
+        }
+      thumb_insn_r->mem_rec_count = register_count;
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            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 0;
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , 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;     
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_pro_mic_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) \
+            ? \
+            arm_handle_insn[insn_id] (arm_record) \
+            : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = u_buf.s_word;  
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* yet to be implemented; handle thumb2 part here.  */
+    }
+  else
+    {
+      /* throw assertion.  */
+      gdb_assert(0);
+    }
+  
+  return ret;
+}
+
+/* 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;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  if (0 == ret)
+    {
+      ARM_RECORD_ARCH_LIST_ADD_REG(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 (ARM_RECORD_ARCH_LIST_ADD_REG 
(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_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_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

Regards,
Oza.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
@ 2011-05-07 13:50                   ` paawan oza
  2011-05-09 14:57                     ` Tom Tromey
  2011-05-12 21:21                     ` Petr Hluzín
  2011-05-07 13:56                   ` paawan oza
  2 siblings, 2 replies; 128+ messages in thread
From: paawan oza @ 2011-05-07 13:50 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr and Tom,

I have implemented most of your comments..
The comments which I could not put it in are below with explanation.

1) ARM_RECORD_ARCH_LIST_ADD_REG is used only at 2 places, but probably I wanted 
to 

give clear interface where it just takes only one argument, register number.
I should have done it for memory, but have not done yet.

sure, it hides local variable usage and it doesnt look good, but my intension 
was to give clear interface 

to function process_record modifiers.

I am still thinking over it.


2) > +   uint32_t opcode;              /* insn opcode.  */

I understand that above is one of the fields of arm_insn_record, but why I am 
usiong it as global field,
because the decoding bits by this field kind of global and common to most of the 
insns.

probably I would like to just extract it once and use anywhere, but 
unfortunately I have extracted in every function
and seems local, will work on that though.

3) 
+ start_address = start_address + 4
- start_address = start_address - 4
in two of the four cases.

If you have a look at the code, start_address initialization is the key factor 
for addressing mode.
not how start_address later gets incremented.. so even in decrement mode, 
increment is necessary but
initialization is different.

4)
In arm_handle_coproc_data_proc_insn():
> +            tdep->arm_swi_record(reg_cache);

When this line is executed this function still returns -1 (i.e. failure).
I guess the two if's are intended to return success then.

oza: the coprocessor insns are not implemented and syscall record too. so in 
both cases we return
-1.

5)
The return value is never tested. What is its meaning?

The parsed args seem to be stored as a side-effect. Where are they stored?
(Answers should go to comments.)
(Since this is an indirect call, the documentation should be more
verbose than usual cases.)

Oza: swi basically equivalent to sysenter an int80 insn on x86, so systemcall is 
implemented that way.
I am going to work on that implementation in phase 3.
phase 2 does not support it.

6) 
Tom: I still need to take care of endianess issue, which I will in the coming 
stage.

Note: updated patch will be mailed in the next mail.

Regards,
OZa.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-04 21:33                     ` Petr Hluzín
@ 2011-05-05 15:29                       ` Tom Tromey
  0 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-05-05 15:29 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb, gdb-patches

>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:

Petr> I investigated the patch because I am interested reversible debugging.
Petr> However I barely work on GDB. I would be mostly interested in
Petr> polishing, removing rough corners and making tiny things work right.
Petr> But I feel that real hackers here do not like making tools nice to
Petr> use; or making things work for those who are not already experts; for
Petr> people who expect their tools to know their job without requiring
Petr> user's supervision, etc.

I can understand why you think this.
I have two things to suggest here.

First, in my experience with GDB, changes to the CLI are one of the most
hotly debated areas -- both what the user types and also what GDB
prints.  You can see any number of discussions about this in the
archives.

So, I think us developers do pay attention -- but maybe a funny kind of
attention, as we're used to the quirks of GDB CLI and expect additions
to be faithful to its traditions.

Second, feel free to comment on changes.  We try to make GDB as good as
we know how, but nobody has a monopoly on good ideas.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-02 14:47                   ` Tom Tromey
@ 2011-05-04 21:33                     ` Petr Hluzín
  2011-05-05 15:29                       ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-05-04 21:33 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb, gdb-patches

On 2 May 2011 16:46, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
> Petr> I also recommend to define a local variable in the smalles scope
> Petr> possible, however I understand that many
> Petr> programmers use weak tools and knowing its definition requires more
> Petr> effort than placing cursor on the variable - therefore they prefer
> Petr> definitions at the start of function.
>
> I agree, using the smallest scope is generally preferable.
> This practice makes it simpler to reason about the code.
>
> Petr> My IDE has a spellchecker which underlines typos. No effort required.
> Petr> (Consider upgrading your tools.)
>
> I'm curious to know what IDE you use for working on GDB.

The spell-checking and highlighting/displaying variable's definition
(plus many other goodies) is done by "Visual Assist X" extension to
Visual Studio. The initialization by 0xCCCCCCCC is done by VS compiler
and C runtime. VS can be configured to use an external compiler; of
course you loose some perks.

I am still searching for a comfortable cross-platform IDE.

I investigated the patch because I am interested reversible debugging.
However I barely work on GDB. I would be mostly interested in
polishing, removing rough corners and making tiny things work right.
But I feel that real hackers here do not like making tools nice to
use; or making things work for those who are not already experts; for
people who expect their tools to know their job without requiring
user's supervision, etc.

> Petr> GDB commiters: please reply whether you agree with my review. (So that
> Petr> paawan oza does not spend effort in vain.)
>
> I thought it was quite good.  Thanks for doing this.

Thanks for feedback.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
@ 2011-05-02 14:47                   ` Tom Tromey
  2011-05-04 21:33                     ` Petr Hluzín
  2011-05-07 13:50                   ` paawan oza
  2011-05-07 13:56                   ` paawan oza
  2 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-05-02 14:47 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb, gdb-patches

>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:

Petr> I also recommend to define a local variable in the smalles scope
Petr> possible, however I understand that many
Petr> programmers use weak tools and knowing its definition requires more
Petr> effort than placing cursor on the variable - therefore they prefer
Petr> definitions at the start of function.

I agree, using the smallest scope is generally preferable.
This practice makes it simpler to reason about the code.

Petr> My IDE has a spellchecker which underlines typos. No effort required.
Petr> (Consider upgrading your tools.)

I'm curious to know what IDE you use for working on GDB.

For those using Emacs, M-x flyspell-prog-mode will spell-check in
comments and strings.

Petr> Also I have no vote in GDB development, so my patch approval would
Petr> have little impact.

I appreciate thoughtful reviews from anyone, regardless of their
official status.  I think GDB patches still spend too much time waiting
for review, and this sort of thing can help speed things up.

Petr> GDB commiters: please reply whether you agree with my review. (So that
Petr> paawan oza does not spend effort in vain.)

I thought it was quite good.  Thanks for doing this.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-30 16:16                           ` paawan oza
@ 2011-05-02 13:28                             ` Tom Tromey
  0 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-05-02 13:28 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> So you are suggesting;
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
Oza> if (target is big endian)
Oza>   {
Oza>         convert_big_to_little (u_buf.s_word)
Oza>   }
Oza> something like above ?
Oza> right ?

More or less, but if you use the existing functions like
extract_unsigned_integer or extract_typed_address, then they
will handle all the details.

Oza> and while replaying do I need to convert it to big endian ?
Oza> somethig like that ?

It depends on what you are doing.

If you are doing calculations on some number, then you have to extract
it properly so that the host math works correctly.  If you are just
storing some data to be restored verbatim, then you don't need to
convert at all.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-25 14:03               ` paawan oza
@ 2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
                                     ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-05-01  1:20 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb, gdb-patches

On 25 April 2011 16:03, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr,
>
> I have implemented your review comments.

Typo "hamdle" in thumb_hamdle_ld_st_stack_insn() still exists.

I decoded the `arm_mem_r *arm_mems' strucutre:

arm_mems[0].len - is number of valid records `arm_mems[i]' after [0].
arm_mems[i].len - is number of bytes modified by the instruction.
arm_mems[0].addr - is undefined (never written, never read) - except
on line: thumb_insn_r->arm_mems[0].addr =
u_buf[0].s_word+u_buf[1].s_word;
arm_mems[i].addr - is target address of the modified block (for i=1..)

This is reusing field arm_mem_r::len for two different things.
This is ugly.

Move the counter into insn_decode_record_t. Or use struct arm_mem_r {
	int count;
	struct {
		uint32_t len;
		CORE_ADDR addr;
	} array[0];
}

Each instance of insn_decode_record_t is allocated and freed before
new instance is allocated, therefore its size does not matter.

The same applies for arm_record.arm_regs[].


> +/* arm-reversible process reacord data structures.  */

Typo, reacord.


> +#define THUMB2_INSN_SIZE_BYTES 4

Not used.
In decode_insn() I suggest adding
   else if (THUMB_INSN_SIZE_BYTES == insn_size)
     {
       arm_record->arm_insn = u_buf.s_word;
       arm_record->id = bits (arm_record->arm_insn, 13, 15);
       ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
     }
+  else if THUMB2_INSN_SIZE_BYTES == insn_size)
+    // not implemented, maybe complain loudly
+  else
+    assert(false);

This would document the possible values.


+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)

This is used only at two places:

+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1; no_of_rec<=arm_record.arm_regs[0]; no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }

This saves only few characters and no lines of code.
But adds an indirection and hides use of local variable 'arm_record'.
Also the caller already contains record_arch_list_add_* functions.


Structure insn_decode_record:

> +
> + typedef struct insn_decode_record_t {
> +   uint32_t arm_insn;            /* should accomodate thumb.  */

Typo, accomodate -> accommodate.

> +   uint32_t opcode;              /* insn opcode.  */

This field is practically used as a local variable - all functions
which read the field also initialize it.
Furthermore `arm_insn' is a kind of "insn opcode", too.
Local-like varibales make a structure look more complex than it is;
this places fear into those who will want to modify the code.

> +   uint32_t id;                  /* type of insn.  */

Practically local variable in decode_insn(). No other function ever uses it.

> +   uint32_t cond;                /* condition code.  */

Is not initialized if (THUMB_INSN_SIZE_BYTES == insn_size).
It is not a bug since Thumb mode does not use condition prefixes.
However I find useful to assign -1 or something to indicate that:
* the field does not have an usual value
* I did not acidentaly skipped initialization
* I am not relying on initialization from other place
* hopefully the special value will trigger assertion if Thumb code
actually uses it.
(Actually my runtime fills memory with 0xCCCCCCC or something for this
reason, so I merelly add a comment about the non-use.)

> +  struct gdbarch *gdbarch;

Most functions do not actually use the field. Consider removing the
dummy variables in relevant functions.

> +  struct regcache *regcache;

Many functions use unnecesary cast to init local var, e.g. `(struct
regcache*) thumb_insn_r->regcache'.
Most functions do not actually use the var.

> + ...} insn_decode_record;

I suggest to add comment to insn_decode_record_t :

/* Contains opcode of current instruction and execution state (before
entry to decode_insn()),
contains list of to-be-modified registers and memory blocks (on return
from decode_insn()). */


Moving on:

In handle_extension_space()
> +  uint32_t reg_src1 = 0, reg_src2 = 0;

Unused locals.

In arm_handle_data_proc_imm_insn()
> +  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;

All these are unused.

In other functions:
GCC can detect when a local variable is used before it is initialized.
Your code initializes by 0 at the start of the function so the
advantage of GCC diagnostics is lost.
I recommend to not initialize a local variable until its "true" value
is know/computed.
I also recommend to define a local variable in the smalles scope
possible, however I understand that many
programmers use weak tools and knowing its definition requires more
effort than placing cursor on the variable - therefore they prefer
definitions at the start of function.


In arm_hamdle_ld_st_multiple_insn (I deleted irrelevant lines):
> +     switch(addr_mode)
> +      {
> +        /* Decrement after.  */
> +        case 0:
> +          start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Increment after.  */
> +        case 1:
> +          start_address = u_buf[0].s_word;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Decrement before.  */
> +        case 2:
> +          start_address = (u_buf[0].s_word) - (register_count * 4);
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Increment before.  */
> +        case 3:
> +          start_address = u_buf[0].s_word + 4;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;

Initialization of `start_address' looks good but I guess the increment
part should be:
+ start_address = start_address + 4
- start_address = start_address - 4
in two of the four cases.


> +
> +        default:
> +          /* unreachable.  */

Consider using gdb_assert_not_reached("Invalid addressing mode").


> +         printf("handling store insn, immed offfset insn\n");

Typo offfset. Should be printed conditionally.

> +       /* LDR insn has a capability to do branching, if
> +              MOV LR, PC is precedded by LDR insn having Rn as R15

Typo precedded -> preccedded. Multiple times.

> +   /* handle incremenrt after/before and decrment after.before mode;
> +        Rn is chaging depending on W bit, but as of now we store Rn too wihtout going for
> +        optmization.  */

Typos chaging, wihtout, optmization.

My IDE has a spellchecker which underlines typos. No effort required.
(Consider upgrading your tools.)


> +      ret = (0x0F != arm_record->cond)?
> +            arm_handle_insn[arm_record->id] ((void*)arm_record) :
> +            handle_extension_space(arm_record);

The ? and : should be at the begging.
GNU style guideline: "When you split an expression into multiple
lines, split it before an operator, not after one."
Also I find it more readable.


In decode_insn():
> +            arm_handle_insn[arm_record->id] ((void*)arm_record) :
> +      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);

The (void*) casts are now unnecessary.

In arm_handle_coproc_data_proc_insn():
> +            tdep->arm_swi_record(reg_cache);

When this line is executed this function still returns -1 (i.e. failure).
I guess the two if's are intended to return success then.

In thumb_handle_add_sub_cmp_mov_insn():
> +   union { ... } u_buf;

Is unused. So does in thumb_handle_shift_add_sub_insn(). Maybe more.


In thumb_handle_ld_st_reg_offset_insn():
> +      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
> +  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);

The values are never read.
If you remove the 'thumb_insn_r->opcode' assignment then you can
simplify the function and remove the goto's.


> @@ -200,6 +200,9 @@
>   /* Return the expected next PC if FRAME is stopped at a syscall
>      instruction.  */
>   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi args.  */
> +  int (*arm_swi_record) (struct regcache *regcache);

This field is newer assigned (only initialized to NULL).

I did not know that "swi" is an instruction. Is it a widely known fact
for ARM developers?
If not then use "swi insn" in the comment.

The return value is never tested. What is its meaning?

The parsed args seem to be stored as a side-effect. Where are they stored?
(Answers should go to comments.)
(Since this is an indirect call, the documentation should be more
verbose than usual cases.)

Disclaimers:

I am not familiar with ARM, I did not check e.g. if all cases are
handled, instructions have correct semantics etc.
Also I have no vote in GDB development, so my patch approval would
have little impact.

GDB commiters: please reply whether you agree with my review. (So that
paawan oza does not spend effort in vain.)

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 19:36                         ` Tom Tromey
@ 2011-04-30 16:16                           ` paawan oza
  2011-05-02 13:28                             ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-04-30 16:16 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

Hi Tom,

So you are suggesting;

GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
if (target is big endian)
  {
        convert_big_to_little (u_buf.s_word)
  }


something like above ?
right ?

and while replaying do I need to convert it to big endian ?
somethig like that ?

Regards,
Oza.


----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb@sourceware.org; 
gdb-patches@sourceware.org
Sent: Fri, April 29, 2011 1:06:39 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> but whole operation happens on target memory, so 
Oza> after 
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

Oza> we get scalar u_buf.s_word again in big-endian.

Oza> +      start_address = u_buf.s_word -  \
Oza> +                   (4 * (bit (thumb_insn_r->arm_insn, 8) + 
register_count)) ;

Oza> and above math is again in target memory in big endian machine and
Oza> record is saved to target memory.

Oza> I think it never gets fetched to host for any reason, Am I thinking
Oza> correct?

No, sorry.  Any code in gdb is by running on the host system.

So, GET_REG_VAL fetches the raw register -- from the target to the host.
`u_buf.s_word' is a scalar value in gdb, i.e., on the host.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
@ 2011-04-28 19:36                         ` Tom Tromey
  2011-04-30 16:16                           ` paawan oza
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-04-28 19:36 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> but whole operation happens on target memory, so 
Oza> after 
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

Oza> we get scalar u_buf.s_word again in big-endian.

Oza> +      start_address = u_buf.s_word -  \
Oza> +                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Oza> and above math is again in target memory in big endian machine and
Oza> record is saved to target memory.

Oza> I think it never gets fetched to host for any reason, Am I thinking
Oza> correct?

No, sorry.  Any code in gdb is by running on the host system.

So, GET_REG_VAL fetches the raw register -- from the target to the host.
`u_buf.s_word' is a scalar value in gdb, i.e., on the host.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 19:00                     ` Tom Tromey
@ 2011-04-28 19:22                       ` paawan oza
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
  1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-04-28 19:22 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

but whole operation happens on target memory, so 

after 
GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

we get scalar u_buf.s_word again in big-endian.


+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

and above math is again in target memory in big endian machine and record is 
saved to target memory.

I think it never gets fetched to host for any reason, Am I thinking correct?

Regards,
Oza.



----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb@sourceware.org; 
gdb-patches@sourceware.org
Sent: Fri, April 29, 2011 12:30:05 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Tom> It seems to me that extract_typed_address or something similar would be
Tom> better.

Oza> 1)  are suggesting to use something else than unions ? whatever you have 
Oza> described about union is right.

Oza> 2)  why could I use extract_typed_address instead of direct assignment ?

extract_typed_address handles endianess and conversion from "array of
bytes" to "host scalar".

Oza> 3) in my understanding cross debug would not affect endianess
Oza> because all the record saving done on target memory and played back
Oza> in target memory.  they never get fetched to host machine I think.
Oza> please clarify how would it affect host/target endianness issue ?

Here is a snippet from the patch:

+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
[...]
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Here, this fetches the raw register bits from the cache, which, IIUC,
are in target order.  Then it uses the union to turn this into a scalar,
and does math on the scalar value.

So, if the host and target endianness differ, you will get the wrong
result.

Maybe I am missing something here?

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 18:26                   ` paawan oza
@ 2011-04-28 19:00                     ` Tom Tromey
  2011-04-28 19:22                       ` paawan oza
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
  0 siblings, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-04-28 19:00 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Tom> It seems to me that extract_typed_address or something similar would be
Tom> better.

Oza> 1)  are suggesting to use something else than unions ? whatever you have 
Oza> described about union is right.

Oza> 2)  why could I use extract_typed_address instead of direct assignment ?

extract_typed_address handles endianess and conversion from "array of
bytes" to "host scalar".

Oza> 3) in my understanding cross debug would not affect endianess
Oza> because all the record saving done on target memory and played back
Oza> in target memory.  they never get fetched to host machine I think.
Oza> please clarify how would it affect host/target endianness issue ?

Here is a snippet from the patch:

+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
[...]
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Here, this fetches the raw register bits from the cache, which, IIUC,
are in target order.  Then it uses the union to turn this into a scalar,
and does math on the scalar value.

So, if the host and target endianness differ, you will get the wrong
result.

Maybe I am missing something here?

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-25 19:57                 ` Tom Tromey
@ 2011-04-28 18:26                   ` paawan oza
  2011-04-28 19:00                     ` Tom Tromey
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-04-28 18:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

Hi Tom,

I have implemented all the comments, except one thing I am not sure.

Tom's comments
Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];
There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:
Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
It seems to me that extract_typed_address or something similar would be
better.
I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza's query;

1)  are suggesting to use something else than unions ? whatever you have 
described about union is right.

2)  why could I use extract_typed_address instead of direct assignment ?

3)  in my understanding cross debug would not affect endianess because all the 
record saving done on target memory and played back in target memory.
they never get fetched to host machine I think.
please clarify how would it affect host/target endianness issue ?
I am confused.


Regards,
Oza.















----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb@sourceware.org; 
gdb-patches@sourceware.org
Sent: Tue, April 26, 2011 1:27:17 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate
Oza> xmallocs, but I am not sure whether to go for that macros or leave
Oza> the implementation of reg/mem allcoation scattered across code
Oza> calling xmalloc.

I saw one use of REG_ALLOC and none of MEM_ALLOC.
If you intend to just have a single use it is probably better to just
drop the macros.

But, maybe you intend to use these universally through the code.
That would be fine.

Oza> +  /* Enable process record */

Period plus two spaces at the end of a comment.

Oza> +  set_gdbarch_process_record(gdbarch, arm_process_record);

Space before an open paren.

There are a lot of small formatting problems in this patch.

Oza>  #include "features/arm-with-m.c"

Oza> +
Oza>  static int arm_debug;

Adding a blank line for no reason.

Oza> +/* arm-reversible process reacord data structures.  */

Surely it should be "ARM".

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;
Oza> +    CORE_ADDR addr;
Oza> +};

Wrong formatting.  The struct needs documentation and so do its fields.

Oza> +
Oza> +static int
Oza> +SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)

A new function needs a documentation comment.
Uppercase function names need special pleading.

Oza> +  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));

Likewise locals.

Oza> +static int 
Oza> +arm_handle_data_proc_misc_load_str_insn   \
Oza> +(insn_decode_record *arm_insn_r)

Bad formatting.

Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];

There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:

Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;

It seems to me that extract_typed_address or something similar would be
better.

I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza> +       /* SPSR is going to be changed.  */
Oza> +       /* Oza: FIX ME ? how to read SPSR value?  */

There are a few comments in this style.

First, don't put your name into comments.

Second, I think instead of new "FIXME" comments, new code should either
just work, or call error and have an explanatory comment.


I can't really comment on the details of the implementation.  I don't
know much about either ARM or process record.  It seems basically
reasonable; I prefer a somewhat more symbolic style, but I understand
that the x86 process record code is also written with many manifest
constants.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
@ 2011-04-25 19:57                 ` Tom Tromey
  2011-04-28 18:26                   ` paawan oza
  0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-04-25 19:57 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:

Oza> PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate
Oza> xmallocs, but I am not sure whether to go for that macros or leave
Oza> the implementation of reg/mem allcoation scattered across code
Oza> calling xmalloc.

I saw one use of REG_ALLOC and none of MEM_ALLOC.
If you intend to just have a single use it is probably better to just
drop the macros.

But, maybe you intend to use these universally through the code.
That would be fine.

Oza> +  /* Enable process record */

Period plus two spaces at the end of a comment.

Oza> +  set_gdbarch_process_record(gdbarch, arm_process_record);

Space before an open paren.

There are a lot of small formatting problems in this patch.

Oza>  #include "features/arm-with-m.c"
 
Oza> +
Oza>  static int arm_debug;

Adding a blank line for no reason.

Oza> +/* arm-reversible process reacord data structures.  */

Surely it should be "ARM".

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;
Oza> +    CORE_ADDR addr;
Oza> +};

Wrong formatting.  The struct needs documentation and so do its fields.

Oza> +
Oza> +static int
Oza> +SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)

A new function needs a documentation comment.
Uppercase function names need special pleading.

Oza> +  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));

Likewise locals.

Oza> +static int 
Oza> +arm_handle_data_proc_misc_load_str_insn   \
Oza> +(insn_decode_record *arm_insn_r)

Bad formatting.

Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];

There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:

Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;

It seems to me that extract_typed_address or something similar would be
better.

I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza> +       /* SPSR is going to be changed.  */
Oza> +       /* Oza: FIX ME ? how to read SPSR value?  */

There are a few comments in this style.

First, don't put your name into comments.

Second, I think instead of new "FIXME" comments, new code should either
just work, or call error and have an explanatory comment.


I can't really comment on the details of the implementation.  I don't
know much about either ARM or process record.  It seems basically
reasonable; I prefer a somewhat more symbolic style, but I understand
that the x86 process record code is also written with many manifest
constants.

Tom

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-22  5:49             ` paawan oza
  2011-04-22  5:55               ` oza Pawandeep
@ 2011-04-25 14:03               ` paawan oza
  2011-05-01  1:20                 ` Petr Hluzín
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
  2 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-04-25 14:03 UTC (permalink / raw)
  To: Petr Hluzín, gdb, gdb-patches

Hi Petr,

I have implemented your review comments.

PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate xmallocs, but I am 
not sure whether to go for that macros or
leave the implementation of reg/mem allcoation scattered across code calling 
xmalloc.



PATCH
---------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-25 18:43:44.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record */
+  set_gdbarch_process_record(gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-04-25 18:43:44.000000000 +0530
@@ -54,8 +54,11 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
+
 static int arm_debug;
 
 /* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1706 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
 }
+
+
+
+/* arm-reversible process reacord data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(LENGTH,RECORD_BUF) \
+  do  \
+    { \
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*(LENGTH+1));\
+      arm_insn_r->arm_regs[0] = LENGTH; \
+      while(LENGTH) \
+        { \
+          arm_insn_r->arm_regs[LENGTH] = RECORD_BUF[LENGTH-1];  \
+          LENGTH--;  \
+        } \
+    } \
+while (0)
+
+#define MEM_ALLOC(LENGTH,RECORD_BUF) \
+  do  \
+    { \
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct \
+                              arm_mem_r) * (LENGTH+1)); \
+      arm_insn_r->arm_mems[0].len = LENGTH;  \
+      while(LENGTH) \
+        { \
+          arm_insn_r->arm_mems[LENGTH].addr = RECORD_BUF[(LENGTH * 2) - 1];  \
+          arm_insn_r->arm_mems[LENGTH].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+          LENGTH--;   \
+        } \
+    } \
+  while (0)
+
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+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 accomodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t id;                  /* type of insn.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  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;
+
+
+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;
+}
+
+static int 
+handle_extension_space (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 reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+static int 
+arm_handle_data_proc_misc_load_str_insn   \
+(insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_length=0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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;
+            record_length = 2;
+            REG_ALLOC (record_length, record_buf);
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+           arm_insn_r->arm_regs[0] = 3;
+           arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+           arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+         }        
+      }
+  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 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. 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)
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+          }
+        else
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = reg_dest;
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+          }
+      }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }    
+      else
+      {
+        /* SPSR is going to be changed. */
+        /* Oza: FIX ME ? how to read SPSR value ?  */
+      }
+    }   
+  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 insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+                              arm_mem_r)*2);
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      arm_insn_r->arm_mems[0].len = 1;
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          arm_insn_r->arm_mems[1].len = 4;
+        }
+        else
+        {   
+          /* SWPB insn, swaps only byte.  */
+          arm_insn_r->arm_mems[1].len = 1;
+        }
+      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);    
+    }
+  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.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+        arm_insn_r->arm_regs[0] = 2;
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      }
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?  */
+    }  
+  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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        printf("handling store insn, immed offfset insn\n");
+        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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);  
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 
19);              

+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+    }  
+  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.  */
+      printf("handling CLZ - cunt leading zero insn\n");
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);  
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 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 (((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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         arm_insn_r->arm_regs[0] = 1;
+         arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+       }    
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }   
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*2);
+          arm_insn_r->arm_mems[0].len = 1;
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                arm_insn_r->arm_mems[1].len = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                arm_insn_r->arm_mems[1].len = 1;    
+              break;   
+
+              default:
+                /* rest of the insns are unreachable for this addressing mode.  
*/
+              break;   
+            }       
+          arm_insn_r->arm_mems[1].addr = tgt_mem_addr;    
+          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.  */
+              arm_insn_r->arm_regs = (uint32_t*)xmalloc 
(sizeof(uint32_t)*2);     

+              arm_insn_r->arm_regs[0] = 1;
+              arm_insn_r->arm_regs[1] = reg_src1;    
+            }  
+        }  
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        } 
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+            arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;   
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;   
+              }       
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in pre-indexed mode and 
+                                post-indexed mode as well.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }     
+          }
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  /* unreachable.  */  
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }       
+            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)
+                        xmalloc (sizeof(struct arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;   
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;   
+              }                   
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in register scaled pre-indexed 
+                                mode, and scaled post indexed mode.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }
+          }            
+      }  
+    }
+  return 0;   
+}
+
+static int 
+arm_hamdle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{   
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;       
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is chaging depending on W bit, but as of now we store Rn too wihtout 
going for 

+        optmization.  */
+
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        arm_insn_r->arm_regs[0] = register_count + 2;
+        arm_insn_r->arm_regs[register_count+1] = reg_src1;
+        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+                arm_insn_r->arm_regs[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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[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_buf[0].s_word) - (register_count * 4) + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));   
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        default:
+          /* unreachable.  */    
+        break;    
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+    arm_insn_r->arm_regs[0] = 1;
+    arm_insn_r->arm_regs[1] = reg_src1;
+    }
+  return 0;   
+}
+
+static int 
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  arm_insn_r->arm_regs[0] = 2;
+  arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+  
+  return 0;
+}
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+   return -1;   
+}
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+     
+   return -1;   
+}
+
+
+static int 
+thumb_handle_shift_add_sub_insn (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 reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;   
+}
+
+static int 
+thumb_handle_add_sub_cmp_mov_insn (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 reg_src1 = 0;
+
+
+  union
+  {
+    uint32_t s_word;
+    gdb_byte buf[4];
+  } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_ld_st_reg_offset_insn (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 reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */ 
+      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+      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);           
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = reg_src1;
+        }
+      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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          thumb_insn_r->arm_mems = (struct arm_mem_r *)  \
+                                    xmalloc (sizeof(struct arm_mem_r) * 2);
+          thumb_insn_r->arm_mems[0].len = 1; 
+          thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word; 
+          if (8 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 4;    /* STR (2).  */             
+          else if (10 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 2;    /* STRH (2).  */
+        }                 
+      goto end;
+    }            
+  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);                          

+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+      goto end;
+    }
+    
+  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  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.  */
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          thumb_insn_r->arm_regs[0] = 2;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+          thumb_insn_r->arm_regs[2] = reg_src1;
+        }
+    }
+  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;
+        }
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = reg_src1;
+    }  
+
+  end:
+  return 0;
+}
+
+static int 
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+    }
+
+  return 0;
+}
+
+static int 
+thumb_hamdle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{ 
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 2;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+    }
+  return 0;
+}
+
+static int 
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        thumb_insn_r->arm_regs[0] = register_count + 2;
+        thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+        thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count + 1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+        thumb_insn_r->arm_regs[0] = 1;
+        thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter..  */
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?.  */
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }  
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  
+ 
+  return 0;
+}
+
+static int 
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  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;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
2));
+        thumb_insn_r->arm_regs[0] = register_count + 1;
+        thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count+1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            printf("handling syscall swi insn\n");
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record, 
+        as PC is saved there.  */
+  
+  return 0;
+}
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1=0;
+  uint32_t reg_src1=0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */  
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved 
+        there.  */
+  return 0;     
+}
+
+
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) \
+                                    (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) \
+                                      (insn_decode_record*) = 
+  { 
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      arm_record->id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)? \
+            arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;  
+      arm_record->id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+    }
+  return ret;
+}
+
+/* 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);  
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  uint32_t no_of_rec=0;
+  uint32_t ret=0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }   
+  /* record memories.  */
+  if (arm_record.arm_mems)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+       {
+          if (record_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_arch_list_add_end ())
+    ret = -1;
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-04-25 18:43:44.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified


Regards,
Oza.

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-22  5:49             ` paawan oza
@ 2011-04-22  5:55               ` oza Pawandeep
  2011-04-25 14:03               ` paawan oza
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
  2 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-04-22  5:55 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr,

If you could look at the rest of the code and provide your comments it
would be great too.

Note: I am mallocing regs and mems scattered in the code, planning to
organise it too in some way.

Regards,
Oza.

On Fri, Apr 22, 2011 at 11:19 AM, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr,
>
> Thanks for your comments.
>
> 1) This array is local to the function. If you mark it as static you
> avoid its initialization in each invocation of the function.
>
> Oza: I shall change it.
>
> 2) All the functions are called only from this module (only from this
> function). If you make their arguments type-safe (not void*), you will
> get less code. (And type-safety, obviously.)
>
> Oza: this was leftover; as when I designed initially, I felt I would need any
> type of data.
> but now it is uniform and I can certainly change to arm_record type.
> thanks for pointing that out.
>
> 3) This field points to array of 2 or register_count (which itself
> changes). It might be worth documenting it points to array. (Pointers
> are usually not used for pointer-arithmetics at my job.)
> It is quite difficult to prove that accesses to arm_mems[] are within
> allocated bounds.
> Also some array elements are initialized only partially.
>
> oza: basically both arm_mems and arm_regs point to an array. could be documents
> in code.
> what we do is:
> first find out the registers and memories (where we require length also) in the
> beginning.
> and at the end in process_record just go for recording.
> in both arm_regs and arm_mems;  first array field provides only information
> about how many records are there.
>
> 4) (Usually I add a struct field like debug_arm_mems_count and add
> assertions at appropriate places.)
>
> Oza: can you please elaborate on that as I am not sure on what condition to
> assert ?
>
> Regards,
> Oza.
>
>
>
>
> ----- Original Message ----
> From: Petr Hluzín <petr.hluzin@gmail.com>
> To: paawan oza <paawan1982@yahoo.com>
> Cc: gdb@sourceware.org; gdb-patches@sourceware.org
> Sent: Fri, April 22, 2011 2:25:04 AM
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>
> On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
>> Hi,
>>
>> I am working on phase-3 now.
>> if anybody could please start reviewing phase-2 patch (as this is
>> independent of phase-3 and could be checked in independently too)
>> I may start implementing review comments as and when I get.
>> In Parallel, test cases are also being worked upon.
>> following is the phase-2 patch.
>
> I took a peak and noticed the first points which looked suspicious to me.
> Note: I am just a causal mailing-list observer.
>
>> +
>> +struct arm_mem_r
>> +{
>> +    uint32_t len;
>> +    CORE_ADDR addr;
>> +};
>> +
>> +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 accomodate thumb.  */
>> +  uint32_t cond;                /* condition code.  */
>> +  uint32_t id;                  /* type of insn.  */
>> +  uint32_t opcode;              /* insn opcode.  */
>> +  uint32_t decode;              /* insn decode bits.  */
>> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
>> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */
>
> This field points to array of 2 or register_count (which itself
> changes). It might be worth documenting it points to array. (Pointers
> are usually not used for pointer-arithmetics at my job.)
> It is quite difficult to prove that accesses to arm_mems[] are within
> allocated bounds.
> Also some array elements are initialized only partially.
>
> (Usually I add a struct field like debug_arm_mems_count and add
> assertions at appropriate places.)
>
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>> +{
>> +
>> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
>> instruction.  */
>> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
>> +  {
>> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
>> +      arm_handle_brn_insn,                      /* 101.  */
>> +      arm_handle_coproc_insn,                   /* 110.  */
>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>> +  };
>> +
>> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
>> instruction.  */
>> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =
>
> This array is local to the function. If you mark it as static you
> avoid its initialization in each invocation of the function.
>
>> +  {
>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
>
> Typo, hamdle
>
>> +      thumb_handle_misc_insn,                  /* 101.  */
>> +      thumb_handle_swi_insn,                   /* 110.  */
>> +      thumb_handle_branch_insn                 /* 111.  */
>> +  };
>
> All the functions are called only from this module (only from this
> function). If you make their arguments type-safe (not void*), you will
> get less code. (And type-safety, obviously.)
>
> There might be more, I just picked the first thing. I am not familiar
> with the code base.
>
> --
> Petr Hluzin
>
>

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-21 20:55           ` Petr Hluzín
@ 2011-04-22  5:49             ` paawan oza
  2011-04-22  5:55               ` oza Pawandeep
                                 ` (2 more replies)
  0 siblings, 3 replies; 128+ messages in thread
From: paawan oza @ 2011-04-22  5:49 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr,

Thanks for your comments.

1) This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

Oza: I shall change it.

2) All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

Oza: this was leftover; as when I designed initially, I felt I would need any 
type of data.
but now it is uniform and I can certainly change to arm_record type.
thanks for pointing that out.

3) This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

oza: basically both arm_mems and arm_regs point to an array. could be documents 
in code.
what we do is:
first find out the registers and memories (where we require length also) in the 
beginning.
and at the end in process_record just go for recording.
in both arm_regs and arm_mems;  first array field provides only information 
about how many records are there.

4) (Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

Oza: can you please elaborate on that as I am not sure on what condition to 
assert ?

Regards,
Oza.




----- Original Message ----
From: Petr Hluzín <petr.hluzin@gmail.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb@sourceware.org; gdb-patches@sourceware.org
Sent: Fri, April 22, 2011 2:25:04 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
> Hi,
>
> I am working on phase-3 now.
> if anybody could please start reviewing phase-2 patch (as this is
> independent of phase-3 and could be checked in independently too)
> I may start implementing review comments as and when I get.
> In Parallel, test cases are also being worked upon.
> following is the phase-2 patch.

I took a peak and noticed the first points which looked suspicious to me.
Note: I am just a causal mailing-list observer.

> +
> +struct arm_mem_r
> +{
> +    uint32_t len;
> +    CORE_ADDR addr;
> +};
> +
> +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 accomodate thumb.  */
> +  uint32_t cond;                /* condition code.  */
> +  uint32_t id;                  /* type of insn.  */
> +  uint32_t opcode;              /* insn opcode.  */
> +  uint32_t decode;              /* insn decode bits.  */
> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */

This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

(Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
> +  {
> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */
> +  };
> +
> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction.  */
> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =

This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

> +  {
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */

Typo, hamdle

> +      thumb_handle_misc_insn,                  /* 101.  */
> +      thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */
> +  };

All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

There might be more, I just picked the first thing. I am not familiar
with the code base.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-20 19:16         ` [PATCH] arm reversible : <phase_2_complete> paawan oza
@ 2011-04-21 20:55           ` Petr Hluzín
  2011-04-22  5:49             ` paawan oza
  0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-04-21 20:55 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb, gdb-patches

On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
> Hi,
>
> I am working on phase-3 now.
> if anybody could please start reviewing phase-2 patch (as this is
> independent of phase-3 and could be checked in independently too)
> I may start implementing review comments as and when I get.
> In Parallel, test cases are also being worked upon.
> following is the phase-2 patch.

I took a peak and noticed the first points which looked suspicious to me.
Note: I am just a causal mailing-list observer.

> +
> +struct arm_mem_r
> +{
> +    uint32_t len;
> +    CORE_ADDR addr;
> +};
> +
> +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 accomodate thumb.  */
> +  uint32_t cond;                /* condition code.  */
> +  uint32_t id;                  /* type of insn.  */
> +  uint32_t opcode;              /* insn opcode.  */
> +  uint32_t decode;              /* insn decode bits.  */
> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */

This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

(Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
> +  {
> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */
> +  };
> +
> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction.  */
> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =

This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

> +  {
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */

Typo, hamdle

> +      thumb_handle_misc_insn,                  /* 101.  */
> +      thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */
> +  };

All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

There might be more, I just picked the first thing. I am not familiar
with the code base.

-- 
Petr Hluzin

^ permalink raw reply	[flat|nested] 128+ messages in thread

* [PATCH] arm reversible : <phase_2_complete>
  2011-04-16 21:03       ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
@ 2011-04-20 19:16         ` paawan oza
  2011-04-21 20:55           ` Petr Hluzín
  0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-04-20 19:16 UTC (permalink / raw)
  To: gdb, gdb-patches

Hi,

I am working on phase-3 now.
if anybody could please start reviewing phase-2 patch (as this is
independent of phase-3 and could be checked in independently too)
I may start implementing review comments as and when I get.
In Parallel, test cases are also being worked upon.
following is the phase-2 patch.

PATCH STARTS.

------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

+  /* Enable process record */
+  set_gdbarch_process_record(gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@


   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
}

/* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -54,8 +54,11 @@
#include "gdb_assert.h"
#include "vec.h"

+#include "record.h"
+
#include "features/arm-with-m.c"

+
static int arm_debug;

/* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1692 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
}
+
+
+
+/* arm-reversible process reacord data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+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 accomodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t id;                  /* type of insn.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  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;
+
+
+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;
+}
+
+static int 
+handle_extension_space (insn_decode_record *arm_record)
+{
+  insn_decode_record *arm_insn_r = arm_record;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+    
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+static int 
+arm_handle_data_proc_misc_load_str_insn (void *data)
+{
+
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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.  */
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+           arm_insn_r->arm_regs[0] = 3;
+           arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+           arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+         }        
+      }
+  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 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. 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)
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+          }
+        else
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = reg_dest;
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+          }
+      }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }    
+      else
+      {
+        /* SPSR is going to be changed. */
+        /* Oza: FIX ME ? how to read SPSR value ?  */
+      }
+    }  
+  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 insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+                              arm_mem_r)*2);
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      arm_insn_r->arm_mems[0].len = 1;
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          arm_insn_r->arm_mems[1].len = 4;
+        }
+        else
+        {  
+          /* SWPB insn, swaps only byte.  */
+          arm_insn_r->arm_mems[1].len = 1;
+        }
+      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);    
+    }
+  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.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+        arm_insn_r->arm_regs[0] = 2;
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      }
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?  */
+    }  
+  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) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        printf("handling store insn, immed offfset insn\n");
+        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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);  
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 
19);              

+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+    }  
+  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.  */
+      printf("handling CLZ - count leading zero insn\n");
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);  
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_data_proc_imm_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  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;
+
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         arm_insn_r->arm_regs[0] = 1;
+         arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+       }    
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }  
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {  
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*2);
+          arm_insn_r->arm_mems[0].len = 1;
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:  
+              case 13:  
+              case 1:  
+              case 5:              
+                /* STR insn, STRT insn.  */
+                arm_insn_r->arm_mems[1].len = 4;    
+              break;  
+
+              case 10:
+              case 14:            
+              case 11:  
+              case 15:  
+              case 3:  
+              case 7:  
+                /* STRB insn, STRBT insn.  */
+                arm_insn_r->arm_mems[1].len = 1;    
+              break;  
+
+              default:
+                /* rest of the insns are unreachable for this addressing mode.  

*/
+              break;  
+            }      
+          arm_insn_r->arm_mems[1].addr = tgt_mem_addr;    
+          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.  */
+              arm_insn_r->arm_regs = (uint32_t*)xmalloc 
(sizeof(uint32_t)*2);    

+              arm_insn_r->arm_regs[0] = 1;
+              arm_insn_r->arm_regs[1] = reg_src1;    
+            }  
+        }  
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        } 
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+            arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:  
+                case 13:  
+                case 1:  
+                case 5:              
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;  
+
+                case 10:
+                case 14:            
+                case 11:  
+                case 15:  
+                case 3:  
+                case 7:  
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;  
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;  
+              }      
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in pre-indexed mode and 
+                                post-indexed mode as well.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }    
+          }
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);  
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  /* unreachable.  */  
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }      
+            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)
+                        xmalloc (sizeof(struct arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:  
+                case 13:  
+                case 1:  
+                case 5:              
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;  
+
+                case 10:
+                case 14:            
+                case 11:  
+                case 15:  
+                case 3:  
+                case 7:  
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;  
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;  
+              }                  
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in register scaled pre-indexed 
+                                mode, and scaled post indexed mode.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }
+          }            
+      }  
+    }
+  return 0;  
+}
+
+static int 
+arm_hamdle_ld_st_multiple_insn (void *data)
+{  
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;      
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is chaging depending on W bit, but as of now we store Rn too wihtout 

going for 

+        optmization.  */
+
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        arm_insn_r->arm_regs[0] = register_count + 2;
+        arm_insn_r->arm_regs[register_count+1] = reg_src1;
+        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+                arm_insn_r->arm_regs[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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[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_buf[0].s_word) - (register_count * 4) + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));  
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        default:
+          /* unreachable.  */    
+        break;    
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+    arm_insn_r->arm_regs[0] = 1;
+    arm_insn_r->arm_regs[1] = reg_src1;
+    }
+  return 0;  
+}
+
+static int 
+arm_handle_brn_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data; 
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  arm_insn_r->arm_regs[0] = 2;
+  arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+  
+  return 0;
+}
+
+static int 
+arm_handle_coproc_insn (void *data)
+{
+   return -1;  
+}
+
+static int 
+arm_handle_coproc_data_proc_insn (void *data)
+{
+
+   insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+  
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+    
+   return -1;  
+}
+
+
+static int 
+thumb_handle_shift_add_sub_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (  thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_add_sub_cmp_mov_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+  {
+    uint32_t s_word;
+    gdb_byte buf[4];
+  } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */ 
+      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+      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);          
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = reg_src1;
+        }
+      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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          thumb_insn_r->arm_mems = (struct arm_mem_r *)  \
+                                    xmalloc (sizeof(struct arm_mem_r) * 2);
+          thumb_insn_r->arm_mems[0].len = 1; 
+          thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word; 
+          if (8 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 4;    /* STR (2).  */            
+          else if (10 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 2;    /* STRH (2).  */
+        }                
+      goto end;
+    }            
+  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);                          


+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+      goto end;
+    }
+    
+  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  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.  */
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          thumb_insn_r->arm_regs[0] = 2;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+          thumb_insn_r->arm_regs[2] = reg_src1;
+        }
+    }
+  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;
+        }
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = reg_src1;
+    }  
+
+  end:
+  return 0;
+}
+
+static int 
+thumb_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+    }
+
+  return 0;
+}
+
+static int 
+thumb_hamdle_ld_st_stack_insn (void *data)
+{ 
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 2;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+    }
+  return 0;
+}
+
+static int 
+thumb_handle_misc_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        thumb_insn_r->arm_regs[0] = register_count + 2;
+        thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+        thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count + 1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+        thumb_insn_r->arm_regs[0] = 1;
+        thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter..  */
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?.  */
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }  
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  
+ 
+  return 0;
+}
+
+static int 
+thumb_handle_swi_insn (void *data)                
+{
+
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  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;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
2));
+        thumb_insn_r->arm_regs[0] = register_count + 1;
+        thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count+1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            printf("handling syscall swi insn\n");
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record, 
+        as PC is saved there.  */
+  
+  return 0;
+}
+
+static int 
+thumb_handle_branch_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1=0;
+  uint32_t reg_src1=0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */  
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved 
+        there.  */
+  return 0;    
+}
+
+
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) = 
+  { 
+      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) = 
+  { 
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      arm_record->id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)? \
+            arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;  
+      arm_record->id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+    }
+  return ret;
+}
+
+/* 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);  
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  uint32_t no_of_rec=0;
+  uint32_t ret=0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }  
+  /* record memories.  */
+  if (arm_record.arm_mems)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+       {
+          if (record_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_arch_list_add_end ())
+    ret = -1;
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-04-15 13:11:15.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
};

/* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
/* Functions exported from armbsd-tdep.h.  */

/* Return the appropriate register set for the core section identified

^ permalink raw reply	[flat|nested] 128+ messages in thread

* [PATCH] arm reversible <phase_2_complete>
@ 2011-04-20 19:10 oza Pawandeep
  0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-04-20 19:10 UTC (permalink / raw)
  To: gdb-patches, gdb

Hi,

I am working on phase-3 now.
if anybody could please start reviewing phase-2 patch (as this is
independent of phase-3 and could be checked in independently too)
I may start implementing review comments as and when I get.
In Parallel, test cases are also being worked upon.
following is the phase-2 patch.

PATCH STARTS.
------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -998,6 +998,9 @@
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                             svr4_fetch_objfile_link_map);

+  /* Enable process record */
+  set_gdbarch_process_record(gdbarch, arm_process_record);
+
  tramp_frame_prepend_unwinder (gdbarch,
                &arm_linux_sigreturn_tramp_frame);
  tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@


  tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }

 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -54,8 +54,11 @@
 #include "gdb_assert.h"
 #include "vec.h"

+#include "record.h"
+
 #include "features/arm-with-m.c"

+
 static int arm_debug;

 /* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1692 @@
               NULL, /* FIXME: i18n: "ARM debugging is %s.  */
               &setdebuglist, &showdebuglist);
 }
+
+
+
+/* arm-reversible process reacord data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+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 accomodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t id;                  /* type of insn.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  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;
+
+
+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;
+}
+
+static int
+handle_extension_space (insn_decode_record *arm_record)
+{
+  insn_decode_record *arm_insn_r = arm_record;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+static int
+arm_handle_data_proc_misc_load_str_insn (void *data)
+{
+
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  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;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  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.  */
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+           arm_insn_r->arm_regs[0] = 3;
+           arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+           arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;
+         }
+      }
+  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 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. 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)
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+          }
+        else
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = reg_dest;
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+          }
+      }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+      {
+        /* SPSR is going to be changed. */
+        /* Oza: FIX ME ? how to read SPSR value ?  */
+      }
+    }
+  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 insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+                              arm_mem_r)*2);
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      arm_insn_r->arm_mems[0].len = 1;
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          arm_insn_r->arm_mems[1].len = 4;
+        }
+        else
+        {
+          /* SWPB insn, swaps only byte.  */
+          arm_insn_r->arm_mems[1].len = 1;
+        }
+      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  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.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+        arm_insn_r->arm_regs[0] = 2;
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      }
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in
+               that case, we need to go back with previous CPSR and
+               Program Counter.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?  */
+    }
+  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)
+           let us begin according to addressing modes for store insns
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        printf("handling store insn, immed offfset insn\n");
+        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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].buf[0]);

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    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);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+      }
+    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);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16,
19);

+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+    }
+  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.  */
+      printf("handling CLZ - count leading zero insn\n");
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  /* following is always true, in case none of the above conditions meet, it
will fall here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+    }
+  return 0;
+}
+
+static int
+arm_handle_data_proc_imm_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  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;
+
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         arm_insn_r->arm_regs[0] = 1;
+         arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+       }
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }
+  /* following is always true, in case none of the above conditions meet, it
will fall

+        here.  */
+  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.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+    }
+  return 0;
+}
+
+static int
+arm_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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 (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (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))
+        {
+          /* 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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+          arm_mem_r)*2);
+          arm_insn_r->arm_mems[0].len = 1;
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:
+              case 9:
+              case 13:
+              case 1:
+              case 5:
+                /* STR insn, STRT insn.  */
+                arm_insn_r->arm_mems[1].len = 4;
+              break;
+
+              case 10:
+              case 14:
+              case 11:
+              case 15:
+              case 3:
+              case 7:
+                /* STRB insn, STRBT insn.  */
+                arm_insn_r->arm_mems[1].len = 1;
+              break;
+
+              default:
+                /* rest of the insns are unreachable for this addressing mode.
*/
+              break;
+            }
+          arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+          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.  */
+              arm_insn_r->arm_regs = (uint32_t*)xmalloc
(sizeof(uint32_t)*2);

+              arm_insn_r->arm_regs[0] = 1;
+              arm_insn_r->arm_regs[1] = reg_src1;
+            }
+        }
+    }
+  return 0;
+}
+
+static int
+arm_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  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 immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  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,
+        let us begin 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)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+        }
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (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))
+      {
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].buf[0]);

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }
+            arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+            arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:
+                case 9:
+                case 13:
+                case 1:
+                case 5:
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;
+                break;
+
+                case 10:
+                case 14:
+                case 11:
+                case 15:
+                case 3:
+                case 7:
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;
+                break;
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;
+              }
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in pre-indexed mode and
+                                post-indexed mode as well.  */
+                arm_insn_r->arm_regs[1] = reg_src2;
+              }
+          }
+        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);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm;
+                break;
+
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;
+
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word <<
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  /* unreachable.  */
+                break;
+              }
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }
+
+            arm_insn_r->arm_mems = (struct arm_mem_r *)
+                        xmalloc (sizeof(struct arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:
+                case 9:
+                case 13:
+                case 1:
+                case 5:
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;
+                break;
+
+                case 10:
+                case 14:
+                case 11:
+                case 15:
+                case 3:
+                case 7:
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;
+                break;
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;
+              }
+            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))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in register scaled pre-indexed
+                                mode, and scaled post indexed mode.  */
+                arm_insn_r->arm_regs[1] = reg_src2;
+              }
+          }
+      }
+    }
+  return 0;
+}
+
+static int
+arm_hamdle_ld_st_multiple_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is chaging depending on W bit, but as of now we store Rn too wihtout
going for

+        optmization.  */
+
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* 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 optmization.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count +
3));
+        arm_insn_r->arm_regs[0] = register_count + 2;
+        arm_insn_r->arm_regs[register_count+1] = reg_src1;
+        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+                arm_insn_r->arm_regs[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);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[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_buf[0].s_word) - (register_count * 4) + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;
+
+        /* Decrement before.  */
+        case 2:
+
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;
+
+        default:
+          /* unreachable.  */
+        break;
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+    arm_insn_r->arm_regs[0] = 1;
+    arm_insn_r->arm_regs[1] = reg_src1;
+    }
+  return 0;
+}
+
+static int
+arm_handle_brn_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register,
+        CSPR for the insn which changes T bit.  */
+  arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  arm_insn_r->arm_regs[0] = 2;
+  arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  return 0;
+}
+
+static int
+arm_handle_coproc_insn (void *data)
+{
+   return -1;
+}
+
+static int
+arm_handle_coproc_data_proc_insn (void *data)
+{
+
+   insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* 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)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+
+   return -1;
+}
+
+
+static int
+thumb_handle_shift_add_sub_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (  thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;
+}
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+  {
+    uint32_t s_word;
+    gdb_byte buf[4];
+  } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;
+}
+
+static int
+thumb_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */
+      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+      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);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = reg_src1;
+        }
+      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);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          thumb_insn_r->arm_mems = (struct arm_mem_r *)  \
+                                    xmalloc (sizeof(struct arm_mem_r) * 2);
+          thumb_insn_r->arm_mems[0].len = 1;
+          thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word;
+          if (8 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 4;    /* STR (2).  */
+          else if (10 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 2;    /* STRH (2).  */
+        }
+      goto end;
+    }
+  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);

+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+      goto end;
+    }
+
+  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  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.  */
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          thumb_insn_r->arm_regs[0] = 2;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+          thumb_insn_r->arm_regs[2] = reg_src1;
+        }
+    }
+  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;
+        }
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = reg_src1;
+    }
+
+  end:
+  return 0;
+}
+
+static int
+thumb_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+    }
+
+  return 0;
+}
+
+static int
+thumb_hamdle_ld_st_stack_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+    }
+  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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 2;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+    }
+  return 0;
+}
+
+static int
+thumb_handle_misc_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count +
3));
+        thumb_insn_r->arm_regs[0] = register_count + 2;
+        thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+        thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+      arm_mem_r)*(register_count + 1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+        thumb_insn_r->arm_regs[0] = 1;
+        thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  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.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in
+               that case, we need to go back with previous CPSR and
+               Program Counter..  */
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?.  */
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+
+
+  return 0;
+}
+
+static int
+thumb_handle_swi_insn (void *data)
+{
+
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+  uint32_t reg_val1 = 0;
+  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;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  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;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count +
2));
+        thumb_insn_r->arm_regs[0] = register_count + 1;
+        thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[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);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+      arm_mem_r)*(register_count+1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            printf("handling syscall swi insn\n");
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record,
+        as PC is saved there.  */
+
+  return 0;
+}
+
+static int
+thumb_handle_branch_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+  uint32_t reg_val1=0;
+  uint32_t reg_src1=0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved
+        there.  */
+  return 0;
+}
+
+
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction.  */
+  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
+  {
+      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
+      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */
+  };
+
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction.  */
+  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =
+  {
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
+      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0;
+
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], 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_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+      arm_record->id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)? \
+            arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+            handle_extension_space(arm_record);
+    }
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+    }
+  return ret;
+}
+
+/* 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);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  uint32_t no_of_rec=0;
+  uint32_t ret=0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  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));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+    }
+
+  /* record registers.  */
+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }
+  /* record memories.  */
+  if (arm_record.arm_mems)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+       {
+          if (record_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_arch_list_add_end ())
+    ret = -1;
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+
+  return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-04-15 13:11:15.000000000 +0530
@@ -200,6 +200,9 @@
  /* Return the expected next PC if FRAME is stopped at a syscall
     instruction.  */
  CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };

 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                      struct displaced_step_closure *,
                      CORE_ADDR, CORE_ADDR, struct regcache *);

+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */

 /* Return the appropriate register set for the core section identified


----- Original Message ----
From: Yao Qi <yao@codesourcery.com>
To: gdb@sourceware.org
Sent: Mon, April 11, 2011 8:35:42 AM
Subject: Re: [PATCH] arm reversible : progress <phase_2_complete>

On 04/10/2011 05:41 PM, paawan oza wrote:
> Hi,
>
> phase2 (both arm and thumb insn implemenation is complete)
>
> Hi Tom:
> I have taken care of most of your comments: but could nit incorporate numercial
>
> to be replaced by some meaningful symbolic names.
> as I dont know what sort of symbolic names are approproate.
>
>

This one looks much better than previous ones.  Thanks for working on
this.  I am not the people to approve this patch.  Some of my cents below.

> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define NO_OF_TYPE_OF_ARM_INSNS 8
> +#define NO_OF_TYPE_OF_THUMB_INSNS 8
> +
> +#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
> +    record_arch_list_add_reg (arm_record.regcache, regnum)
> +
> +#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
> +
> +#define IS_IT_ARM_INSN(X) ((X & 0x00000020) >> 5)
> +#define ARM_PARSE_INSN(X,BIT_POS,NO_OF_BITS) \
> +                ((X >> (BIT_POS-1)) & (0xFFFFFFFF >> ((sizeof(uint32_t)*8) -
\
> +                  NO_OF_BITS)))


There are some existing macros you can use for parsing instructions.

/* Support routines for instruction parsing.  */
#define submask(x) ((1L << ((x) + 1)) - 1)
#define bit(obj,st) (((obj) >> (st)) & 1)
#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
#define sbits(obj,st,fn) \
 ((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))

> +
> +#define INSN_S_L_BIT_NUM 21
> +#define ARM_BIT_SET(X, NUM) (((X >> (NUM-1)) & 0x00000001) == 1)
> +#define GET_BIT(X, NUM) (((X >> (NUM-1)) & 0x00000001))
> +

GET_BIT can be replaced by `bit' I posted above.

> +
> +static int
> +handle_extension_space (insn_decode_record *arm_record)
> +{
> +  insn_decode_record *arm_insn_r = arm_record;
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> +  struct regcache *reg_cache = arm_insn_r->regcache;
> +
> +  uint32_t reg_src1 = 0, reg_src2 = 0;
> +  uint32_t opcode1 = 0, opcode2 = 0;
> +
> +  opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,26,3);
> +  if ((3 == opcode1) && ARM_BIT_SET(arm_insn_r->arm_insn,5))
> +    {
> +      /* undefined instruction on ARM V5; need to handle if later versions
> +          define it.  */
> +    }
> +
> +  opcode2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
> +
> +  if ((!opcode1) && (9 == opcode2))
> +    {
> +      /* handle arithmetic insn extension space.  */
> +    }
> +
> +  opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,27,2);
                                                  ^  ^
You need an extra space after each comma.

> +  opcode2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,2);
> +
> +  if ((!opcode1) && (2 == opcode2) && !ARM_BIT_SET(arm_insn_r->arm_insn,21))
> +    {
> +      /* handle control insn extension space.  */
> +    }
> +
> +  opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,26,3);
> +  if ((!opcode1) && (ARM_BIT_SET(arm_insn_r->arm_insn,8)) \
> +                 && (ARM_BIT_SET(arm_insn_r->arm_insn,5)))
> +    {
> +      /* handle load/store insn extension space.  */
> +    }
> +
> +  opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,5);
> +  if ((24 == opcode1) && ARM_BIT_SET(arm_insn_r->arm_insn,22))
> +    {
> +      /* handle coprocessor insn extension space.  */
> +    }
> +
> +  /* to be done for ARMv5 and later; as of now we return -1.  */
> +  return -1;
> +}
> +

> +
> +/* 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);
> +  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  uint32_t no_of_rec=0;
> +  uint32_t ret=0;
> +
> +  union
> +    {
> +      uint32_t s_word;
> +      gdb_byte buf[4];
> +    } u_buf;
> +
> +  insn_decode_record arm_record;
> +  memset (&u_buf, 0, sizeof(u_buf));
> +
> +  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));
> +    }
> +
> +  /* check the insn, whether it is thumb or arm one.  */
> +  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
> +  arm_record.cond = ARM_PARSE_INSN (arm_record.arm_insn,29,4);
> +
> +  if (!IS_IT_ARM_INSN (u_buf.s_word))

Please reference to `arm_frame_is_thumb' or `displaced_in_arm_mode' to
see how to check ARM mode or Thumb mode.

> +    {
> +      /* we are decoding arm insn.  */
> +      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> +    }
> +  else
> +    {
> +      /* we are decoding thumb insn.  */
> +      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);

On some ARM arch, there are 32-bit Thumb instructions, called Thumb-2.
Do you plan to support Thumb-2 insn?

> +    }
> +
> +  /* record registers.  */
> +  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
> +  if (arm_record.arm_regs)
> +    {
> +      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
> +        {
> +          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
> +          ret = -1;
> +        }
> +    }
> +  /* record memories.  */
> +  if (arm_record.arm_mems)
> +    {
> +      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
> +       {
> +          if (record_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_arch_list_add_end ())
> +    ret = -1;
> +
> +  if (arm_record.arm_regs)
> +    xfree (arm_record.arm_regs);
> +  if (arm_record.arm_mems)
> +    xfree (arm_record.arm_mems);
> +
> +  return ret;
> +}

--
Yao (齐尧)

^ permalink raw reply	[flat|nested] 128+ messages in thread

end of thread, other threads:[~2012-03-13  5:41 UTC | newest]

Thread overview: 128+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-29 15:38 [PATCH] arm reversible : <phase_2_complete> paawan oza
2011-05-31 18:05 ` Tom Tromey
2011-06-03  7:44   ` paawan oza
2011-06-03  7:51   ` paawan oza
2011-07-12 21:10     ` Tom Tromey
2011-07-13  3:17       ` chandra krishnappa
2011-07-13  5:36         ` paawan oza
2011-07-13 15:20         ` Tom Tromey
2011-07-14  4:49           ` chandra krishnappa
2011-07-14 15:01             ` Yao Qi
2011-07-13  6:57       ` paawan oza
     [not found]       ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
2011-09-19  7:37         ` paawan oza
2011-09-22 17:12           ` oza Pawandeep
2011-09-27  6:52             ` oza Pawandeep
2011-10-06 18:01               ` oza Pawandeep
     [not found]                 ` <CAK1A=4xuUT++WRzdUnZc0KodYF0AiukUyJa7Pr=wzb4i-OQ5eQ@mail.gmail.com>
2011-10-08  2:50                   ` Fwd: " paawan oza
2011-10-11 18:11                     ` [PATCH] arm reversible : <phase_2_complete> how to go ahead ? paawan oza
2011-10-11 19:02                       ` Tom Tromey
2011-10-14 20:13           ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
2011-10-15  3:46             ` paawan oza
2011-10-15  7:01               ` chandra krishnappa
2011-10-15  9:32               ` Yao Qi
2011-10-15 13:33                 ` Yao Qi
2011-10-15 16:34                   ` oza Pawandeep
2011-10-15 17:38                     ` oza Pawandeep
2011-10-16  8:00                       ` oza Pawandeep
2011-10-16  8:44                         ` oza Pawandeep
2011-10-17  4:25                         ` Yao Qi
2011-10-17  3:18                     ` Yao Qi
2011-10-17  4:28                       ` oza Pawandeep
2011-10-17 15:42                         ` chandra krishnappa
2011-11-03 17:10                 ` Tom Tromey
2011-11-04 16:27                   ` Yao Qi
2011-10-16 23:32               ` Petr Hluzín
2011-10-22 15:42                 ` oza Pawandeep
2011-10-23 10:17                   ` oza Pawandeep
2011-10-24  7:43                     ` Petr Hluzín
2011-10-25  7:20                     ` Yao Qi
2011-11-03 17:41                     ` Tom Tromey
2011-11-05 17:36                       ` Petr Hluzín
2011-11-03 17:38                 ` Tom Tromey
2011-11-05 17:35                   ` Petr Hluzín
2011-11-07 15:39                     ` Tom Tromey
2011-11-08  6:02                       ` oza Pawandeep
2011-11-08 10:17                         ` Yao Qi
2011-11-08 10:45                           ` oza Pawandeep
2011-11-09  5:28                         ` oza Pawandeep
2011-11-09  6:08                           ` oza Pawandeep
2011-11-17  9:24                             ` oza Pawandeep
2011-11-17  9:52                               ` Yao Qi
2011-11-17 20:40                             ` Tom Tromey
2011-11-18  3:18                               ` oza Pawandeep
2011-11-18 17:22                                 ` Tom Tromey
2011-11-19  9:43                               ` oza Pawandeep
2011-11-19 11:39                                 ` oza Pawandeep
2011-12-02 18:36                                   ` Tom Tromey
2011-12-03  8:20                                     ` oza Pawandeep
2011-12-03 14:18                                       ` oza Pawandeep
2011-12-03 16:32                                         ` Petr Hluzín
2011-12-03 18:46                                           ` oza Pawandeep
2011-12-03 19:02                                             ` oza Pawandeep
2011-12-03 20:30                                               ` Petr Hluzín
     [not found]                                                 ` <1322975560.12415.YahooMailNeo@web112518.mail.gq1.yahoo.com>
2011-12-04  7:09                                                   ` paawan oza
2011-12-04  1:47                                               ` Yao Qi
2011-12-04  8:26                                                 ` oza Pawandeep
2011-12-04 11:33                                                   ` oza Pawandeep
2011-12-04 13:29                                                     ` Petr Hluzín
2011-12-04 14:46                                                     ` Yao Qi
2011-12-04 17:00                                                       ` oza Pawandeep
2011-12-04 23:46                                                         ` Yao Qi
2011-12-05  5:35                                                           ` oza Pawandeep
2011-12-05  8:12                                                             ` Yao Qi
2011-12-05 16:02                                                               ` oza Pawandeep
2011-12-19  6:26                                                                 ` oza Pawandeep
2011-12-20 19:11                                                                 ` Tom Tromey
2011-12-28 12:43                                                                   ` oza Pawandeep
2012-01-05 11:01                                                                     ` oza Pawandeep
2012-01-05 12:03                                                                       ` Eli Zaretskii
2012-01-05 16:17                                                                       ` Tom Tromey
2012-01-05 18:17                                                                         ` oza Pawandeep
2012-01-06  8:06                                                                           ` oza Pawandeep
2012-01-06 19:13                                                                             ` Tom Tromey
2012-01-07  6:31                                                                               ` oza Pawandeep
2012-01-09 16:25                                                                                 ` Tom Tromey
2012-02-02  6:29                                                                                   ` oza Pawandeep
     [not found]                                                                                     ` <m38vkfoiut.fsf@fleche.redhat.com>
     [not found]                                                                                       ` <CAK1A=4xrUBzcG1i7NHyEtmAjwx0nbYmkePFS9_kQcS3E1gaduA@mail.gmail.com>
     [not found]                                                                                         ` <m3haz19ezl.fsf@fleche.redhat.com>
     [not found]                                                                                           ` <CAK1A=4w+yq9AvRMukPcKpZnGjrVnPbE3zdScwRd1Skubt0KHWA@mail.gmail.com>
2012-03-07  5:35                                                                                             ` oza Pawandeep
2012-03-08 16:32                                                                                               ` Tom Tromey
2012-03-09  9:30                                                                                                 ` oza Pawandeep
2012-03-09 16:47                                                                                                   ` Tom Tromey
2012-03-12  6:23                                                                                                     ` oza Pawandeep
2012-03-12  6:55                                                                                                       ` Yao Qi
2012-03-12  9:14                                                                                                         ` oza Pawandeep
2012-03-12 15:32                                                                                                           ` oza Pawandeep
2012-03-12 19:43                                                                                                             ` Tom Tromey
2012-03-13  5:41                                                                                                               ` oza Pawandeep
2011-12-03 15:06                                       ` oza Pawandeep
2011-12-20 19:05                                       ` Tom Tromey
  -- strict thread matches above, loose matches on Subject: below --
2011-08-10 17:09 chandra krishnappa
2011-08-11  1:34 ` Yao Qi
     [not found] <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>
2011-06-06 17:42 ` chandra krishnappa
2011-07-05  8:47   ` oza Pawandeep
2011-05-24  7:19 paawan oza
     [not found] <341905.10459.qm@web112513.mail.gq1.yahoo.com>
     [not found] ` <m3d3m8xdf7.fsf@fleche.redhat.com>
     [not found]   ` <208397.95006.qm@web112517.mail.gq1.yahoo.com>
     [not found]     ` <4DA27006.1080607@codesourcery.com>
2011-04-16 21:03       ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
2011-04-20 19:16         ` [PATCH] arm reversible : <phase_2_complete> paawan oza
2011-04-21 20:55           ` Petr Hluzín
2011-04-22  5:49             ` paawan oza
2011-04-22  5:55               ` oza Pawandeep
2011-04-25 14:03               ` paawan oza
2011-05-01  1:20                 ` Petr Hluzín
2011-05-02 14:47                   ` Tom Tromey
2011-05-04 21:33                     ` Petr Hluzín
2011-05-05 15:29                       ` Tom Tromey
2011-05-07 13:50                   ` paawan oza
2011-05-09 14:57                     ` Tom Tromey
2011-05-10  5:42                       ` paawan oza
2011-05-10 15:37                         ` Tom Tromey
2011-05-12  5:06                           ` paawan oza
2011-05-10  5:50                       ` paawan oza
2011-05-12 21:21                     ` Petr Hluzín
2011-05-24  6:44                       ` paawan oza
2011-05-07 13:56                   ` paawan oza
     [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
2011-04-25 19:57                 ` Tom Tromey
2011-04-28 18:26                   ` paawan oza
2011-04-28 19:00                     ` Tom Tromey
2011-04-28 19:22                       ` paawan oza
     [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
2011-04-28 19:36                         ` Tom Tromey
2011-04-30 16:16                           ` paawan oza
2011-05-02 13:28                             ` Tom Tromey
2011-04-20 19:10 [PATCH] arm reversible <phase_2_complete> oza Pawandeep

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).