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-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
[parent not found: <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>]
* 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
[parent not found: <341905.10459.qm@web112513.mail.gq1.yahoo.com>]
* [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).