Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
@ 2011-03-03  4:08 paawan oza
  2011-03-03 18:32 ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-03-03  4:08 UTC (permalink / raw)
  To: gdb

Hi,

I am done with the deisng for both thumb and arm framework.
coding guidelines are improved.

having some doubts as of now.

1) what is the API to read arm coprocessor registers ?
2) how to read SPSR value ?
3) there are couple of FIX me in code.

PS: patch progress is posted below. phase 3 will include thumb insn decoding 
part.phase 4 will include arm-linux ABI part.

PATCH STARTS
------------------------------------
diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c
--- arm_new/arm-linux-tdep.c    2011-03-03 09:15:59.000000000 +0530
+++ arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
@@ -998,9 +998,6 @@
   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,
diff -urN arm_new/arm-tdep.c arm_orig/arm-tdep.c
--- arm_new/arm-tdep.c    2011-03-03 09:15:59.000000000 +0530
+++ arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
@@ -54,11 +54,8 @@
 #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
@@ -7932,1168 +7929,3 @@
                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 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 & 0x00000010) >> 4)
-#define ARM_PARSE_INSN(X,BIT_POS,NO_OF_BITS) \
-                ((X >> (BIT_POS-1)) & (0xFFFFFFFF >> ((sizeof(uint32_t)*8) - \
-                  NO_OF_BITS)))
-
-#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))
-
-
-
-int arm_handle_data_proc_misc_load_str_insn (void*);
-int arm_handle_data_proc_misc_load_str_insn (void*);
-int arm_handle_data_proc_imm_insn (void*);
-int arm_handle_ld_st_imm_offset_insn (void*);
-int arm_handle_ld_st_reg_offset_insn (void*);
-int arm_hamdle_ld_st_multiple_insn (void*);
-int arm_handle_brn_insn (void*);
-int arm_handle_coproc_insn (void*);
-int arm_handle_coproc_data_proc_insn (void*);
-
-int thumb_handle_shift_add_sub_insn (void*);         
-int thumb_handle_data_proc_load_strbrn_insn (void*); 
-int thumb_handle_ld_st_reg_offset_insn (void*);      
-int thumb_handle_ld_st_imm_offset_insn (void*);      
-int thumb_hamdle_ld_st_stack_insn (void*);        
-int thumb_handle_misc_insn (void*);             
-int thumb_handle_swi_insn (void*);                    
-int thumb_handle_branch_insn (void*);                
-
-
-/* (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_data_proc_load_strbrn_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 */    
-};
-
-
-struct arm_mem_r
-{
-    uint32_t len;
-    CORE_ADDR addr;
-};
-
-typedef struct arm_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 */
-} arm_insn_decode_record;
-
-
-int 
-decode_insn (arm_insn_decode_record *arm_record, uint32_t insn_size)
-{
-  union
-    {
-      uint32_t s_word;
-      gdb_byte buf[insn_size];
-    } u_buf;
-
-  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->id = ARM_PARSE_INSN (arm_record->arm_insn,26,3);
-      arm_handle_insn[arm_record->id] ((void*)arm_record);
-    }    
-  else if(THUMB_INSN_SIZE_BYTES == insn_size)
-    {
-      arm_record->arm_insn = u_buf.s_word;  
-      arm_record->id = ARM_PARSE_INSN (arm_record->arm_insn,14,3);
-      thumb_handle_insn[arm_record->id] ((void*)arm_record);
-    }
-  return 0;
-}
-
-/* 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);
-  int no_of_rec=0;
-
-  union
-    {
-      uint32_t s_word;
-      gdb_byte buf[4];
-    } u_buf;
-
-  arm_insn_decode_record arm_record;
-
-  memset (&u_buf, 0, sizeof(u_buf));
-  memset (&arm_record, 0, sizeof (arm_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]);
-  if (IS_IT_ARM_INSN (u_buf.s_word))
-    {
-      /* we are decoding arm insn */
-      decode_insn (&arm_record, 4);
-    }
-  else
-    {
-      /* we are decoding thumb insn */
-      decode_insn (&arm_record, 2);    
-    }
-
-  /* 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]))
-          return -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))
-            return -1;
-       }
-    }
-
-  if (record_arch_list_add_end ())
-    return -1;
-
-  xfree (arm_record.arm_regs);
-  xfree (arm_record.arm_mems);
-  return 0; 
-}
-
-int 
-arm_handle_data_proc_misc_load_str_insn (void *data)
-{
-
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) 
arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  union
-    {
-      uint32_t s_word;
-      gdb_byte buf[4];
-    } u_buf[2];
-
-
-  uint32_t reg_val1=0,reg_val2=0;
-  uint32_t reg_src1=0,reg_src2=0,reg_dest=0;
-  uint32_t immed_high=0,immed_low=0,offset_8=0,tgt_mem_addr=0;
-
-  memset(&u_buf, 0, sizeof(u_buf));
-
-  arm_insn_r->opcode = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
-  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
-
-  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
-    {
-    /* data processing insn /multiply sinsn */     
-    if(9 == arm_insn_r->decode)
-      {
-      /* 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] = ARM_PARSE_INSN \
-                                      (arm_insn_r->arm_insn,17,4);
-            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] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,17,4);
-           arm_insn_r->arm_regs[2] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,13,4);
-           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
-         }        
-      }
-    else if((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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
-        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] = ARM_PARSE_INSN \
-                                      (arm_insn_r->arm_insn,13,4);
-          }
-        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
-      {
-        /* 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[0] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
-        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;        
-      }
-    }
-  else
-    {
-    /* handle misc, swap insns, and store instructions as 20th bit ((L = 0) */  

-      if(9 == arm_insn_r->decode)
-        {
-          /* Handling SWP, SWPB */
-          /* these insns, changes register and memory as well */
-          if((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
-            {
-              /* 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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4); 
-              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] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,13,4);    

-            }
-        }
-      else if(3 == arm_insn_r->decode)
-        {
-          /* handle BLX, branch and link/exchange */
-          if(9 == arm_insn_r->opcode)
-          {
-            /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm, 
-                         and R14 stores the return address */
-            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)
-        {
-          /* 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 CSPR and 
-               Program Counter. */
-          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
-          arm_insn_r->arm_regs[0] = 1;
-          arm_insn_r->arm_regs[0] = ARM_PS_REGNUM;
-        }
-      else if(11 == arm_insn_r->decode)
-        {
-        /* handle enhanced store insns and LDRD DSP insn */
-        /* 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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);
-              immed_high = ARM_PARSE_INSN (arm_insn_r->arm_insn,9,4);
-              reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-              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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
-              /* get Rn */
-              reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-              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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
-              immed_high = ARM_PARSE_INSN (arm_insn_r->arm_insn,9,4);
-              offset_8 = (immed_high << 4) | immed_low;
-              reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-              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] = ARM_PARSE_INSN \
-                                        (arm_insn_r->arm_insn,17,4);  
-            }
-          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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
-              reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-              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] = ARM_PARSE_INSN \
-                                        
(arm_insn_r->arm_insn,17,4);              

-            }
-          /* DSP LDRD TBD */
-        }
-      else if(1 == arm_insn_r->decode)
-        {
-          /* handle BLX, branch and link/exchange */
-          if(2 == arm_insn_r->opcode)
-            {
-              /* 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(11 == arm_insn_r->opcode)
-            {
-              /* count leading zeros: CLZ */
-              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_PARSE_INSN \
-                                        (arm_insn_r->arm_insn,13,4);
-            }
-        }
-      else if((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
-        {
-          /* 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] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,13,4);  

-        }
-      else if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
-        {
-        /* 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 ?*/
-          }
-        }   
-    }    
-  return 0;
-}
-
-int 
-arm_handle_data_proc_imm_insn (void *data)
-{
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = \
-                          gdbarch_tdep ((struct gdbarch*) arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  uint32_t reg_val1=0,reg_val2=0;
-  uint32_t reg_src1=0,reg_src2=0,reg_dest=0;
-  uint32_t immed_high=0,immed_low=0,offset_8=0,tgt_mem_addr=0;
-
-  arm_insn_r->opcode = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
-  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
-
-  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
-    {
-      /* data processing insn, e.g. MOV */                
-      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_PARSE_INSN (arm_insn_r->arm_insn,13,4);
-      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;       
-    }
-  else
-    {
-      /* handle MSR insn, status register access */
-      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
-      /*CSPR is going to be changed */
-      arm_insn_r->arm_regs[0] = 1;
-      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;                
-    }
-  return 0;
-}
-
-int 
-arm_handle_ld_st_imm_offset_insn (void *data)
-{
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = \
-                          gdbarch_tdep ((struct gdbarch*) arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  uint32_t reg_val1=0,reg_val2=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
-    {
-      uint32_t s_word;
-      gdb_byte buf[4];
-    } u_buf;
-
-  memset(&u_buf, 0, sizeof(u_buf));
-  arm_insn_r->opcode = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
-  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
-
-  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
-    {
-      reg_dest = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
-      /* 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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
-        }
-      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-indeed */
-          reg_src1= ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-          offset_12 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,12);
-          GET_REG_VAL (reg_cache,reg_src1,&u_buf.buf[0]);
-          /* U == 1 */
-          if (ARM_BIT_SET (arm_insn_r->arm_insn,24))
-            {   
-              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;
-}
-
-int 
-arm_handle_ld_st_reg_offset_insn (void *data)
-{
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = \
-                           gdbarch_tdep ((struct gdbarch*) 
arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  uint32_t reg_val1=0,reg_val2=0,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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
-  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
-
-  /* handle enhanced store insns and LDRD DSP insn */
-  /* let us begin according to addressing modes for store insns */
-  /* STRH insn */
-
-  /* LDR or STR ? */
-  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
-    {
-      reg_dest = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
-      /* 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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
-        }
-      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(!ARM_PARSE_INSN(arm_insn_r->arm_insn,5,8))
-          {
-            /* store insn, register offset and register pre-indexed, 
-            register post-indexed */
-            /* get Rm */
-            reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
-            /* get Rn */
-            reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-            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 (ARM_BIT_SET (arm_insn_r->arm_insn,24))
-              {
-                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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,6,2);
-            /* get Rm */
-            reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
-            /* get Rn */
-            reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-            /* get shift_imm */
-            shift_imm = ARM_PARSE_INSN (arm_insn_r->arm_insn,8,5);
-            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(ARM_BIT_SET (u_buf[0].s_word,32))
-                        {
-                          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 = (((GET_BIT (u_buf[1].s_word,30)) << 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 (ARM_BIT_SET (arm_insn_r->arm_insn,24))
-              {
-                tgt_mem_addr = u_buf[1].s_word + offset_12;
-              }
-            else
-              {
-                tgt_mem_addr = u_buf[1].s_word - offset_12;
-              }                       
-            switch(arm_insn_r->opcode)
-              {
-                case 8:
-                case 12:          
-                case 9:   
-                case 13:   
-                case 1:   
-                case 5:               
-                  /* STR insn, STRT insn */
-                  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 = (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;
-
-            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;   
-}
-
-int 
-arm_hamdle_ld_st_multiple_insn (void *data)
-{   
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = \
-                            gdbarch_tdep ((struct gdbarch*) 
arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  uint32_t register_list[16]={0}, register_count=0, register_bits=0;       
-  uint32_t reg_val1=0, reg_val2=0, shift_imm=0;
-  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
-  uint32_t start_address=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 (ARM_BIT_SET (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
-    {
-      /* LDR (1,2,3) where LDR (3) changes CPSR too */
-
-      register_bits = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,16);
-      /* get Rn */
-      reg_src1 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
-      while(register_bits)
-        {
-          register_list[register_count++] = register_bits & 0x00000001;
-          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+1+1+1));
-        arm_insn_r->arm_regs[0] = register_count+1+1;
-        arm_insn_r->arm_regs[register_count+1] = reg_src1;
-        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
-      while(register_count)
-        {
-          arm_insn_r->arm_regs[register_count] = \
-          register_list[register_count-1];
-          register_count--;
-        }
-    }
-  else
-    {
-    /* it handles both STM(1) and STM(2) */
-    addr_mode = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,2);    
-
-    register_bits = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,16);
-    /* get Rn */
-    reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
-    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 = 1;
-          while(register_count)
-            {
-              arm_insn_r->arm_mems[register_count].addr = start_address;
-              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 = 1;
-          while(register_count)
-            {
-              arm_insn_r->arm_mems[register_count].addr = start_address;
-              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 = 1;
-          while(register_count)
-            {
-              arm_insn_r->arm_mems[register_count].addr = start_address;
-              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 = 1;
-          while(register_count)
-            {
-              arm_insn_r->arm_mems[register_count].addr = start_address;
-              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[register_count+1] = reg_src1;
-    }
-  return 0;   
-}
-
-int 
-arm_handle_brn_insn (void *data)
-{
-  arm_insn_decode_record *arm_insn_r = (arm_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;
-}
-
-int 
-arm_handle_coproc_insn (void *data)
-{
-  arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
-  struct gdbarch_tdep *tdep = \
-                          gdbarch_tdep ((struct gdbarch*) arm_insn_r->gdbarch);
-  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
-
-  uint32_t register_list[16]={0},register_count=0, register_bits=0;     
-  uint32_t reg_val1=0,reg_val2=0,shift_imm=0;
-  uint32_t reg_src1=0,reg_src2=0,addr_mode=0;
-  uint32_t start_address=0;
-
-  return 0;   
-}
-
-int 
-arm_handle_coproc_data_proc_insn (void *data)
-{
-  /* TBD */
-  return 0;   
-}
-
-
-int 
-thumb_handle_shift_add_sub_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_data_proc_load_strbrn_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_ld_st_reg_offset_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_ld_st_imm_offset_insn (void *data )
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_hamdle_ld_st_stack_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_misc_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_swi_insn (void *data)                
-{
-  /* TBD */
-  return 0;
-}
-
-int 
-thumb_handle_branch_insn (void *data)
-{
-  /* TBD */
-  return 0;
-}
diff -urN arm_new/arm-tdep.h arm_orig/arm-tdep.h
--- arm_new/arm-tdep.h    2011-03-03 09:15:59.000000000 +0530
+++ arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
@@ -310,10 +310,6 @@
                       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: paawan oza <paawan1982@yahoo.com>
To: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Wed, February 2, 2011 2:58:44 PM
Subject: [PATCH] arm reversible : progress <patch_1_phase_1>

Hi all,

As I thought, I would be working on arm insn part first and then linux ABI part 
first.
working with arm and thumb insn, I have come up with patch_1 of my phase 1 
activity.
which mainly includes design, few insns, and framework on which I will relying 
on rest of the implementation.
few arm insns are implemented and in place, and I am able to debug following 
samle program too.

PS: I am posting this patch, not with the intension of comletion or getting it 
in mainline. but I thought If I post early I may get some valuable suggestions 
and inputs regarding design and data structures, or have missed to consider some 

arch related issues. I will get to know early before I go forward.
please also ignore coding guidelines as it will be corrected in due timeline.
any inputs and suggestions are welcome.


the samle program is as below.
#include <stdio.h>

void main()
{
     int s;
     s = 10;
     s = 15;
     s = 20;
     s = -30;
     s = 88;
}

<PATCH>
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-02-02 14:22:52.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-02-02 14:23:03.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,
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-02-02 14:22:53.000000000 +0530
+++ arm_new/arm-tdep.c    2011-02-02 14:23:03.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,576 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
}
+
+
+
+/* arm-reversible process reacord data structures */
+
+#define NO_OF_TYPE_OF_ARM_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 & 0x00000010) >> 4)
+#define ARM_PARSE_INSN(X,BIT_POS,NO_OF_BITS) \
+                ((X >> (BIT_POS-1)) & (0xFFFFFFFF >> ((sizeof(uint32_t)*8) - \
+                  NO_OF_BITS)))
+
+/* arm_handle_data_proc_imm_insn */
+#define INSN_S_BIT_NUM 21
+#define ARM_BIT_SET(X, NUM) (((X >> (NUM-1)) & 0x00000001) == 1)  
+
+
+int arm_handle_data_proc_misc_load_str_insn (void*);
+int arm_handle_data_proc_misc_load_str_insn(void*);
+int arm_handle_data_proc_imm_insn(void*);
+int arm_handle_ld_st_imm_offset_insn(void*);
+int arm_handle_ld_st_reg_offset_insn(void*);
+int arm_hamdle_ld_st_multiple_insn(void*);
+int arm_handle_brn_insn(void*);
+int arm_handle_coproc_insn(void*);
+int arm_handle_coproc_data_proc_insn(void*);
+
+int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) = 
+{ 
+    arm_handle_data_proc_misc_load_str_insn, 
+    arm_handle_data_proc_imm_insn,
+    arm_handle_ld_st_imm_offset_insn,
+    arm_handle_ld_st_reg_offset_insn,
+    arm_hamdle_ld_st_multiple_insn,
+    arm_handle_brn_insn,
+    arm_handle_coproc_insn,
+    arm_handle_coproc_data_proc_insn
+};
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+typedef struct arm_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 
*/
+} arm_insn_decode_record;
+
+
+int decode_insn(arm_insn_decode_record *arm_record, uint32_t insn_size)
+{
+    union
+    {
+         uint32_t s_word;
+         gdb_byte buf[insn_size];
+    } 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
+    {
+        arm_record->arm_insn = u_buf.s_word;
+        arm_record->cond = ARM_PARSE_INSN (arm_record->arm_insn,29,4);
+        arm_record->id = ARM_PARSE_INSN (arm_record->arm_insn,26,3);
+
+        if (0b1111 == arm_record->cond) 
+        {
+            /* Version5 and above support this, so handle this as well.  
*/            

+        }
+        else
+        {
+            arm_handle_insn[arm_record->id]((void*)arm_record);
+        }
+    }    
+    return 0;
+}
+
+/* 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);
+  int no_of_rec=0;
+
+  union
+  {
+       uint32_t s_word;
+       gdb_byte buf[4];
+  } u_buf;
+
+  arm_insn_decode_record arm_record;
+
+  memset (&arm_record, 0, sizeof (arm_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]);
+  if (IS_IT_ARM_INSN (u_buf.s_word))
+  {
+    /* we are decoding arm insn */
+    decode_insn (&arm_record, 4);
+  }
+  else
+  {
+    /* we are decoding thumb insn */
+    decode_insn (&arm_record, 2);    
+  }
+
+  /* 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]))
+      {
+            return -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))
+      {
+        return -1;
+      }
+    }
+  }
+  
+  if (record_arch_list_add_end ())
+  {
+      return -1;
+  }
+  return 0; 
+}
+
+int arm_handle_data_proc_misc_load_str_insn(void *data)
+{
+
+   arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) 
arm_insn_r->gdbarch);
+   struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
+
+   union
+   {
+     uint32_t s_word;
+     gdb_byte buf[4];
+   }u_buf[2];
+          
+   uint32_t reg_val1=0,reg_val2=0;
+   uint32_t reg_src1=0,reg_src2=0,reg_dest=0;
+   uint32_t immed_high=0,immed_low=0,offset_8=0,tgt_mem_addr=0;
+
+   arm_insn_r->opcode = ARM_PARSE_INSN(arm_insn_r->arm_insn,22,4);
+   arm_insn_r->decode = ARM_PARSE_INSN(arm_insn_r->arm_insn,5,4);
+        
+   if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_BIT_NUM)) 
+   {
+      /* data processing insn /multiply sinsn */    
+      if(9 == arm_insn_r->decode)
+      {
+        /* 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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            arm_insn_r->arm_regs[2] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+            arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+            
+        }        
+      }
+      else if((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. */
+          reg_dest = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+          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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+          }
+          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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+          }
+      }
+      else
+      {
+        /* 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[0] = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;        
+      }
+   }
+   else
+   {
+      /* handle misc, swap insns, and store instructions as 20th bit ((L = 0) 
*/  

+      if(9 == arm_insn_r->decode)
+      {
+        /* Handling SWP, SWPB */
+        /* these insns, changes register and memory as well */
+        if((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+        {
+            /* 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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4); 
+            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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);    

+         }
+      }
+      else if(3 == arm_insn_r->decode)
+      {
+          /* handle BLX, branch and link/exchange */
+          if(9 == arm_insn_r->opcode)
+          {
+              /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm, 
+                             and R14 stores the return address */
+              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)
+      {
+          /* 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 CSPR and 
+                     Program Counter. */
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc(sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[0] = ARM_PS_REGNUM;
+      }
+      else if(13 == arm_insn_r->decode)
+      {
+          /* handle enhanced store insns and LDRD DSP insn and */
+          /* let us begin according to addressing modes for store insns */
+
+          if((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+          {
+            /* 1) handle misc store, immediate offset */
+            immed_low = ARM_PARSE_INSN(arm_insn_r->arm_insn,1,4);
+            immed_high = ARM_PARSE_INSN(arm_insn_r->arm_insn,9,4);
+            reg_src1 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,1,4);  
+            /* get Rn */
+            reg_src2 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,1,4);  
+            immed_high = ARM_PARSE_INSN(arm_insn_r->arm_insn,9,4);
+            offset_8 = (immed_high << 4) | immed_low;
+            reg_src1 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);  

+            
+          }
+          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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,1,4);  
+            reg_src2 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+            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] = 
ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);              

+          }
+          /* DSP LDRD TBD */
+      }
+      else if(1 == arm_insn_r->decode)
+      {
+          /* handle BLX, branch and link/exchange */
+          if(2 == arm_insn_r->opcode)
+          {
+              /* 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(11 == arm_insn_r->opcode)
+          {
+              /* count leading zeros: CLZ */
+              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_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+          }
+      }
+      else if((0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+      {
+          /* 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] = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);  


+      }
+      else if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+      {
+           /* 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 ?*/
+          }
+      }  
+   }    
+   return 0;
+}
+
+int arm_handle_data_proc_imm_insn(void *data)
+{
+   arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = \
+                        gdbarch_tdep ((struct gdbarch*) arm_insn_r->gdbarch);
+   struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
+          
+   uint32_t reg_val1=0,reg_val2=0;
+   uint32_t reg_src1=0,reg_src2=0,reg_dest=0;
+   uint32_t immed_high=0,immed_low=0,offset_8=0,tgt_mem_addr=0;
+
+   arm_insn_r->opcode = ARM_PARSE_INSN(arm_insn_r->arm_insn,22,4);
+   arm_insn_r->decode = ARM_PARSE_INSN(arm_insn_r->arm_insn,5,4);
+        
+   if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_BIT_NUM)) 
+   {
+       /* data processing insn, e.g. MOV */                
+       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_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+       arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;      
+   }
+   return 0;
+}
+
+int arm_handle_ld_st_imm_offset_insn(void *data)
+{
+   arm_insn_decode_record *arm_insn_r = (arm_insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = \
+                        gdbarch_tdep ((struct gdbarch*) arm_insn_r->gdbarch);
+   struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;
+          
+   uint32_t reg_val1=0,reg_val2=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
+   {
+     uint32_t s_word;
+     gdb_byte buf[4];
+   }u_buf;
+
+   arm_insn_r->opcode = ARM_PARSE_INSN(arm_insn_r->arm_insn,22,4);
+   arm_insn_r->decode = ARM_PARSE_INSN(arm_insn_r->arm_insn,5,4);
+
+   /* Oza: as of now only STR is getting implemented for demo */
+   reg_src1= ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+   offset_12 = ARM_PARSE_INSN(arm_insn_r->arm_insn,1,12);
+   GET_REG_VAL(reg_cache,reg_src1,&u_buf.buf[0]);
+   if (ARM_BIT_SET(arm_insn_r->arm_insn,24))
+   {  
+     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;
+   arm_insn_r->arm_mems[1].len = 4;
+   arm_insn_r->arm_mems[1].addr = tgt_mem_addr;      
+   return 0;
+}
+
+int arm_handle_ld_st_reg_offset_insn(void *data)
+{
+   /* TBD */
+   return 0;  
+}
+
+int arm_hamdle_ld_st_multiple_insn(void *data)
+{
+   /* TBD */
+   return 0;  
+}
+
+int arm_handle_brn_insn(void *data)
+{
+   /* TBD */
+   return 0;
+}
+
+int arm_handle_coproc_insn(void *data)
+{
+   /* TBD */
+   return 0;  
+}
+
+int arm_handle_coproc_data_proc_insn(void *data)
+{
+   /* TBD */
+   return 0;  
+}

Regards,
Oza.



----- Original Message ----
From: paawan oza <paawan1982@yahoo.com>
To: Michael Snyder <msnyder@vmware.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Tue, February 1, 2011 8:50:51 AM
Subject: Re: arm reversible execution query

Hi Michael,

thank you for your reply.

I think you are referring to below line. in process_record.

I386_RECORD_ARCH_LIST_ADD_REG (X86_RECORD_REIP_REGNUM);
  if (record_arch_list_add_end ())
    return -1;


I got it that it has to be saved explicitly by process record arch level.

Thanks,
Oza.


----- Original Message ----
From: Michael Snyder <msnyder@vmware.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Tue, February 1, 2011 12:23:14 AM
Subject: Re: arm reversible execution query

paawan oza wrote:
> 
> Hi all,
> 
> I have been wroking on arm-reversible implementation and doing arm insn part. I 
>
>
>am done with framework, and supporting 30-40% on insns till now.
> when I simply test on arm board, I find that,
> 
> all the memory and registers are replayed correctly and recording is 
happening.
> but,
> do I need to save Program counter explicitly ?
> doesnt gdb reversible framework take care of changing pc when I apply 
>reverse-stepi/nexti command ?
> 
> as i386-tdep.c, does not seem to be saving PC explicitly.
> 
> please clarify.


i386-tdep.c does save the PC ($eip), at the end of function i386_process_record.

If you don't save the PC, how can you do a reverse jump?


      


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-03  4:08 [PATCH] arm reversible : progress <patch_1_phase_2> paawan oza
@ 2011-03-03 18:32 ` Tom Tromey
  2011-03-03 18:37   ` Michael Snyder
                     ` (2 more replies)
  0 siblings, 3 replies; 32+ messages in thread
From: Tom Tromey @ 2011-03-03 18:32 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb

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

>> I am done with the deisng for both thumb and arm framework.

Thanks for your work on this.

>> having some doubts as of now.

I can't help with the ARM-specific stuff, but I have a few more general
comments.

>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c

The patch is reversed.

>> -  /* Enable process record */
>> -  set_gdbarch_process_record(gdbarch, arm_process_record);

There are a bunch of minor coding style problems in the patch.
You'll have to fix them all before submitting.

In the quoted lines: the comment must end with a period and two spaces,
and there is a space missing before the open paren.  That is, the code
should look like:

  /* Enable process record.  */
  set_gdbarch_process_record (gdbarch, arm_process_record);

These two problems appear frequently.

>> -int arm_handle_data_proc_misc_load_str_insn (void*);

I did not read closely, but I think most or maybe all of the functions
declared here should be static.  This applies to some other objects as
well, like arm_handle_insn.

Actually, in most cases, I think the code could be rearranged so that
you don't need forward declarations at all.

>> -  else if(ARM_INSN_SIZE_BYTES == insn_size)

Space after the "if" -- this happens a lot.

>> -  struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) arm_insn_r-> gdbarch);

I think you don't need the cast here.
I think this occurs in a few places.

>> -  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;

Or here.  But if you needed something like this, there would have to be
a space before the "*".

>> -    /* data processing insn /multiply sinsn */     
>> -    if(9 == arm_insn_r->decode)

One thing I dislike about the x86 record code is the huge number of
constants.  I think this sort of thing is better if you use some
symbolic name instead.

One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.

>> -            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);

I think it is a little clearer to use the libiberty macros, e.g.:

  arm_insn_r->arm_regs = XNEWVEC (uint32_t, 3);

>> -  uint32_t reg_val1=0,reg_val2=0;

Spaces around the "=" signs.  This occurs in a few places.

Tom


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-03 18:32 ` Tom Tromey
@ 2011-03-03 18:37   ` Michael Snyder
  2011-03-03 18:59     ` Pedro Alves
  2011-03-04  3:32   ` paawan oza
  2011-04-10  9:41   ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
  2 siblings, 1 reply; 32+ messages in thread
From: Michael Snyder @ 2011-03-03 18:37 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb

Tom Tromey wrote:
>>>>>> ">" == paawan oza <paawan1982@yahoo.com> writes:
> 
>>> I am done with the deisng for both thumb and arm framework.
> 
> Thanks for your work on this.
> 
>>> having some doubts as of now.
> 
> I can't help with the ARM-specific stuff, but I have a few more general
> comments.
> 
>>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c
> 
> The patch is reversed.


Oza, you probably meant to say "-upN".


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-03 18:37   ` Michael Snyder
@ 2011-03-03 18:59     ` Pedro Alves
  0 siblings, 0 replies; 32+ messages in thread
From: Pedro Alves @ 2011-03-03 18:59 UTC (permalink / raw)
  To: gdb; +Cc: Michael Snyder, Tom Tromey, paawan oza

On Thursday 03 March 2011 18:37:15, Michael Snyder wrote:
> >>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c
> > 
> > The patch is reversed.
> 
> 
> Oza, you probably meant to say "-upN".

Nah, -r is to recurse in subdirectories, that was correct.
The problem is in the use of 'diff $NEW $OLD'.  It should
be 'diff $OLD $NEW'.

But while at it, please do add the -p as Michael is suggesting.
It makes reading the patches easier.

Are you diffing two copies of the tree (one pristine, one
edited)?  I suggest investing some time on learning to
work with some patch series management tool or process.
E.g., I work on top of a cvs checkout and manage my
patches with quilt; others use git, or stgit.

-- 
Pedro Alves


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-03 18:32 ` Tom Tromey
  2011-03-03 18:37   ` Michael Snyder
@ 2011-03-04  3:32   ` paawan oza
  2011-03-04  3:56     ` paawan oza
  2011-03-04 19:31     ` Tom Tromey
  2011-04-10  9:41   ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
  2 siblings, 2 replies; 32+ messages in thread
From: paawan oza @ 2011-03-04  3:32 UTC (permalink / raw)
  To: Tom Tromey, Michael Snyder; +Cc: gdb

Hi Tom and Michael,

First of all; thanks for your comments.


1)   diff will be changed as you suggested.
2)   coding guidelines will be further more corrected.
3)   function will be made static and prototype will be removed.
4)  casting problems and space problems will be corrected.

Tom: >> One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.


Oza: if you see x86 record code; it doesnt look to be sharing many things.
same case with arm because the way we need to decode the insn for record-replay 
and extract registers and memory and 

linux ABI; probably sharing code is much more clumsy and unclean than writing 
few K new lines.

may I have some idea about QEMU based approach ?
I did not get your hint to incorporate into gdb record-replay.

PS: if somebody could clarify.
1) what is the API to read arm coprocessor registers ?
2) how to read SPSR value ?
3) there are couple of FIX me in code.

Regards,
Oza.


----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Fri, March 4, 2011 12:02:44 AM
Subject: Re: [PATCH] arm reversible : progress <patch_1_phase_2>

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

>> I am done with the deisng for both thumb and arm framework.

Thanks for your work on this.

>> having some doubts as of now.

I can't help with the ARM-specific stuff, but I have a few more general
comments.

>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c

The patch is reversed.

>> -  /* Enable process record */
>> -  set_gdbarch_process_record(gdbarch, arm_process_record);

There are a bunch of minor coding style problems in the patch.
You'll have to fix them all before submitting.

In the quoted lines: the comment must end with a period and two spaces,
and there is a space missing before the open paren.  That is, the code
should look like:

  /* Enable process record.  */
  set_gdbarch_process_record (gdbarch, arm_process_record);

These two problems appear frequently.

>> -int arm_handle_data_proc_misc_load_str_insn (void*);

I did not read closely, but I think most or maybe all of the functions
declared here should be static.  This applies to some other objects as
well, like arm_handle_insn.

Actually, in most cases, I think the code could be rearranged so that
you don't need forward declarations at all.

>> -  else if(ARM_INSN_SIZE_BYTES == insn_size)

Space after the "if" -- this happens a lot.

>> -  struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) arm_insn_r-> 
>>gdbarch);

I think you don't need the cast here.
I think this occurs in a few places.

>> -  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;

Or here.  But if you needed something like this, there would have to be
a space before the "*".

>> -    /* data processing insn /multiply sinsn */    
>> -    if(9 == arm_insn_r->decode)

One thing I dislike about the x86 record code is the huge number of
constants.  I think this sort of thing is better if you use some
symbolic name instead.

One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.

>> -            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);

I think it is a little clearer to use the libiberty macros, e.g.:

  arm_insn_r->arm_regs = XNEWVEC (uint32_t, 3);

>> -  uint32_t reg_val1=0,reg_val2=0;

Spaces around the "=" signs.  This occurs in a few places.

Tom



      


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-04  3:32   ` paawan oza
@ 2011-03-04  3:56     ` paawan oza
  2011-03-04 19:31     ` Tom Tromey
  1 sibling, 0 replies; 32+ messages in thread
From: paawan oza @ 2011-03-04  3:56 UTC (permalink / raw)
  To: paawan oza, Tom Tromey, Michael Snyder; +Cc: gdb

Hi,

with reference to below mail;

QEMU provides both logging and trapshooting techniques.
but I am not sure why gdb has chosen logging ?
moreover when gdb is running on QEMU; does it hand over the record-replay to 
QEMU ?


Regards,
Oza.


----- Original Message ----
From: paawan oza <paawan1982@yahoo.com>
To: Tom Tromey <tromey@redhat.com>; Michael Snyder <msnyder@vmware.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Fri, March 4, 2011 9:02:10 AM
Subject: Re: [PATCH] arm reversible : progress <patch_1_phase_2>

Hi Tom and Michael,

First of all; thanks for your comments.


1)   diff will be changed as you suggested.
2)   coding guidelines will be further more corrected.
3)   function will be made static and prototype will be removed.
4)  casting problems and space problems will be corrected.

Tom: >> One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.


Oza: if you see x86 record code; it doesnt look to be sharing many things.
same case with arm because the way we need to decode the insn for record-replay 
and extract registers and memory and 

linux ABI; probably sharing code is much more clumsy and unclean than writing 
few K new lines.

may I have some idea about QEMU based approach ?
I did not get your hint to incorporate into gdb record-replay.

PS: if somebody could clarify.
1) what is the API to read arm coprocessor registers ?
2) how to read SPSR value ?
3) there are couple of FIX me in code.

Regards,
Oza.


----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Fri, March 4, 2011 12:02:44 AM
Subject: Re: [PATCH] arm reversible : progress <patch_1_phase_2>

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

>> I am done with the deisng for both thumb and arm framework.

Thanks for your work on this.

>> having some doubts as of now.

I can't help with the ARM-specific stuff, but I have a few more general
comments.

>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c

The patch is reversed.

>> -  /* Enable process record */
>> -  set_gdbarch_process_record(gdbarch, arm_process_record);

There are a bunch of minor coding style problems in the patch.
You'll have to fix them all before submitting.

In the quoted lines: the comment must end with a period and two spaces,
and there is a space missing before the open paren.  That is, the code
should look like:

  /* Enable process record.  */
  set_gdbarch_process_record (gdbarch, arm_process_record);

These two problems appear frequently.

>> -int arm_handle_data_proc_misc_load_str_insn (void*);

I did not read closely, but I think most or maybe all of the functions
declared here should be static.  This applies to some other objects as
well, like arm_handle_insn.

Actually, in most cases, I think the code could be rearranged so that
you don't need forward declarations at all.

>> -  else if(ARM_INSN_SIZE_BYTES == insn_size)

Space after the "if" -- this happens a lot.

>> -  struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) arm_insn_r-> 
>>gdbarch);

I think you don't need the cast here.
I think this occurs in a few places.

>> -  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;

Or here.  But if you needed something like this, there would have to be
a space before the "*".

>> -    /* data processing insn /multiply sinsn */    
>> -    if(9 == arm_insn_r->decode)

One thing I dislike about the x86 record code is the huge number of
constants.  I think this sort of thing is better if you use some
symbolic name instead.

One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.

>> -            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);

I think it is a little clearer to use the libiberty macros, e.g.:

  arm_insn_r->arm_regs = XNEWVEC (uint32_t, 3);

>> -  uint32_t reg_val1=0,reg_val2=0;

Spaces around the "=" signs.  This occurs in a few places.

Tom


      


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-04  3:32   ` paawan oza
  2011-03-04  3:56     ` paawan oza
@ 2011-03-04 19:31     ` Tom Tromey
  2011-03-04 20:09       ` Michael Snyder
  1 sibling, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2011-03-04 19:31 UTC (permalink / raw)
  To: paawan oza; +Cc: Michael Snyder, gdb

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

Oza> may I have some idea about QEMU based approach ?
Oza> I did not get your hint to incorporate into gdb record-replay.

I was thinking of this:

http://www.codesourcery.com/publications/reversible_debugging.pdf

Tom


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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-04 19:31     ` Tom Tromey
@ 2011-03-04 20:09       ` Michael Snyder
  2011-03-04 20:11         ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: Michael Snyder @ 2011-03-04 20:09 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb

Tom Tromey wrote:
>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
> 
> Oza> may I have some idea about QEMU based approach ?
> Oza> I did not get your hint to incorporate into gdb record-replay.
> 
> I was thinking of this:
> 
> http://www.codesourcery.com/publications/reversible_debugging.pdf
>

I think that fell by the wayside.



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

* Re: [PATCH] arm reversible : progress <patch_1_phase_2>
  2011-03-04 20:09       ` Michael Snyder
@ 2011-03-04 20:11         ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2011-03-04 20:11 UTC (permalink / raw)
  To: Michael Snyder; +Cc: paawan oza, gdb

Tom> http://www.codesourcery.com/publications/reversible_debugging.pdf

Michael> I think that fell by the wayside.

Yeah.  Do you know why?

Tom


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

* [PATCH] arm reversible : progress <phase_2_complete>
  2011-03-03 18:32 ` Tom Tromey
  2011-03-03 18:37   ` Michael Snyder
  2011-03-04  3:32   ` paawan oza
@ 2011-04-10  9:41   ` paawan oza
  2011-04-11  3:05     ` Yao Qi
  2 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-10  9:41 UTC (permalink / raw)
  To: gdb, Tom Tromey

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.


here is the PATCH:
---------------------------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-10 15:00:56.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-10 15:00:56.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,1705 @@
                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 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)))
+
+#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))
+
+
+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 = ARM_PARSE_INSN (insn,bit_num,len);
+      
+  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 = 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);
+  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;
+}
+
+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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
+  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
+  opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,21,5);
+
+  /* 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] = ARM_PARSE_INSN \
+                                      (arm_insn_r->arm_insn,17,4);
+            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] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,17,4);
+           arm_insn_r->arm_regs[2] = ARM_PARSE_INSN 
(arm_insn_r->arm_insn,13,4);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+         }        
+      }
+  else if ((ARM_BIT_SET (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 = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+        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] = ARM_PARSE_INSN \
+                                      (arm_insn_r->arm_insn,13,4);
+          }
+        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 == ARM_PARSE_INSN (arm_insn_r->arm_insn,21,2)))
+    {
+      /* 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))
+           && (!ARM_BIT_SET (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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4); 
+      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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);    
+    }
+  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)
+          && (!ARM_BIT_SET (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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);
+        immed_high = ARM_PARSE_INSN (arm_insn_r->arm_insn,9,4);
+        reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+        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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
+        /* get Rn.  */
+        reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+        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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
+        immed_high = ARM_PARSE_INSN (arm_insn_r->arm_insn,9,4);
+        offset_8 = (immed_high << 4) | immed_low;
+        reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+        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] = ARM_PARSE_INSN \
+                                  (arm_insn_r->arm_insn,17,4);  
+      }
+    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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
+        reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+        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] = ARM_PARSE_INSN \
+                                  (arm_insn_r->arm_insn,17,4);              
+      }
+    /* 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.  */
+      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_PARSE_INSN \
+                                (arm_insn_r->arm_insn,13,4);
+    }
+  else if ((!ARM_BIT_SET (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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);  
+    }      
+  /* 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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
+      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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
+  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
+
+  if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+       && (2 == ARM_PARSE_INSN (arm_insn_r->arm_insn,21,2))
+       && (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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
+      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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
+  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
+
+  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+    {
+      reg_dest = ARM_PARSE_INSN(arm_insn_r->arm_insn,13,4);
+      /* 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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
+        }
+      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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+          offset_12 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,12);
+          GET_REG_VAL (reg_cache,reg_src1,&u_buf.buf[0]);
+          /* U == 1 */
+          if (ARM_BIT_SET (arm_insn_r->arm_insn,24))
+            {   
+              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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,22,4);
+  arm_insn_r->decode = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
+
+  /* handle enhanced store insns and LDRD DSP insn,
+        let us begin according to addressing modes for store insns 
+        STRH insn.  */
+
+  /* LDR or STR?  */
+  if (ARM_BIT_SET(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      reg_dest = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
+      /* 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] = ARM_PARSE_INSN (arm_insn_r->arm_insn,13,4);
+        }
+      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 (!ARM_PARSE_INSN(arm_insn_r->arm_insn,5,8))
+          {
+            /* store insn, register offset and register pre-indexed, 
+                          register post-indexed.  */
+            /* get Rm.  */
+            reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
+            /* get Rn.  */
+            reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+            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 (ARM_BIT_SET (arm_insn_r->arm_insn,24))
+              {
+                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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,6,2);
+            /* get Rm.  */
+            reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,4);  
+            /* get Rn.  */
+            reg_src2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+            /* get shift_imm.  */
+            shift_imm = ARM_PARSE_INSN (arm_insn_r->arm_insn,8,5);
+            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 (ARM_BIT_SET (u_buf[0].s_word,32))
+                        {
+                          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 = (((GET_BIT (u_buf[1].s_word,30)) << 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 (ARM_BIT_SET (arm_insn_r->arm_insn,24))
+              {
+                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 (ARM_BIT_SET (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,16);
+      /* get Rn.  */
+      reg_src1 = ARM_PARSE_INSN(arm_insn_r->arm_insn,17,4);
+      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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,2);    
+
+    register_bits = ARM_PARSE_INSN (arm_insn_r->arm_insn,1,16);
+    /* get Rn.  */
+    reg_src1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,17,4);
+    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 = ARM_PARSE_INSN (arm_insn_r->arm_insn,25,4);
+   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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+
+  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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,3);
+
+  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 (ARM_BIT_SET(thumb_insn_r->arm_insn,13))
+    {
+      /* handle load/store register offset.  */ 
+      opcode1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,12,2);
+      opcode2 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,10,2);  
+      if ((opcode2 >= 12) && (opcode2 <= 15))
+        {         
+          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
+          reg_src1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);           
+          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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,4,3);
+          reg_src2 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,7,3);
+          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 (ARM_BIT_SET(thumb_insn_r->arm_insn,12))
+    {
+      /* handle load from literal pool.  */  
+      /* LDR(3).  */
+      reg_src1 = ARM_PARSE_INSN 
(thumb_insn_r->arm_insn,9,3);                          

+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,14,3);
+  opcode1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,11,3);
+  if (opcode1)
+    {
+      opcode2 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,2);
+      opcode3 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+          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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+      if (ARM_BIT_SET(thumb_insn_r->arm_insn,8))
+        {
+          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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,12,2);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,4,3);
+      immed_5 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,7,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 = 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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,12,2);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,8);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,7,5);
+      reg_src1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,4,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,12,2);
+  opcode1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,5);
+  opcode2 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,10,4);
+
+  if (14 == opcode2)
+    {
+      /* POP.  */
+      register_bits = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,8);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,8);
+      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 * (GET_BIT(thumb_insn_r->arm_insn,9) + 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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,5);
+  opcode2 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,12,2);
+
+  if (1 == opcode2)
+    {
+
+      /* LDMIA.  */
+      register_bits = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,8);
+      /* get Rn.  */
+      reg_src1 = ARM_PARSE_INSN(thumb_insn_r->arm_insn,9,3);
+      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 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,1,8);
+      /* get Rn.  */
+      reg_src1 = ARM_PARSE_INSN (thumb_insn_r->arm_insn,9,3);
+      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)
+          {
+            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 = ARM_PARSE_INSN (arm_record->arm_insn,29,4); 
+      arm_record->id = ARM_PARSE_INSN (arm_record->arm_insn,26,3);
+      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 = ARM_PARSE_INSN (arm_record->arm_insn,14,3);
+      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;
+
+  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))
+    {
+      /* 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-10 15:00:56.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

Regards,
Oza.




----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: "gdb@sourceware.org" <gdb@sourceware.org>
Sent: Fri, March 4, 2011 12:02:44 AM
Subject: Re: [PATCH] arm reversible : progress <patch_1_phase_2>

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

>> I am done with the deisng for both thumb and arm framework.

Thanks for your work on this.

>> having some doubts as of now.

I can't help with the ARM-specific stuff, but I have a few more general
comments.

>> diff -urN arm_new/arm-linux-tdep.c arm_orig/arm-linux-tdep.c

The patch is reversed.

>> -  /* Enable process record */
>> -  set_gdbarch_process_record(gdbarch, arm_process_record);

There are a bunch of minor coding style problems in the patch.
You'll have to fix them all before submitting.

In the quoted lines: the comment must end with a period and two spaces,
and there is a space missing before the open paren.  That is, the code
should look like:

  /* Enable process record.  */
  set_gdbarch_process_record (gdbarch, arm_process_record);

These two problems appear frequently.

>> -int arm_handle_data_proc_misc_load_str_insn (void*);

I did not read closely, but I think most or maybe all of the functions
declared here should be static.  This applies to some other objects as
well, like arm_handle_insn.

Actually, in most cases, I think the code could be rearranged so that
you don't need forward declarations at all.

>> -  else if(ARM_INSN_SIZE_BYTES == insn_size)

Space after the "if" -- this happens a lot.

>> -  struct gdbarch_tdep *tdep = gdbarch_tdep ((struct gdbarch*) arm_insn_r-> 
>>gdbarch);

I think you don't need the cast here.
I think this occurs in a few places.

>> -  struct regcache *reg_cache = (struct regcache*) arm_insn_r->regcache;

Or here.  But if you needed something like this, there would have to be
a space before the "*".

>> -    /* data processing insn /multiply sinsn */    
>> -    if(9 == arm_insn_r->decode)

One thing I dislike about the x86 record code is the huge number of
constants.  I think this sort of thing is better if you use some
symbolic name instead.

One idea would be to share things with opcodes/arm-dis.c somehow.
I don't know if that is practical or not.

Actually, I have never understood why the process record stuff doesn't
share more code with the simulators.  Maybe that is just too much work
somehow.

And, whatever happened to the QEMU-based replay approach?  That seemed
promising to me.

>> -            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);

I think it is a little clearer to use the libiberty macros, e.g.:

  arm_insn_r->arm_regs = XNEWVEC (uint32_t, 3);

>> -  uint32_t reg_val1=0,reg_val2=0;

Spaces around the "=" signs.  This occurs in a few places.

Tom


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

* Re: [PATCH] arm reversible : progress <phase_2_complete>
  2011-04-10  9:41   ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
@ 2011-04-11  3:05     ` Yao Qi
  2011-04-11  4:52       ` paawan oza
  2011-04-16 21:03       ` paawan oza
  0 siblings, 2 replies; 32+ messages in thread
From: Yao Qi @ 2011-04-11  3:05 UTC (permalink / raw)
  To: gdb

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] 32+ messages in thread

* Re: [PATCH] arm reversible : progress <phase_2_complete>
  2011-04-11  3:05     ` Yao Qi
@ 2011-04-11  4:52       ` paawan oza
  2011-04-12 10:58         ` Yao Qi
  2011-04-16 21:03       ` paawan oza
  1 sibling, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-11  4:52 UTC (permalink / raw)
  To: Yao Qi, gdb

Hi Yao,

thanks for your comments.

1) will try to use macros for arm insns as you suggesed.

2) displaced_in_arm_mode and arm_frame_is_thumb checks T bit differenly, I do no 
follow frame unwind logic and checking T bit; 

infact the arm-reference-manual which I referred; I could not find 'M' profile 
information too.
hence I just checked current CSPR value.
bu yes as you said; I shall change the code;

3) as of now it I have support for arm and thumb(16) only. no plan for thumb32 
support.

4) please also refer to FIX ME in the code, specially how o read SPSR value ?

5) also need to know how to read coprocessor registers' value ?

Regards,
Oza.



----- 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] 32+ messages in thread

* Re: [PATCH] arm reversible : progress <phase_2_complete>
  2011-04-11  4:52       ` paawan oza
@ 2011-04-12 10:58         ` Yao Qi
  0 siblings, 0 replies; 32+ messages in thread
From: Yao Qi @ 2011-04-12 10:58 UTC (permalink / raw)
  To: gdb

On 04/11/2011 12:52 PM, paawan oza wrote:
> 5) also need to know how to read coprocessor registers' value ?

See gdb PR12602 "Support of coprocessor registers: cp14, cp15."
http://sourceware.org/bugzilla/show_bug.cgi?id=12602

It was opened some weeks ago.

-- 
Yao (齐尧)


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

* Re: [PATCH] arm reversible : progress <phase_2_complete>
  2011-04-11  3:05     ` Yao Qi
  2011-04-11  4:52       ` paawan oza
@ 2011-04-16 21:03       ` paawan oza
  2011-04-20 19:16         ` [PATCH] arm reversible : <phase_2_complete> paawan oza
  1 sibling, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-16 21:03 UTC (permalink / raw)
  To: Yao Qi, gdb, gdb-patches

Hi Yao,

I have incorporated your comments. please have a look.
currently patch suports

1) most of the arm insns  (except coprocessor support, extension space insns )
2) thumb insn (not thumb 2)

PS: phase 3 will have arm-linux abi support e.g. syscall support, signal etc...

Note: this mail is cc-ed to gdb-owner to resolve mailing list problem if any.
I am sorry Yao, if you are getting this patch multiple times. please bear with 
it as nobody else is getting this mail because of words filters @ gdb mailing 
list.


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] 32+ messages in thread

* [PATCH] arm reversible : <phase_2_complete>
  2011-04-16 21:03       ` paawan oza
@ 2011-04-20 19:16         ` paawan oza
  2011-04-21 20:55           ` Petr Hluzín
  0 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-20 19:16 UTC (permalink / raw)
  To: gdb, gdb-patches

Hi,

I am working on phase-3 now.
if anybody could please start reviewing phase-2 patch (as this is
independent of phase-3 and could be checked in independently too)
I may start implementing review comments as and when I get.
In Parallel, test cases are also being worked upon.
following is the phase-2 patch.

PATCH STARTS.

------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);

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


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

/* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-04-15 13:11:15.000000000 +0530
@@ -54,8 +54,11 @@
#include "gdb_assert.h"
#include "vec.h"

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

+
static int arm_debug;

/* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1692 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
}
+
+
+
+/* arm-reversible process reacord data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+typedef struct insn_decode_record_t
+{
+  struct gdbarch *gdbarch;
+  struct regcache *regcache;
+  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
+  uint32_t arm_insn;            /* should accomodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t id;                  /* type of insn.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  uint32_t *arm_regs;           /* registers to be saved for this record.  */
+  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */
+} insn_decode_record;
+
+
+static int
+SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+      
+  if (!len)
+    return 1;
+
+  if(!sbo)
+    ONES = ~ONES;
+
+  while (ONES)
+    {
+      if (!(ONES & sbo))
+        {
+          return 0;
+        }
+      ONES = ONES >> 1;
+    }
+  return 1;
+}
+
+static int 
+handle_extension_space (insn_decode_record *arm_record)
+{
+  insn_decode_record *arm_insn_r = arm_record;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+    
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+static int 
+arm_handle_data_proc_misc_load_str_insn (void *data)
+{
+
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+  uint32_t opcode1 = 0;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+  /* data processing insn /multiply insn.  */    
+  if ((9 == arm_insn_r->decode) 
+     && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+     ||  ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+    {
+      /* handle multiply instructions.  */
+      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
+        if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+          {
+            /* handle MLA and MUL.  */
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+           arm_insn_r->arm_regs[0] = 3;
+           arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+           arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+         }        
+      }
+  else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+        && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+      {
+        /* handle misc load insns, as 20th bit (L = 1).  */
+        /* LDR insn has a capability to do branching, if
+                  MOV LR, PC is precedded by LDR insn having Rn as R15 
+                  in that case, it emulates branch and link insn, and hence we 
+                  need to save CSPR and PC as well. I am not sure this is right 


+                  place as opcode = 010 LDR insn make this happen, if R15 was 
+                  used.  */
+        reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+        if (15 != reg_dest)
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+          }
+        else
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = reg_dest;
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+          }
+      }
+  else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+      && (SBO_SBZ (arm_insn_r->arm_insn, 5, 12, 0))
+      && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+      && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+    {
+      /* handle MSR insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }    
+      else
+      {
+        /* SPSR is going to be changed. */
+        /* Oza: FIX ME ? how to read SPSR value ?  */
+      }
+    }  
+  else if ((9 == arm_insn_r->decode) 
+           && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+           && (!bit (arm_insn_r->arm_insn,  INSN_S_L_BIT_NUM)))
+    {
+      /* Handling SWP, SWPB.  */
+      /* these insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+                              arm_mem_r)*2);
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      arm_insn_r->arm_mems[0].len = 1;
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          arm_insn_r->arm_mems[1].len = 4;
+        }
+        else
+        {  
+          /* SWPB insn, swaps only byte.  */
+          arm_insn_r->arm_mems[1].len = 1;
+        }
+      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);    
+    }
+  else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+           && (SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1)))
+    {
+      /* handle BLX, branch and link/exchange.  */
+      if (9 == arm_insn_r->opcode)
+      {
+        /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm, 
+                     and R14 stores the return address.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+        arm_insn_r->arm_regs[0] = 2;
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      }
+    }
+  else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+    {
+      /* handle enhanced software breakpoint insn, BKPT */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?  */
+    }  
+  else if ((11 == arm_insn_r->decode)
+          && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+  {
+    /* handle enhanced store insns and DSP insns (e.g. LDRD) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        printf("handling store insn, immed offfset insn\n");
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+      {
+        /* 2) store, register offset.  */
+        /* get Rm.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        /* get Rn.  */
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+      || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+      {
+        /* 3) store, immediate pre-indexed.  */            
+        /* 5)  store, immediate post-indexed.  */
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);  
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        offset_8 = (immed_high << 4) | immed_low;
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);  
+      }
+    else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+      || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+      {
+        /* 4) store, register pre-indexed.  */
+        /* 6) store, register post -indexed.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 
19);              

+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1))
+    {
+      /* handle BX, branch and link/exchange.  */
+      /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+    }  
+  else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 9, 4, 1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+    {
+      /* count leading zeros: CLZ.  */
+      printf("handling CLZ - count leading zero insn\n");
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+          && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+          && (SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+          && (SBO_SBZ (arm_insn_r->arm_insn, 1, 12, 0))
+          )
+    {      
+      /* handle MRS insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);  
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_data_proc_imm_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+       && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+       && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+       )
+    {
+      /* handle MSR insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         arm_insn_r->arm_regs[0] = 1;
+         arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+       }    
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }  
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
+      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)        
+      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
+      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+        {
+          /* store, immediate offset, immediate pre-indexed,
+                      immediate post-indexed.  */          
+          reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+          offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {  
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*2);
+          arm_insn_r->arm_mems[0].len = 1;
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:  
+              case 13:  
+              case 1:  
+              case 5:              
+                /* STR insn, STRT insn.  */
+                arm_insn_r->arm_mems[1].len = 4;    
+              break;  
+
+              case 10:
+              case 14:            
+              case 11:  
+              case 15:  
+              case 3:  
+              case 7:  
+                /* STRB insn, STRBT insn.  */
+                arm_insn_r->arm_mems[1].len = 1;    
+              break;  
+
+              default:
+                /* rest of the insns are unreachable for this addressing mode.  

*/
+              break;  
+            }      
+          arm_insn_r->arm_mems[1].addr = tgt_mem_addr;    
+          if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
+          || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+          || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
+          || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)          
+          || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+          || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+            {
+              /* we are handling pre-indexed mode; post-indexed mode;
+                             where Rn is going to be changed.  */
+              arm_insn_r->arm_regs = (uint32_t*)xmalloc 
(sizeof(uint32_t)*2);    

+              arm_insn_r->arm_regs[0] = 1;
+              arm_insn_r->arm_regs[1] = reg_src1;    
+            }  
+        }  
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  /* handle enhanced store insns and LDRD DSP insn,
+        let us begin according to addressing modes for store insns 
+        STRH insn.  */
+
+  /* LDR or STR?  */
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        } 
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)    
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
+    || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)        
+    || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
+    || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)        
+    || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+    || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+      {
+        if (! bits (arm_insn_r->arm_insn, 4, 11))
+          {
+            /* store insn, register offset and register pre-indexed, 
+                          register post-indexed.  */
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+            arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:  
+                case 13:  
+                case 1:  
+                case 5:              
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;  
+
+                case 10:
+                case 14:            
+                case 11:  
+                case 15:  
+                case 3:  
+                case 7:  
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;  
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;  
+              }      
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)        
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in pre-indexed mode and 
+                                post-indexed mode as well.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }    
+          }
+        else
+          {
+            /* store insn, scaled register offset; scaled pre-indexed.  */
+            offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            /* get shift_imm.  */
+            shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);  
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  /* unreachable.  */  
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }      
+            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)
+                        xmalloc (sizeof(struct arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:  
+                case 13:  
+                case 1:  
+                case 5:              
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;  
+
+                case 10:
+                case 14:            
+                case 11:  
+                case 15:  
+                case 3:  
+                case 7:  
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;  
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;  
+              }                  
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)    
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)    
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)        
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in register scaled pre-indexed 
+                                mode, and scaled post indexed mode.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }
+          }            
+      }  
+    }
+  return 0;  
+}
+
+static int 
+arm_hamdle_ld_st_multiple_insn (void *data)
+{  
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;      
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is chaging depending on W bit, but as of now we store Rn too wihtout 

going for 

+        optmization.  */
+
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* get Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      while (register_bits)
+       {
+         if (register_bits & 0x00000001)
+           register_list[register_count++] = 1;
+         register_bits = register_bits >> 1;
+       }
+      
+        /* extra space for Base Register and CPSR; wihtout optmization.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        arm_insn_r->arm_regs[0] = register_count + 2;
+        arm_insn_r->arm_regs[register_count+1] = reg_src1;
+        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+                arm_insn_r->arm_regs[index] = register_count;
+                index++;
+              }
+          }
+    }
+  else
+    {
+    /* it handles both STM(1) and STM(2).  */
+    addr_mode = bits (arm_insn_r->arm_insn, 23, 24);    
+
+    register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+    /* get Rn.  */
+    reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));  
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        default:
+          /* unreachable.  */    
+        break;    
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+    arm_insn_r->arm_regs[0] = 1;
+    arm_insn_r->arm_regs[1] = reg_src1;
+    }
+  return 0;  
+}
+
+static int 
+arm_handle_brn_insn (void *data)
+{
+  insn_decode_record *arm_insn_r = (insn_decode_record*) data; 
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  arm_insn_r->arm_regs[0] = 2;
+  arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+  
+  return 0;
+}
+
+static int 
+arm_handle_coproc_insn (void *data)
+{
+   return -1;  
+}
+
+static int 
+arm_handle_coproc_data_proc_insn (void *data)
+{
+
+   insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+  
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* handle SWI insn; system call would be handled over here.  */
+
+   arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+   if (15 == arm_insn_r->opcode) 
+   {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+    
+   return -1;  
+}
+
+
+static int 
+thumb_handle_shift_add_sub_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (  thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_add_sub_cmp_mov_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+  {
+    uint32_t s_word;
+    gdb_byte buf[4];
+  } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_ld_st_reg_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */ 
+      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+      opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);  
+      if ((opcode2 >= 12) && (opcode2 <= 15))
+        {        
+          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);          
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = reg_src1;
+        }
+      else if ((opcode2 >= 8) && (opcode2 <= 10))
+        {
+          /* STR(2), STRB(2), STRH(2) .  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+          reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          thumb_insn_r->arm_mems = (struct arm_mem_r *)  \
+                                    xmalloc (sizeof(struct arm_mem_r) * 2);
+          thumb_insn_r->arm_mems[0].len = 1; 
+          thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word; 
+          if (8 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 4;    /* STR (2).  */            
+          else if (10 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 2;    /* STRH (2).  */
+        }                
+      goto end;
+    }            
+  else if (bit (thumb_insn_r->arm_insn, 11))
+    {
+      /* handle load from literal pool.  */  
+      /* LDR(3).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);                          


+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+      goto end;
+    }
+    
+  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  if (opcode1)
+    {
+      opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+      opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if ((3 == opcode2) && (!opcode3))
+        {
+          /* branch with exchange.  */
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          thumb_insn_r->arm_regs[0] = 2;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+          thumb_insn_r->arm_regs[2] = reg_src1;
+        }
+    }
+  else
+    {
+      /* format 5; data processing insns.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if (bit (thumb_insn_r->arm_insn, 7))
+        {
+          reg_src1 = reg_src1 + 8;
+        }
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = reg_src1;
+    }  
+
+  end:
+  return 0;
+}
+
+static int 
+thumb_handle_ld_st_imm_offset_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+    }
+
+  return 0;
+}
+
+static int 
+thumb_hamdle_ld_st_stack_insn (void *data)
+{ 
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+    }
+  else if (0 == opcode)
+    {
+      /* STRH(1).  */
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 2;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+    }
+  return 0;
+}
+
+static int 
+thumb_handle_misc_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+  if (14 == opcode2)
+    {
+      /* POP.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        thumb_insn_r->arm_regs[0] = register_count + 2;
+        thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+        thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count + 1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+        thumb_insn_r->arm_regs[0] = 1;
+        thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  else if (0x1E == opcode1)
+    {
+      /* BKPT insn.  */
+      /* handle enhanced software breakpoint insn, BKPT.  */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter..  */
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?.  */
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }  
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  
+ 
+  return 0;
+}
+
+static int 
+thumb_handle_swi_insn (void *data)                
+{
+
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (1 == opcode2)
+    {
+
+      /* LDMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
2));
+        thumb_insn_r->arm_regs[0] = register_count + 1;
+        thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (0 == opcode2)
+    {
+      /* it handles both STMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count+1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            printf("handling syscall swi insn\n");
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record, 
+        as PC is saved there.  */
+  
+  return 0;
+}
+
+static int 
+thumb_handle_branch_insn (void *data)
+{
+  insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1=0;
+  uint32_t reg_src1=0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */  
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved 
+        there.  */
+  return 0;    
+}
+
+
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) = 
+  { 
+      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) = 
+  { 
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))    
+    {        
+      if (record_debug)
+        {
+          printf_unfiltered (_("Process record: error reading memory at "
+                               "addr %s len = %d.\n"),
+          paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+          return -1;
+        }
+    }
+  else if (ARM_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      arm_record->id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)? \
+            arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;  
+      arm_record->id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+    }
+  return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something is wrong..  */
+
+int 
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+                             CORE_ADDR insn_addr)
+{
+
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);  
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  uint32_t no_of_rec=0;
+  uint32_t ret=0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  memset (&arm_record, 0, sizeof (insn_decode_record));
+  arm_record.regcache = regcache;
+  arm_record.this_addr = insn_addr;
+  arm_record.gdbarch = gdbarch;
+
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+                                      "addr = %s\n",
+      paddress (gdbarch, arm_record.this_addr));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }  
+  /* record memories.  */
+  if (arm_record.arm_mems)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+       {
+          if (record_arch_list_add_mem \
+            ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+            arm_record.arm_mems[no_of_rec].len))
+            ret = -1;
+       }
+    }
+
+  if (record_arch_list_add_end ())
+    ret = -1;
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-04-15 13:11:15.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
};

/* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);

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

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


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-20 19:16         ` [PATCH] arm reversible : <phase_2_complete> paawan oza
@ 2011-04-21 20:55           ` Petr Hluzín
  2011-04-22  5:49             ` paawan oza
  0 siblings, 1 reply; 32+ messages in thread
From: Petr Hluzín @ 2011-04-21 20:55 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb, gdb-patches

On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
> Hi,
>
> I am working on phase-3 now.
> if anybody could please start reviewing phase-2 patch (as this is
> independent of phase-3 and could be checked in independently too)
> I may start implementing review comments as and when I get.
> In Parallel, test cases are also being worked upon.
> following is the phase-2 patch.

I took a peak and noticed the first points which looked suspicious to me.
Note: I am just a causal mailing-list observer.

> +
> +struct arm_mem_r
> +{
> +    uint32_t len;
> +    CORE_ADDR addr;
> +};
> +
> +typedef struct insn_decode_record_t
> +{
> +  struct gdbarch *gdbarch;
> +  struct regcache *regcache;
> +  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
> +  uint32_t arm_insn;            /* should accomodate thumb.  */
> +  uint32_t cond;                /* condition code.  */
> +  uint32_t id;                  /* type of insn.  */
> +  uint32_t opcode;              /* insn opcode.  */
> +  uint32_t decode;              /* insn decode bits.  */
> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */

This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

(Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
> +  {
> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */
> +  };
> +
> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction.  */
> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =

This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

> +  {
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */

Typo, hamdle

> +      thumb_handle_misc_insn,                  /* 101.  */
> +      thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */
> +  };

All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

There might be more, I just picked the first thing. I am not familiar
with the code base.

-- 
Petr Hluzin


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-21 20:55           ` Petr Hluzín
@ 2011-04-22  5:49             ` paawan oza
  2011-04-22  5:55               ` oza Pawandeep
                                 ` (2 more replies)
  0 siblings, 3 replies; 32+ messages in thread
From: paawan oza @ 2011-04-22  5:49 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr,

Thanks for your comments.

1) This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

Oza: I shall change it.

2) All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

Oza: this was leftover; as when I designed initially, I felt I would need any 
type of data.
but now it is uniform and I can certainly change to arm_record type.
thanks for pointing that out.

3) This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

oza: basically both arm_mems and arm_regs point to an array. could be documents 
in code.
what we do is:
first find out the registers and memories (where we require length also) in the 
beginning.
and at the end in process_record just go for recording.
in both arm_regs and arm_mems;  first array field provides only information 
about how many records are there.

4) (Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

Oza: can you please elaborate on that as I am not sure on what condition to 
assert ?

Regards,
Oza.




----- Original Message ----
From: Petr Hluzín <petr.hluzin@gmail.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb@sourceware.org; gdb-patches@sourceware.org
Sent: Fri, April 22, 2011 2:25:04 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
> Hi,
>
> I am working on phase-3 now.
> if anybody could please start reviewing phase-2 patch (as this is
> independent of phase-3 and could be checked in independently too)
> I may start implementing review comments as and when I get.
> In Parallel, test cases are also being worked upon.
> following is the phase-2 patch.

I took a peak and noticed the first points which looked suspicious to me.
Note: I am just a causal mailing-list observer.

> +
> +struct arm_mem_r
> +{
> +    uint32_t len;
> +    CORE_ADDR addr;
> +};
> +
> +typedef struct insn_decode_record_t
> +{
> +  struct gdbarch *gdbarch;
> +  struct regcache *regcache;
> +  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
> +  uint32_t arm_insn;            /* should accomodate thumb.  */
> +  uint32_t cond;                /* condition code.  */
> +  uint32_t id;                  /* type of insn.  */
> +  uint32_t opcode;              /* insn opcode.  */
> +  uint32_t decode;              /* insn decode bits.  */
> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */

This field points to array of 2 or register_count (which itself
changes). It might be worth documenting it points to array. (Pointers
are usually not used for pointer-arithmetics at my job.)
It is quite difficult to prove that accesses to arm_mems[] are within
allocated bounds.
Also some array elements are initialized only partially.

(Usually I add a struct field like debug_arm_mems_count and add
assertions at appropriate places.)

> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction.  */
> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
> +  {
> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
> +      arm_handle_data_proc_imm_insn,            /* 001.  */
> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
> +      arm_handle_brn_insn,                      /* 101.  */
> +      arm_handle_coproc_insn,                   /* 110.  */
> +      arm_handle_coproc_data_proc_insn          /* 111.  */
> +  };
> +
> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction.  */
> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =

This array is local to the function. If you mark it as static you
avoid its initialization in each invocation of the function.

> +  {
> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */

Typo, hamdle

> +      thumb_handle_misc_insn,                  /* 101.  */
> +      thumb_handle_swi_insn,                   /* 110.  */
> +      thumb_handle_branch_insn                 /* 111.  */
> +  };

All the functions are called only from this module (only from this
function). If you make their arguments type-safe (not void*), you will
get less code. (And type-safety, obviously.)

There might be more, I just picked the first thing. I am not familiar
with the code base.

-- 
Petr Hluzin


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-22  5:49             ` paawan oza
@ 2011-04-22  5:55               ` oza Pawandeep
  2011-04-25 14:03               ` paawan oza
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
  2 siblings, 0 replies; 32+ messages in thread
From: oza Pawandeep @ 2011-04-22  5:55 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr,

If you could look at the rest of the code and provide your comments it
would be great too.

Note: I am mallocing regs and mems scattered in the code, planning to
organise it too in some way.

Regards,
Oza.

On Fri, Apr 22, 2011 at 11:19 AM, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr,
>
> Thanks for your comments.
>
> 1) This array is local to the function. If you mark it as static you
> avoid its initialization in each invocation of the function.
>
> Oza: I shall change it.
>
> 2) All the functions are called only from this module (only from this
> function). If you make their arguments type-safe (not void*), you will
> get less code. (And type-safety, obviously.)
>
> Oza: this was leftover; as when I designed initially, I felt I would need any
> type of data.
> but now it is uniform and I can certainly change to arm_record type.
> thanks for pointing that out.
>
> 3) This field points to array of 2 or register_count (which itself
> changes). It might be worth documenting it points to array. (Pointers
> are usually not used for pointer-arithmetics at my job.)
> It is quite difficult to prove that accesses to arm_mems[] are within
> allocated bounds.
> Also some array elements are initialized only partially.
>
> oza: basically both arm_mems and arm_regs point to an array. could be documents
> in code.
> what we do is:
> first find out the registers and memories (where we require length also) in the
> beginning.
> and at the end in process_record just go for recording.
> in both arm_regs and arm_mems;  first array field provides only information
> about how many records are there.
>
> 4) (Usually I add a struct field like debug_arm_mems_count and add
> assertions at appropriate places.)
>
> Oza: can you please elaborate on that as I am not sure on what condition to
> assert ?
>
> Regards,
> Oza.
>
>
>
>
> ----- Original Message ----
> From: Petr Hluzín <petr.hluzin@gmail.com>
> To: paawan oza <paawan1982@yahoo.com>
> Cc: gdb@sourceware.org; gdb-patches@sourceware.org
> Sent: Fri, April 22, 2011 2:25:04 AM
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>
> On 20 April 2011 21:16, paawan oza <paawan1982@yahoo.com> wrote:
>> Hi,
>>
>> I am working on phase-3 now.
>> if anybody could please start reviewing phase-2 patch (as this is
>> independent of phase-3 and could be checked in independently too)
>> I may start implementing review comments as and when I get.
>> In Parallel, test cases are also being worked upon.
>> following is the phase-2 patch.
>
> I took a peak and noticed the first points which looked suspicious to me.
> Note: I am just a causal mailing-list observer.
>
>> +
>> +struct arm_mem_r
>> +{
>> +    uint32_t len;
>> +    CORE_ADDR addr;
>> +};
>> +
>> +typedef struct insn_decode_record_t
>> +{
>> +  struct gdbarch *gdbarch;
>> +  struct regcache *regcache;
>> +  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
>> +  uint32_t arm_insn;            /* should accomodate thumb.  */
>> +  uint32_t cond;                /* condition code.  */
>> +  uint32_t id;                  /* type of insn.  */
>> +  uint32_t opcode;              /* insn opcode.  */
>> +  uint32_t decode;              /* insn decode bits.  */
>> +  uint32_t *arm_regs;           /* registers to be saved for this record.  */
>> +  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */
>
> This field points to array of 2 or register_count (which itself
> changes). It might be worth documenting it points to array. (Pointers
> are usually not used for pointer-arithmetics at my job.)
> It is quite difficult to prove that accesses to arm_mems[] are within
> allocated bounds.
> Also some array elements are initialized only partially.
>
> (Usually I add a struct field like debug_arm_mems_count and add
> assertions at appropriate places.)
>
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>> +{
>> +
>> +  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
>> instruction.  */
>> +  int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
>> +  {
>> +      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
>> +      arm_handle_data_proc_imm_insn,            /* 001.  */
>> +      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
>> +      arm_handle_ld_st_reg_offset_insn,         /* 011.  */
>> +      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
>> +      arm_handle_brn_insn,                      /* 101.  */
>> +      arm_handle_coproc_insn,                   /* 110.  */
>> +      arm_handle_coproc_data_proc_insn          /* 111.  */
>> +  };
>> +
>> +  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
>> instruction.  */
>> +  int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =
>
> This array is local to the function. If you mark it as static you
> avoid its initialization in each invocation of the function.
>
>> +  {
>> +      thumb_handle_shift_add_sub_insn,         /* 000.  */
>> +      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
>> +      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
>> +      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */
>> +      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
>
> Typo, hamdle
>
>> +      thumb_handle_misc_insn,                  /* 101.  */
>> +      thumb_handle_swi_insn,                   /* 110.  */
>> +      thumb_handle_branch_insn                 /* 111.  */
>> +  };
>
> All the functions are called only from this module (only from this
> function). If you make their arguments type-safe (not void*), you will
> get less code. (And type-safety, obviously.)
>
> There might be more, I just picked the first thing. I am not familiar
> with the code base.
>
> --
> Petr Hluzin
>
>


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-22  5:49             ` paawan oza
  2011-04-22  5:55               ` oza Pawandeep
@ 2011-04-25 14:03               ` paawan oza
  2011-05-01  1:20                 ` Petr Hluzín
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
  2 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-25 14:03 UTC (permalink / raw)
  To: Petr Hluzín, gdb, gdb-patches

Hi Petr,

I have implemented your review comments.

PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate xmallocs, but I am 
not sure whether to go for that macros or
leave the implementation of reg/mem allcoation scattered across code calling 
xmalloc.



PATCH
---------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-04-25 18:43:44.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record */
+  set_gdbarch_process_record(gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-04-25 18:43:44.000000000 +0530
@@ -54,8 +54,11 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
+
 static int arm_debug;
 
 /* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1706 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
 }
+
+
+
+/* arm-reversible process reacord data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(LENGTH,RECORD_BUF) \
+  do  \
+    { \
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*(LENGTH+1));\
+      arm_insn_r->arm_regs[0] = LENGTH; \
+      while(LENGTH) \
+        { \
+          arm_insn_r->arm_regs[LENGTH] = RECORD_BUF[LENGTH-1];  \
+          LENGTH--;  \
+        } \
+    } \
+while (0)
+
+#define MEM_ALLOC(LENGTH,RECORD_BUF) \
+  do  \
+    { \
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct \
+                              arm_mem_r) * (LENGTH+1)); \
+      arm_insn_r->arm_mems[0].len = LENGTH;  \
+      while(LENGTH) \
+        { \
+          arm_insn_r->arm_mems[LENGTH].addr = RECORD_BUF[(LENGTH * 2) - 1];  \
+          arm_insn_r->arm_mems[LENGTH].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+          LENGTH--;   \
+        } \
+    } \
+  while (0)
+
+
+struct arm_mem_r
+{
+    uint32_t len;
+    CORE_ADDR addr;
+};
+
+typedef struct insn_decode_record_t
+{
+  struct gdbarch *gdbarch;
+  struct regcache *regcache;
+  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
+  uint32_t arm_insn;            /* should accomodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t id;                  /* type of insn.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  uint32_t *arm_regs;           /* registers to be saved for this record.  */
+  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */
+} insn_decode_record;
+
+
+static int
+SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+      
+  if (!len)
+    return 1;
+
+  if(!sbo)
+    ONES = ~ONES;
+
+  while (ONES)
+    {
+      if (!(ONES & sbo))
+        {
+          return 0;
+        }
+      ONES = ONES >> 1;
+    }
+  return 1;
+}
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+    
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+static int 
+arm_handle_data_proc_misc_load_str_insn   \
+(insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_length=0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+  uint32_t opcode1 = 0;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+  /* data processing insn /multiply insn.  */     
+  if ((9 == arm_insn_r->decode) 
+     && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+     ||  ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+    {
+      /* handle multiply instructions.  */
+      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
+        if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+          {
+            /* handle MLA and MUL.  */
+            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+            record_buf[1] = ARM_PS_REGNUM;
+            record_length = 2;
+            REG_ALLOC (record_length, record_buf);
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+           arm_insn_r->arm_regs[0] = 3;
+           arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+           arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+           arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;  
+         }        
+      }
+  else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+        && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+      {
+        /* handle misc load insns, as 20th bit (L = 1).  */
+        /* LDR insn has a capability to do branching, if
+                  MOV LR, PC is precedded by LDR insn having Rn as R15 
+                  in that case, it emulates branch and link insn, and hence we 
+                  need to save CSPR and PC as well. I am not sure this is right 

+                  place as opcode = 010 LDR insn make this happen, if R15 was 
+                  used.  */
+        reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+        if (15 != reg_dest)
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+            arm_insn_r->arm_regs[0] = 1;
+            arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+          }
+        else
+          {
+            arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+            arm_insn_r->arm_regs[0] = 2;
+            arm_insn_r->arm_regs[1] = reg_dest;
+            arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+          }
+      }
+  else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+      && (SBO_SBZ (arm_insn_r->arm_insn, 5, 12, 0))
+      && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+      && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+    {
+      /* handle MSR insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }    
+      else
+      {
+        /* SPSR is going to be changed. */
+        /* Oza: FIX ME ? how to read SPSR value ?  */
+      }
+    }   
+  else if ((9 == arm_insn_r->decode) 
+           && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+           && (!bit (arm_insn_r->arm_insn,  INSN_S_L_BIT_NUM)))
+    {
+      /* Handling SWP, SWPB.  */
+      /* these insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+                              arm_mem_r)*2);
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      arm_insn_r->arm_mems[0].len = 1;
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          arm_insn_r->arm_mems[1].len = 4;
+        }
+        else
+        {   
+          /* SWPB insn, swaps only byte.  */
+          arm_insn_r->arm_mems[1].len = 1;
+        }
+      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);    
+    }
+  else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+           && (SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1)))
+    {
+      /* handle BLX, branch and link/exchange.  */
+      if (9 == arm_insn_r->opcode)
+      {
+        /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm, 
+                     and R14 stores the return address.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+        arm_insn_r->arm_regs[0] = 2;
+        arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      }
+    }
+  else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+    {
+      /* handle enhanced software breakpoint insn, BKPT */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?  */
+    }  
+  else if ((11 == arm_insn_r->decode)
+          && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+  {
+    /* handle enhanced store insns and DSP insns (e.g. LDRD) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        printf("handling store insn, immed offfset insn\n");
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+      {
+        /* 2) store, register offset.  */
+        /* get Rm.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        /* get Rn.  */
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+      }
+    else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+      || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+      {
+        /* 3) store, immediate pre-indexed.  */            
+        /* 5)  store, immediate post-indexed.  */
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);  
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        offset_8 = (immed_high << 4) | immed_low;
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);  
+      }
+    else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+      || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+      {
+        /* 4) store, register pre-indexed.  */
+        /* 6) store, register post -indexed.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+        arm_insn_r->arm_mems[0].len = 1;
+        arm_insn_r->arm_mems[1].len = 2;
+        arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+        /* record Rn also as it changes.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+        arm_insn_r->arm_regs[0] = 1;
+        arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 
19);              

+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1))
+    {
+      /* handle BX, branch and link/exchange.  */
+      /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+    }  
+  else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 9, 4, 1)
+           && SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+    {
+      /* count leading zeros: CLZ.  */
+      printf("handling CLZ - cunt leading zero insn\n");
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+    }
+  else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+          && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+          && (SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+          && (SBO_SBZ (arm_insn_r->arm_insn, 1, 12, 0))
+          )
+    {      
+      /* handle MRS insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      arm_insn_r->arm_regs[0] = 1;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);  
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+       && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+       && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+       )
+    {
+      /* handle MSR insn.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         arm_insn_r->arm_regs[0] = 1;
+         arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+       }    
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }   
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      arm_insn_r->arm_regs[0] = 2;
+      arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;        
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)         
+      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+        {
+          /* store, immediate offset, immediate pre-indexed,
+                      immediate post-indexed.  */          
+          reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+          offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*2);
+          arm_insn_r->arm_mems[0].len = 1;
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                arm_insn_r->arm_mems[1].len = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                arm_insn_r->arm_mems[1].len = 1;    
+              break;   
+
+              default:
+                /* rest of the insns are unreachable for this addressing mode.  
*/
+              break;   
+            }       
+          arm_insn_r->arm_mems[1].addr = tgt_mem_addr;    
+          if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+          || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+          || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+          || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)          
+          || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+          || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+            {
+              /* we are handling pre-indexed mode; post-indexed mode;
+                             where Rn is going to be changed.  */
+              arm_insn_r->arm_regs = (uint32_t*)xmalloc 
(sizeof(uint32_t)*2);     

+              arm_insn_r->arm_regs[0] = 1;
+              arm_insn_r->arm_regs[1] = reg_src1;    
+            }  
+        }  
+    }
+  return 0;
+}
+
+static int 
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  /* handle enhanced store insns and LDRD DSP insn,
+        let us begin according to addressing modes for store insns 
+        STRH insn.  */
+
+  /* LDR or STR?  */
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          arm_insn_r->arm_regs[0] = 1;
+          arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+        }
+      else
+        {
+          arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          arm_insn_r->arm_regs[0] = 2;
+          arm_insn_r->arm_regs[1] = reg_dest;
+          arm_insn_r->arm_regs[2] = ARM_PS_REGNUM; 
+        } 
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+    || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)         
+    || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+    || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+    || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+    || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+      {
+        if (! bits (arm_insn_r->arm_insn, 4, 11))
+          {
+            /* store insn, register offset and register pre-indexed, 
+                          register post-indexed.  */
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+            arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;   
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;   
+              }       
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in pre-indexed mode and 
+                                post-indexed mode as well.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }     
+          }
+        else
+          {
+            /* store insn, scaled register offset; scaled pre-indexed.  */
+            offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            /* get shift_imm.  */
+            shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  /* unreachable.  */  
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }       
+            
+            arm_insn_r->arm_mems = (struct arm_mem_r *)
+                        xmalloc (sizeof(struct arm_mem_r)*2);
+            arm_insn_r->arm_mems[0].len = 1;
+            arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  arm_insn_r->arm_mems[1].len = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  arm_insn_r->arm_mems[1].len = 1;    
+                break;   
+
+                default:
+                  /* rest of the insns are unreachable for this addr mode.  */
+                break;   
+              }                   
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                arm_insn_r->arm_regs = \
+                (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+                arm_insn_r->arm_regs[0] = 1;
+                /* Rn is going to be changed in register scaled pre-indexed 
+                                mode, and scaled post indexed mode.  */
+                arm_insn_r->arm_regs[1] = reg_src2;  
+              }
+          }            
+      }  
+    }
+  return 0;   
+}
+
+static int 
+arm_hamdle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{   
+  struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;       
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is chaging depending on W bit, but as of now we store Rn too wihtout 
going for 

+        optmization.  */
+
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* get Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      while (register_bits)
+       {
+         if (register_bits & 0x00000001)
+           register_list[register_count++] = 1;
+         register_bits = register_bits >> 1;
+       }
+      
+        /* extra space for Base Register and CPSR; wihtout optmization.  */
+        arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        arm_insn_r->arm_regs[0] = register_count + 2;
+        arm_insn_r->arm_regs[register_count+1] = reg_src1;
+        arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+                arm_insn_r->arm_regs[index] = register_count;
+                index++;
+              }
+          }
+    }
+  else
+    {
+    /* it handles both STM(1) and STM(2).  */
+    addr_mode = bits (arm_insn_r->arm_insn, 23, 24);    
+
+    register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+    /* get Rn.  */
+    reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));   
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+          arm_mem_r)*(register_count+1));
+          arm_insn_r->arm_mems[0].len = register_count;
+          while (register_count)
+            {
+              arm_insn_r->arm_mems[register_count].addr = start_address;
+              arm_insn_r->arm_mems[register_count].len = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+        break;    
+
+        default:
+          /* unreachable.  */    
+        break;    
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+    arm_insn_r->arm_regs[0] = 1;
+    arm_insn_r->arm_regs[1] = reg_src1;
+    }
+  return 0;   
+}
+
+static int 
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  arm_insn_r->arm_regs[0] = 2;
+  arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+  
+  return 0;
+}
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+   return -1;   
+}
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* handle SWI insn; system call would be handled over here.  */
+
+   arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+   if (15 == arm_insn_r->opcode) 
+   {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+     
+   return -1;   
+}
+
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (  thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;   
+}
+
+static int 
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0;
+
+
+  union
+  {
+    uint32_t s_word;
+    gdb_byte buf[4];
+  } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = reg_src1;
+
+  return 0;  
+}
+
+static int 
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */ 
+      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+      opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);  
+      if ((opcode2 >= 12) && (opcode2 <= 15))
+        {         
+          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);           
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = reg_src1;
+        }
+      else if ((opcode2 >= 8) && (opcode2 <= 10))
+        {
+          /* STR(2), STRB(2), STRH(2) .  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+          reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          thumb_insn_r->arm_mems = (struct arm_mem_r *)  \
+                                    xmalloc (sizeof(struct arm_mem_r) * 2);
+          thumb_insn_r->arm_mems[0].len = 1; 
+          thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word; 
+          if (8 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 4;    /* STR (2).  */             
+          else if (10 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            thumb_insn_r->arm_mems[0].len = 2;    /* STRH (2).  */
+        }                 
+      goto end;
+    }            
+  else if (bit (thumb_insn_r->arm_insn, 11))
+    {
+      /* handle load from literal pool.  */  
+      /* LDR(3).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);                          

+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+      goto end;
+    }
+    
+  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  if (opcode1)
+    {
+      opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+      opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if ((3 == opcode2) && (!opcode3))
+        {
+          /* branch with exchange.  */
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+          thumb_insn_r->arm_regs[0] = 1;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+          thumb_insn_r->arm_regs[0] = 2;
+          thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+          thumb_insn_r->arm_regs[2] = reg_src1;
+        }
+    }
+  else
+    {
+      /* format 5; data processing insns.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if (bit (thumb_insn_r->arm_insn, 7))
+        {
+          reg_src1 = reg_src1 + 8;
+        }
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = reg_src1;
+    }  
+
+  end:
+  return 0;
+}
+
+static int 
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+    }
+
+  return 0;
+}
+
+static int 
+thumb_hamdle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{ 
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 4;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+    }
+  else if (0 == opcode)
+    {
+      /* STRH(1).  */
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+        arm_mem_r)*2);
+      thumb_insn_r->arm_mems[0].len = 1;
+      thumb_insn_r->arm_mems[1].len = 2;
+      thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+    }
+  return 0;
+}
+
+static int 
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+  if (14 == opcode2)
+    {
+      /* POP.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
3));
+        thumb_insn_r->arm_regs[0] = register_count + 2;
+        thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+        thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count + 1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+        thumb_insn_r->arm_regs[0] = 1;
+        thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  else if (0x1E == opcode1)
+    {
+      /* BKPT insn.  */
+      /* handle enhanced software breakpoint insn, BKPT.  */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter..  */
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+      thumb_insn_r->arm_regs[0] = 2;
+      thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+      thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+      /* save SPSR also; how?.  */
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = reg_src1;
+    }  
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+      thumb_insn_r->arm_regs[0] = 1;
+      thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+    }
+  
+ 
+  return 0;
+}
+
+static int 
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (1 == opcode2)
+    {
+
+      /* LDMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+        thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+                                      (sizeof(uint32_t) * (register_count + 
2));
+        thumb_insn_r->arm_regs[0] = register_count + 1;
+        thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              thumb_insn_r->arm_regs[index] = register_count;
+              index++;
+            }
+        }
+    }
+  else if (0 == opcode2)
+    {
+      /* it handles both STMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct 
+      arm_mem_r)*(register_count+1));
+      thumb_insn_r->arm_mems[0].len = register_count;
+      while (register_count)
+        {
+          thumb_insn_r->arm_mems[register_count].addr = start_address;
+          thumb_insn_r->arm_mems[register_count].len = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            printf("handling syscall swi insn\n");
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record, 
+        as PC is saved there.  */
+  
+  return 0;
+}
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1=0;
+  uint32_t reg_src1=0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */  
+  thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+  thumb_insn_r->arm_regs[0] = 2;
+  thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+  thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved 
+        there.  */
+  return 0;     
+}
+
+
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) \
+                                    (insn_decode_record*) = 
+  { 
+      arm_handle_data_proc_misc_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_hamdle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) \
+                                      (insn_decode_record*) = 
+  { 
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_hamdle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))    
+    {        
+      if (record_debug)
+        {
+          printf_unfiltered (_("Process record: error reading memory at "
+                               "addr %s len = %d.\n"),
+          paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+          return -1;
+        }
+    }
+  else if (ARM_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      arm_record->id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond)? \
+            arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;  
+      arm_record->id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+    }
+  return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something is wrong..  */
+
+int 
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+                             CORE_ADDR insn_addr)
+{
+
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);  
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  uint32_t no_of_rec=0;
+  uint32_t ret=0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  memset (&arm_record, 0, sizeof (insn_decode_record));
+  arm_record.regcache = regcache;
+  arm_record.this_addr = insn_addr;
+  arm_record.gdbarch = gdbarch;
+
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+                                      "addr = %s\n",
+      paddress (gdbarch, arm_record.this_addr));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }   
+  /* record memories.  */
+  if (arm_record.arm_mems)
+    {
+      for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+       {
+          if (record_arch_list_add_mem \
+            ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+            arm_record.arm_mems[no_of_rec].len))
+            ret = -1;
+       }
+    }
+
+  if (record_arch_list_add_end ())
+    ret = -1;
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-04-25 18:43:44.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi args.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified


Regards,
Oza.


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

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]               ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
@ 2011-04-25 19:57                 ` Tom Tromey
  2011-04-28 18:26                   ` paawan oza
  0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2011-04-25 19:57 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

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

Oza> PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate
Oza> xmallocs, but I am not sure whether to go for that macros or leave
Oza> the implementation of reg/mem allcoation scattered across code
Oza> calling xmalloc.

I saw one use of REG_ALLOC and none of MEM_ALLOC.
If you intend to just have a single use it is probably better to just
drop the macros.

But, maybe you intend to use these universally through the code.
That would be fine.

Oza> +  /* Enable process record */

Period plus two spaces at the end of a comment.

Oza> +  set_gdbarch_process_record(gdbarch, arm_process_record);

Space before an open paren.

There are a lot of small formatting problems in this patch.

Oza>  #include "features/arm-with-m.c"
 
Oza> +
Oza>  static int arm_debug;

Adding a blank line for no reason.

Oza> +/* arm-reversible process reacord data structures.  */

Surely it should be "ARM".

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;
Oza> +    CORE_ADDR addr;
Oza> +};

Wrong formatting.  The struct needs documentation and so do its fields.

Oza> +
Oza> +static int
Oza> +SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)

A new function needs a documentation comment.
Uppercase function names need special pleading.

Oza> +  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));

Likewise locals.

Oza> +static int 
Oza> +arm_handle_data_proc_misc_load_str_insn   \
Oza> +(insn_decode_record *arm_insn_r)

Bad formatting.

Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];

There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:

Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;

It seems to me that extract_typed_address or something similar would be
better.

I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza> +       /* SPSR is going to be changed.  */
Oza> +       /* Oza: FIX ME ? how to read SPSR value?  */

There are a few comments in this style.

First, don't put your name into comments.

Second, I think instead of new "FIXME" comments, new code should either
just work, or call error and have an explanatory comment.


I can't really comment on the details of the implementation.  I don't
know much about either ARM or process record.  It seems basically
reasonable; I prefer a somewhat more symbolic style, but I understand
that the x86 process record code is also written with many manifest
constants.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-25 19:57                 ` Tom Tromey
@ 2011-04-28 18:26                   ` paawan oza
  2011-04-28 19:00                     ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-28 18:26 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

Hi Tom,

I have implemented all the comments, except one thing I am not sure.

Tom's comments
Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];
There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:
Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
It seems to me that extract_typed_address or something similar would be
better.
I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza's query;

1)  are suggesting to use something else than unions ? whatever you have 
described about union is right.

2)  why could I use extract_typed_address instead of direct assignment ?

3)  in my understanding cross debug would not affect endianess because all the 
record saving done on target memory and played back in target memory.
they never get fetched to host machine I think.
please clarify how would it affect host/target endianness issue ?
I am confused.


Regards,
Oza.















----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: Petr Hluzín <petr.hluzin@gmail.com>; gdb@sourceware.org; 
gdb-patches@sourceware.org
Sent: Tue, April 26, 2011 1:27:17 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>

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

Oza> PS: I have added REG_ALLOC and MEM_ALLOC macors to accumulate
Oza> xmallocs, but I am not sure whether to go for that macros or leave
Oza> the implementation of reg/mem allcoation scattered across code
Oza> calling xmalloc.

I saw one use of REG_ALLOC and none of MEM_ALLOC.
If you intend to just have a single use it is probably better to just
drop the macros.

But, maybe you intend to use these universally through the code.
That would be fine.

Oza> +  /* Enable process record */

Period plus two spaces at the end of a comment.

Oza> +  set_gdbarch_process_record(gdbarch, arm_process_record);

Space before an open paren.

There are a lot of small formatting problems in this patch.

Oza>  #include "features/arm-with-m.c"

Oza> +
Oza>  static int arm_debug;

Adding a blank line for no reason.

Oza> +/* arm-reversible process reacord data structures.  */

Surely it should be "ARM".

Oza> +struct arm_mem_r
Oza> +{
Oza> +    uint32_t len;
Oza> +    CORE_ADDR addr;
Oza> +};

Wrong formatting.  The struct needs documentation and so do its fields.

Oza> +
Oza> +static int
Oza> +SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)

A new function needs a documentation comment.
Uppercase function names need special pleading.

Oza> +  uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));

Likewise locals.

Oza> +static int 
Oza> +arm_handle_data_proc_misc_load_str_insn   \
Oza> +(insn_decode_record *arm_insn_r)

Bad formatting.

Oza> +  union
Oza> +    {
Oza> +      uint32_t s_word;
Oza> +      gdb_byte buf[4];
Oza> +    } u_buf[2];

There are lots of these little unions in the code.
From what I can tell, this is mostly to read target memory into the
array, then convert to a scalar like:

Oza> +      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
[...]
Oza> +      arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;

It seems to me that extract_typed_address or something similar would be
better.

I'm not very familiar with the target record stuff; but if it is
possible to cross-debug and use it, then this code does not seem to
account for host/target endian differences.

Oza> +       /* SPSR is going to be changed.  */
Oza> +       /* Oza: FIX ME ? how to read SPSR value?  */

There are a few comments in this style.

First, don't put your name into comments.

Second, I think instead of new "FIXME" comments, new code should either
just work, or call error and have an explanatory comment.


I can't really comment on the details of the implementation.  I don't
know much about either ARM or process record.  It seems basically
reasonable; I prefer a somewhat more symbolic style, but I understand
that the x86 process record code is also written with many manifest
constants.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 18:26                   ` paawan oza
@ 2011-04-28 19:00                     ` Tom Tromey
  2011-04-28 19:22                       ` paawan oza
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
  0 siblings, 2 replies; 32+ messages in thread
From: Tom Tromey @ 2011-04-28 19:00 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

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

Tom> It seems to me that extract_typed_address or something similar would be
Tom> better.

Oza> 1)  are suggesting to use something else than unions ? whatever you have 
Oza> described about union is right.

Oza> 2)  why could I use extract_typed_address instead of direct assignment ?

extract_typed_address handles endianess and conversion from "array of
bytes" to "host scalar".

Oza> 3) in my understanding cross debug would not affect endianess
Oza> because all the record saving done on target memory and played back
Oza> in target memory.  they never get fetched to host machine I think.
Oza> please clarify how would it affect host/target endianness issue ?

Here is a snippet from the patch:

+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
[...]
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Here, this fetches the raw register bits from the cache, which, IIUC,
are in target order.  Then it uses the union to turn this into a scalar,
and does math on the scalar value.

So, if the host and target endianness differ, you will get the wrong
result.

Maybe I am missing something here?

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 19:00                     ` Tom Tromey
@ 2011-04-28 19:22                       ` paawan oza
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
  1 sibling, 0 replies; 32+ messages in thread
From: paawan oza @ 2011-04-28 19:22 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

but whole operation happens on target memory, so 

after 
GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

we get scalar u_buf.s_word again in big-endian.


+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

and above math is again in target memory in big endian machine and record is 
saved to target memory.

I think it never gets fetched to host for any reason, Am I thinking correct?

Regards,
Oza.



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

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

Tom> It seems to me that extract_typed_address or something similar would be
Tom> better.

Oza> 1)  are suggesting to use something else than unions ? whatever you have 
Oza> described about union is right.

Oza> 2)  why could I use extract_typed_address instead of direct assignment ?

extract_typed_address handles endianess and conversion from "array of
bytes" to "host scalar".

Oza> 3) in my understanding cross debug would not affect endianess
Oza> because all the record saving done on target memory and played back
Oza> in target memory.  they never get fetched to host machine I think.
Oza> please clarify how would it affect host/target endianness issue ?

Here is a snippet from the patch:

+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
[...]
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Here, this fetches the raw register bits from the cache, which, IIUC,
are in target order.  Then it uses the union to turn this into a scalar,
and does math on the scalar value.

So, if the host and target endianness differ, you will get the wrong
result.

Maybe I am missing something here?

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
       [not found]                       ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
@ 2011-04-28 19:36                         ` Tom Tromey
  2011-04-30 16:16                           ` paawan oza
  0 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2011-04-28 19:36 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

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

Oza> but whole operation happens on target memory, so 
Oza> after 
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

Oza> we get scalar u_buf.s_word again in big-endian.

Oza> +      start_address = u_buf.s_word -  \
Oza> +                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;

Oza> and above math is again in target memory in big endian machine and
Oza> record is saved to target memory.

Oza> I think it never gets fetched to host for any reason, Am I thinking
Oza> correct?

No, sorry.  Any code in gdb is by running on the host system.

So, GET_REG_VAL fetches the raw register -- from the target to the host.
`u_buf.s_word' is a scalar value in gdb, i.e., on the host.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-28 19:36                         ` Tom Tromey
@ 2011-04-30 16:16                           ` paawan oza
  2011-05-02 13:28                             ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: paawan oza @ 2011-04-30 16:16 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Petr Hluzín, gdb, gdb-patches

Hi Tom,

So you are suggesting;

GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
if (target is big endian)
  {
        convert_big_to_little (u_buf.s_word)
  }


something like above ?
right ?

and while replaying do I need to convert it to big endian ?
somethig like that ?

Regards,
Oza.


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

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

Oza> but whole operation happens on target memory, so 
Oza> after 
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);

Oza> we get scalar u_buf.s_word again in big-endian.

Oza> +      start_address = u_buf.s_word -  \
Oza> +                   (4 * (bit (thumb_insn_r->arm_insn, 8) + 
register_count)) ;

Oza> and above math is again in target memory in big endian machine and
Oza> record is saved to target memory.

Oza> I think it never gets fetched to host for any reason, Am I thinking
Oza> correct?

No, sorry.  Any code in gdb is by running on the host system.

So, GET_REG_VAL fetches the raw register -- from the target to the host.
`u_buf.s_word' is a scalar value in gdb, i.e., on the host.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-25 14:03               ` paawan oza
@ 2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
                                     ` (2 more replies)
  0 siblings, 3 replies; 32+ messages in thread
From: Petr Hluzín @ 2011-05-01  1:20 UTC (permalink / raw)
  To: paawan oza; +Cc: gdb, gdb-patches

On 25 April 2011 16:03, paawan oza <paawan1982@yahoo.com> wrote:
> Hi Petr,
>
> I have implemented your review comments.

Typo "hamdle" in thumb_hamdle_ld_st_stack_insn() still exists.

I decoded the `arm_mem_r *arm_mems' strucutre:

arm_mems[0].len - is number of valid records `arm_mems[i]' after [0].
arm_mems[i].len - is number of bytes modified by the instruction.
arm_mems[0].addr - is undefined (never written, never read) - except
on line: thumb_insn_r->arm_mems[0].addr =
u_buf[0].s_word+u_buf[1].s_word;
arm_mems[i].addr - is target address of the modified block (for i=1..)

This is reusing field arm_mem_r::len for two different things.
This is ugly.

Move the counter into insn_decode_record_t. Or use struct arm_mem_r {
	int count;
	struct {
		uint32_t len;
		CORE_ADDR addr;
	} array[0];
}

Each instance of insn_decode_record_t is allocated and freed before
new instance is allocated, therefore its size does not matter.

The same applies for arm_record.arm_regs[].


> +/* arm-reversible process reacord data structures.  */

Typo, reacord.


> +#define THUMB2_INSN_SIZE_BYTES 4

Not used.
In decode_insn() I suggest adding
   else if (THUMB_INSN_SIZE_BYTES == insn_size)
     {
       arm_record->arm_insn = u_buf.s_word;
       arm_record->id = bits (arm_record->arm_insn, 13, 15);
       ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
     }
+  else if THUMB2_INSN_SIZE_BYTES == insn_size)
+    // not implemented, maybe complain loudly
+  else
+    assert(false);

This would document the possible values.


+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)

This is used only at two places:

+  ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+  if (arm_record.arm_regs)
+    {
+      for (no_of_rec=1; no_of_rec<=arm_record.arm_regs[0]; no_of_rec++)
+        {
+          if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+          ret = -1;
+        }
+    }

This saves only few characters and no lines of code.
But adds an indirection and hides use of local variable 'arm_record'.
Also the caller already contains record_arch_list_add_* functions.


Structure insn_decode_record:

> +
> + typedef struct insn_decode_record_t {
> +   uint32_t arm_insn;            /* should accomodate thumb.  */

Typo, accomodate -> accommodate.

> +   uint32_t opcode;              /* insn opcode.  */

This field is practically used as a local variable - all functions
which read the field also initialize it.
Furthermore `arm_insn' is a kind of "insn opcode", too.
Local-like varibales make a structure look more complex than it is;
this places fear into those who will want to modify the code.

> +   uint32_t id;                  /* type of insn.  */

Practically local variable in decode_insn(). No other function ever uses it.

> +   uint32_t cond;                /* condition code.  */

Is not initialized if (THUMB_INSN_SIZE_BYTES == insn_size).
It is not a bug since Thumb mode does not use condition prefixes.
However I find useful to assign -1 or something to indicate that:
* the field does not have an usual value
* I did not acidentaly skipped initialization
* I am not relying on initialization from other place
* hopefully the special value will trigger assertion if Thumb code
actually uses it.
(Actually my runtime fills memory with 0xCCCCCCC or something for this
reason, so I merelly add a comment about the non-use.)

> +  struct gdbarch *gdbarch;

Most functions do not actually use the field. Consider removing the
dummy variables in relevant functions.

> +  struct regcache *regcache;

Many functions use unnecesary cast to init local var, e.g. `(struct
regcache*) thumb_insn_r->regcache'.
Most functions do not actually use the var.

> + ...} insn_decode_record;

I suggest to add comment to insn_decode_record_t :

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


Moving on:

In handle_extension_space()
> +  uint32_t reg_src1 = 0, reg_src2 = 0;

Unused locals.

In arm_handle_data_proc_imm_insn()
> +  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> +  uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;

All these are unused.

In other functions:
GCC can detect when a local variable is used before it is initialized.
Your code initializes by 0 at the start of the function so the
advantage of GCC diagnostics is lost.
I recommend to not initialize a local variable until its "true" value
is know/computed.
I also recommend to define a local variable in the smalles scope
possible, however I understand that many
programmers use weak tools and knowing its definition requires more
effort than placing cursor on the variable - therefore they prefer
definitions at the start of function.


In arm_hamdle_ld_st_multiple_insn (I deleted irrelevant lines):
> +     switch(addr_mode)
> +      {
> +        /* Decrement after.  */
> +        case 0:
> +          start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Increment after.  */
> +        case 1:
> +          start_address = u_buf[0].s_word;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Decrement before.  */
> +        case 2:
> +          start_address = (u_buf[0].s_word) - (register_count * 4);
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;
> +        /* Increment before.  */
> +        case 3:
> +          start_address = u_buf[0].s_word + 4;
> +          while (register_count)
> +              start_address = start_address + 4;
> +        break;

Initialization of `start_address' looks good but I guess the increment
part should be:
+ start_address = start_address + 4
- start_address = start_address - 4
in two of the four cases.


> +
> +        default:
> +          /* unreachable.  */

Consider using gdb_assert_not_reached("Invalid addressing mode").


> +         printf("handling store insn, immed offfset insn\n");

Typo offfset. Should be printed conditionally.

> +       /* LDR insn has a capability to do branching, if
> +              MOV LR, PC is precedded by LDR insn having Rn as R15

Typo precedded -> preccedded. Multiple times.

> +   /* handle incremenrt after/before and decrment after.before mode;
> +        Rn is chaging depending on W bit, but as of now we store Rn too wihtout going for
> +        optmization.  */

Typos chaging, wihtout, optmization.

My IDE has a spellchecker which underlines typos. No effort required.
(Consider upgrading your tools.)


> +      ret = (0x0F != arm_record->cond)?
> +            arm_handle_insn[arm_record->id] ((void*)arm_record) :
> +            handle_extension_space(arm_record);

The ? and : should be at the begging.
GNU style guideline: "When you split an expression into multiple
lines, split it before an operator, not after one."
Also I find it more readable.


In decode_insn():
> +            arm_handle_insn[arm_record->id] ((void*)arm_record) :
> +      ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);

The (void*) casts are now unnecessary.

In arm_handle_coproc_data_proc_insn():
> +            tdep->arm_swi_record(reg_cache);

When this line is executed this function still returns -1 (i.e. failure).
I guess the two if's are intended to return success then.

In thumb_handle_add_sub_cmp_mov_insn():
> +   union { ... } u_buf;

Is unused. So does in thumb_handle_shift_add_sub_insn(). Maybe more.


In thumb_handle_ld_st_reg_offset_insn():
> +      opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
> +  thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);

The values are never read.
If you remove the 'thumb_insn_r->opcode' assignment then you can
simplify the function and remove the goto's.


> @@ -200,6 +200,9 @@
>   /* Return the expected next PC if FRAME is stopped at a syscall
>      instruction.  */
>   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> +   /* Parse swi args.  */
> +  int (*arm_swi_record) (struct regcache *regcache);

This field is newer assigned (only initialized to NULL).

I did not know that "swi" is an instruction. Is it a widely known fact
for ARM developers?
If not then use "swi insn" in the comment.

The return value is never tested. What is its meaning?

The parsed args seem to be stored as a side-effect. Where are they stored?
(Answers should go to comments.)
(Since this is an indirect call, the documentation should be more
verbose than usual cases.)

Disclaimers:

I am not familiar with ARM, I did not check e.g. if all cases are
handled, instructions have correct semantics etc.
Also I have no vote in GDB development, so my patch approval would
have little impact.

GDB commiters: please reply whether you agree with my review. (So that
paawan oza does not spend effort in vain.)

-- 
Petr Hluzin


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-04-30 16:16                           ` paawan oza
@ 2011-05-02 13:28                             ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2011-05-02 13:28 UTC (permalink / raw)
  To: paawan oza; +Cc: Petr Hluzín, gdb, gdb-patches

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

Oza> So you are suggesting;
Oza> GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
Oza> if (target is big endian)
Oza>   {
Oza>         convert_big_to_little (u_buf.s_word)
Oza>   }
Oza> something like above ?
Oza> right ?

More or less, but if you use the existing functions like
extract_unsigned_integer or extract_typed_address, then they
will handle all the details.

Oza> and while replaying do I need to convert it to big endian ?
Oza> somethig like that ?

It depends on what you are doing.

If you are doing calculations on some number, then you have to extract
it properly so that the host math works correctly.  If you are just
storing some data to be restored verbatim, then you don't need to
convert at all.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
@ 2011-05-02 14:47                   ` Tom Tromey
  2011-05-04 21:33                     ` Petr Hluzín
  2011-05-07 13:50                   ` paawan oza
  2011-05-07 13:56                   ` paawan oza
  2 siblings, 1 reply; 32+ messages in thread
From: Tom Tromey @ 2011-05-02 14:47 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb, gdb-patches

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

Petr> I also recommend to define a local variable in the smalles scope
Petr> possible, however I understand that many
Petr> programmers use weak tools and knowing its definition requires more
Petr> effort than placing cursor on the variable - therefore they prefer
Petr> definitions at the start of function.

I agree, using the smallest scope is generally preferable.
This practice makes it simpler to reason about the code.

Petr> My IDE has a spellchecker which underlines typos. No effort required.
Petr> (Consider upgrading your tools.)

I'm curious to know what IDE you use for working on GDB.

For those using Emacs, M-x flyspell-prog-mode will spell-check in
comments and strings.

Petr> Also I have no vote in GDB development, so my patch approval would
Petr> have little impact.

I appreciate thoughtful reviews from anyone, regardless of their
official status.  I think GDB patches still spend too much time waiting
for review, and this sort of thing can help speed things up.

Petr> GDB commiters: please reply whether you agree with my review. (So that
Petr> paawan oza does not spend effort in vain.)

I thought it was quite good.  Thanks for doing this.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-02 14:47                   ` Tom Tromey
@ 2011-05-04 21:33                     ` Petr Hluzín
  2011-05-05 15:29                       ` Tom Tromey
  0 siblings, 1 reply; 32+ messages in thread
From: Petr Hluzín @ 2011-05-04 21:33 UTC (permalink / raw)
  To: Tom Tromey; +Cc: paawan oza, gdb, gdb-patches

On 2 May 2011 16:46, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
> Petr> I also recommend to define a local variable in the smalles scope
> Petr> possible, however I understand that many
> Petr> programmers use weak tools and knowing its definition requires more
> Petr> effort than placing cursor on the variable - therefore they prefer
> Petr> definitions at the start of function.
>
> I agree, using the smallest scope is generally preferable.
> This practice makes it simpler to reason about the code.
>
> Petr> My IDE has a spellchecker which underlines typos. No effort required.
> Petr> (Consider upgrading your tools.)
>
> I'm curious to know what IDE you use for working on GDB.

The spell-checking and highlighting/displaying variable's definition
(plus many other goodies) is done by "Visual Assist X" extension to
Visual Studio. The initialization by 0xCCCCCCCC is done by VS compiler
and C runtime. VS can be configured to use an external compiler; of
course you loose some perks.

I am still searching for a comfortable cross-platform IDE.

I investigated the patch because I am interested reversible debugging.
However I barely work on GDB. I would be mostly interested in
polishing, removing rough corners and making tiny things work right.
But I feel that real hackers here do not like making tools nice to
use; or making things work for those who are not already experts; for
people who expect their tools to know their job without requiring
user's supervision, etc.

> Petr> GDB commiters: please reply whether you agree with my review. (So that
> Petr> paawan oza does not spend effort in vain.)
>
> I thought it was quite good.  Thanks for doing this.

Thanks for feedback.

-- 
Petr Hluzin


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-04 21:33                     ` Petr Hluzín
@ 2011-05-05 15:29                       ` Tom Tromey
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Tromey @ 2011-05-05 15:29 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: paawan oza, gdb, gdb-patches

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

Petr> I investigated the patch because I am interested reversible debugging.
Petr> However I barely work on GDB. I would be mostly interested in
Petr> polishing, removing rough corners and making tiny things work right.
Petr> But I feel that real hackers here do not like making tools nice to
Petr> use; or making things work for those who are not already experts; for
Petr> people who expect their tools to know their job without requiring
Petr> user's supervision, etc.

I can understand why you think this.
I have two things to suggest here.

First, in my experience with GDB, changes to the CLI are one of the most
hotly debated areas -- both what the user types and also what GDB
prints.  You can see any number of discussions about this in the
archives.

So, I think us developers do pay attention -- but maybe a funny kind of
attention, as we're used to the quirks of GDB CLI and expect additions
to be faithful to its traditions.

Second, feel free to comment on changes.  We try to make GDB as good as
we know how, but nobody has a monopoly on good ideas.

Tom


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
@ 2011-05-07 13:50                   ` paawan oza
  2011-05-07 13:56                   ` paawan oza
  2 siblings, 0 replies; 32+ messages in thread
From: paawan oza @ 2011-05-07 13:50 UTC (permalink / raw)
  To: Petr Hluzín; +Cc: gdb, gdb-patches

Hi Petr and Tom,

I have implemented most of your comments..
The comments which I could not put it in are below with explanation.

1) ARM_RECORD_ARCH_LIST_ADD_REG is used only at 2 places, but probably I wanted 
to 

give clear interface where it just takes only one argument, register number.
I should have done it for memory, but have not done yet.

sure, it hides local variable usage and it doesnt look good, but my intension 
was to give clear interface 

to function process_record modifiers.

I am still thinking over it.


2) > +   uint32_t opcode;              /* insn opcode.  */

I understand that above is one of the fields of arm_insn_record, but why I am 
usiong it as global field,
because the decoding bits by this field kind of global and common to most of the 
insns.

probably I would like to just extract it once and use anywhere, but 
unfortunately I have extracted in every function
and seems local, will work on that though.

3) 
+ start_address = start_address + 4
- start_address = start_address - 4
in two of the four cases.

If you have a look at the code, start_address initialization is the key factor 
for addressing mode.
not how start_address later gets incremented.. so even in decrement mode, 
increment is necessary but
initialization is different.

4)
In arm_handle_coproc_data_proc_insn():
> +            tdep->arm_swi_record(reg_cache);

When this line is executed this function still returns -1 (i.e. failure).
I guess the two if's are intended to return success then.

oza: the coprocessor insns are not implemented and syscall record too. so in 
both cases we return
-1.

5)
The return value is never tested. What is its meaning?

The parsed args seem to be stored as a side-effect. Where are they stored?
(Answers should go to comments.)
(Since this is an indirect call, the documentation should be more
verbose than usual cases.)

Oza: swi basically equivalent to sysenter an int80 insn on x86, so systemcall is 
implemented that way.
I am going to work on that implementation in phase 3.
phase 2 does not support it.

6) 
Tom: I still need to take care of endianess issue, which I will in the coming 
stage.

Note: updated patch will be mailed in the next mail.

Regards,
OZa.


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

* Re: [PATCH] arm reversible : <phase_2_complete>
  2011-05-01  1:20                 ` Petr Hluzín
  2011-05-02 14:47                   ` Tom Tromey
  2011-05-07 13:50                   ` paawan oza
@ 2011-05-07 13:56                   ` paawan oza
  2 siblings, 0 replies; 32+ messages in thread
From: paawan oza @ 2011-05-07 13:56 UTC (permalink / raw)
  To: Petr Hluzín, gdb, gdb-patches

Hi,

With almost all the comments resolved posting the updated patch..
if there are still typos I will try to do it with more spelling enforcements.

thanks to Tom, Petr, Pedro and Yao for their valuable comments to make this 
patch better.
I am still looking for more comments, so I can still shape it further.
.

ARM-REVERSIBLE PATCH
------------------------------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
 
+  /* Enable process record.  */
+  set_gdbarch_process_record (gdbarch, arm_process_record);
+
   tramp_frame_prepend_unwinder (gdbarch,
                 &arm_linux_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
 
 
   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+  tdep->arm_swi_record = NULL;
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c    2011-05-07 14:20:31.000000000 +0530
@@ -54,6 +54,8 @@
 #include "gdb_assert.h"
 #include "vec.h"
 
+#include "record.h"
+
 #include "features/arm-with-m.c"
 
 static int arm_debug;
@@ -7929,3 +7931,1708 @@
                NULL, /* FIXME: i18n: "ARM debugging is %s.  */
                &setdebuglist, &showdebuglist);
 }
+
+
+
+/* ARM-reversible process record data structures.  */
+
+#define ARM_INSN_SIZE_BYTES 4    
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+    record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF)  regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        REGS = (uint32_t*) xmalloc (sizeof(uint32_t)*(LENGTH)); \
+        while(LENGTH) \
+          { \
+            REGS[LENGTH -1] = RECORD_BUF[LENGTH-1];  \
+            LENGTH--;  \
+          } \
+      } \
+  } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do  \
+  { \
+    if (LENGTH) \
+      { \
+        MEMS = (struct arm_mem_r *)xmalloc \
+               (sizeof(struct arm_mem_r) * (LENGTH)); \
+        while(LENGTH) \
+          { \
+            MEMS[LENGTH - 1].addr = RECORD_BUF[(LENGTH * 2) - 1]; \
+            MEMS[LENGTH - 1].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+            LENGTH--;   \
+          } \
+      } \
+  } \
+while (0)
+
+
+/* ARM memory record strcuture/  */
+struct arm_mem_r
+{
+    uint32_t len;     /* record length.  */
+    CORE_ADDR addr;   /* memory address.  */
+};
+
+/* ARM instruction record.  
+contains opcode of current insn and execution state (before entry to 
+decode_insn() ), 
+contains list of to-be-modified registers and memory blocks (on return from 
+decode_insn() ).  */
+typedef struct insn_decode_record_t
+{
+  struct gdbarch *gdbarch;
+  struct regcache *regcache;
+  CORE_ADDR this_addr;          /* address of the insn being decoded.  */
+  uint32_t arm_insn;            /* should accommodate thumb.  */
+  uint32_t cond;                /* condition code.  */
+  uint32_t opcode;              /* insn opcode.  */
+  uint32_t decode;              /* insn decode bits.  */
+  uint32_t mem_rec_count;       /* no of mem recors */
+  uint32_t reg_rec_count;       /* no of reg records */
+  uint32_t *arm_regs;           /* registers to be saved for this record.  */
+  struct arm_mem_r *arm_mems;   /* memory to be saved for this record.  */
+} insn_decode_record;
+
+
+/* checkes ARM SBZ and SBO mendatory fields.  */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+  uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+      
+  if (!len)
+    return 1;
+
+  if(!sbo)
+    ones = ~ones;
+
+  while (ones)
+    {
+      if (!(ones & sbo))
+        {
+          return 0;
+        }
+      ones = ones >> 1;
+    }
+  return 1;
+}
+
+/* handling ARM extension space insns.  */
+
+static int 
+handle_extension_space (insn_decode_record *arm_insn_r)
+{  
+  uint32_t opcode1 = 0, opcode2 = 0;
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+    {
+      /* undefined instruction on ARM V5; need to handle if later versions
+          define it.  */
+    }
+  
+  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+  
+  if ((!opcode1) && (9 == opcode2))
+    {
+      /* handle arithmetic insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+  if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+    {
+      /* handle control insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+  if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+                 && (bit(arm_insn_r->arm_insn, 4)))
+    {
+      /* handle load/store insn extension space.  */
+    }
+
+  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+  if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+    {
+      /* handle coprocessor insn extension space.  */
+    }
+
+  /* to be done for ARMv5 and later; as of now we return -1.  */
+  return -1;
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+arm_handle_data_pro_mic_load_str_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+  uint32_t opcode1 = 0;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+  /* data processing insn /multiply insn.  */     
+  if ((9 == arm_insn_r->decode) 
+     && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+     ||  ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+    {
+      /* handle multiply instructions.  */
+      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
+        if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+          {
+            /* handle MLA and MUL.  */
+            record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+            record_buf[1] = ARM_PS_REGNUM;
+            arm_insn_r->reg_rec_count = 2;            
+          }
+        else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+         {
+          /* handle SMLAL, SMULL, UMLAL, UMULL.  */
+           record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+           record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+           record_buf[2] = ARM_PS_REGNUM;  
+           arm_insn_r->reg_rec_count = 3;
+         }        
+      }
+  else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+        && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+      {
+        /* handle misc load insns, as 20th bit (L = 1).  */
+        /* LDR insn has a capability to do branching, if
+                  MOV LR, PC is preccedded by LDR insn having Rn as R15 
+                  in that case, it emulates branch and link insn, and hence we 
+                  need to save CSPR and PC as well. I am not sure this is right 

+                  place as opcode = 010 LDR insn make this happen, if R15 was 
+                  used.  */
+        reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+        if (15 != reg_dest)
+          {
+            record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+            arm_insn_r->reg_rec_count = 1;
+          }
+        else
+          {
+            record_buf[0] = reg_dest;
+            record_buf[1] = ARM_PS_REGNUM; 
+            arm_insn_r->reg_rec_count = 2;
+          }
+      }
+  else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+      && (sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0))
+      && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+      && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+    {
+      /* handle MSR insn.  */
+      if (9 == arm_insn_r->opcode)
+        {
+          /* CSPR is going to be changed.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          arm_insn_r->reg_rec_count = 1;
+        }    
+      else
+        {
+          /* SPSR is going to be changed. */
+          /* how to read SPSR value ?  */
+          return -1;
+        }
+    }   
+  else if ((9 == arm_insn_r->decode) 
+           && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+           && (!bit (arm_insn_r->arm_insn,  INSN_S_L_BIT_NUM)))
+    {
+      /* Handling SWP, SWPB.  */
+      /* these insns, changes register and memory as well.  */
+      /* SWP or SWPB insn.  */
+      /* get memory address given by Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19); 
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+      /* SWP insn ?, swaps word.  */
+      if (8 == arm_insn_r->opcode)
+        {
+          record_buf_mem[0] = 4;
+        }
+        else
+        {   
+          /* SWPB insn, swaps only byte.  */
+          record_buf_mem[0] = 1;
+        }
+      record_buf_mem[1] = u_buf[0].s_word;
+      arm_insn_r->mem_rec_count = 1;
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);    
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+           && (sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1)))
+    {
+      /* handle BLX, branch and link/exchange.  */
+      if (9 == arm_insn_r->opcode)
+      {
+        /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm, 
+                     and R14 stores the return address.  */
+        record_buf[0] = ARM_PS_REGNUM;
+        record_buf[1] = ARM_LR_REGNUM;
+        arm_insn_r->reg_rec_count = 2;
+      }
+    }
+  else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+    {
+      /* handle enhanced software breakpoint insn, BKPT */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly */
+      /* what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      arm_insn_r->reg_rec_count = 2;
+      
+      /* save SPSR also; how?  */
+      return -1;
+    }  
+  else if ((11 == arm_insn_r->decode)
+          && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+  {
+    /* handle enhanced store insns and DSP insns (e.g. LDRD) 
+           let us begin according to addressing modes for store insns 
+           STRH insn, addresing modes are taken following.  */
+    if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+      {
+        /* 1) handle misc store, immediate offset.  */
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);            
+        if (15 == reg_src1)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        offset_8 = (immed_high << 4) | immed_low;
+        /* calculate target store address.  */
+        if (14 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+      {
+        /* 2) store, register offset.  */
+        /* get Rm.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        /* get Rn.  */
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+        if (15 == reg_src2)
+          {
+            /* if R15 was used as Rn, hence current PC+8.  */
+            u_buf[0].s_word = u_buf[0].s_word + 8;
+          }            
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if (12 == arm_insn_r->opcode)
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+      }
+    else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+      || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+      {
+        /* 3) store, immediate pre-indexed.  */            
+        /* 5)  store, immediate post-indexed.  */
+        immed_low = bits (arm_insn_r->arm_insn, 0, 3);  
+        immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+        offset_8 = (immed_high << 4) | immed_low;
+        reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + offset_8;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[0].s_word - offset_8;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);  
+        arm_insn_r->reg_rec_count = 1;
+      }
+    else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+      || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+      {
+        /* 4) store, register pre-indexed.  */
+        /* 6) store, register post -indexed.  */
+        reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+        reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+        GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+        GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+        /* calculate target store address, Rn +/- Rm, register offset.  */
+        if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+          {
+            tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+          }
+        else
+          {
+            tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+          }            
+        record_buf_mem[0] = 2;
+        record_buf_mem[1] = tgt_mem_addr;
+        arm_insn_r->mem_rec_count = 1;
+        /* record Rn also as it changes.  */
+        record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);              
+        arm_insn_r->reg_rec_count = 1;
+      }
+    /* DSP insns (e.g. LDRD)  TBD.  */
+  }  
+  else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+           && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+    {
+      /* handle BX, branch and link/exchange.  */
+      /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm.  */
+      record_buf[0] = ARM_PS_REGNUM;
+      arm_insn_r->reg_rec_count = 1;
+    }  
+  else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+           && (sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1))
+           && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)))
+    {
+      /* count leading zeros: CLZ.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      arm_insn_r->reg_rec_count = 1;
+    }
+  else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+          && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+          && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+          && (sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+          )
+    {      
+      /* handle MRS insn.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);  
+      arm_insn_r->reg_rec_count = 1;
+    }      
+  /* following is always true, in case none of the above conditions meet, it 
will fall here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      record_buf[1] = ARM_PS_REGNUM;        
+      arm_insn_r->reg_rec_count = 2;
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;
+}
+
+/* handling opcode 001 insns.  */
+
+static int 
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+       && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+       && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+       )
+    {
+      /* handle MSR insn.  */
+      if (9 == arm_insn_r->opcode)
+       {
+         /*CSPR is going to be changed.  */
+         record_buf[0] = ARM_PS_REGNUM;
+         arm_insn_r->reg_rec_count = 1;
+       }    
+      else
+      {
+       /* SPSR is going to be changed.  */
+       /* Oza: FIX ME ? how to read SPSR value?  */
+      }
+    }   
+  /* following is always true, in case none of the above conditions meet, it 
will fall 

+        here.  */
+  else if (arm_insn_r->opcode <= 15) 
+    {
+      /* normal data processing insns.  */
+      /* out of 11 shifter operands mode, all the insn modifies destination 
+                register, which is specified by 13-16 decode.  */
+      record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+      record_buf[1] = ARM_PS_REGNUM;        
+      arm_insn_r->reg_rec_count = 2;
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;
+}
+
+/* handling opcode 010 insns.  */
+
+static int 
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache = arm_insn_r->regcache;
+
+  uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)) 
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          record_buf[0] = reg_dest;
+          record_buf[1] = ARM_PS_REGNUM; 
+          arm_insn_r->reg_rec_count = 2;
+        }
+    }
+  else
+    {
+      if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+      || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+      || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+      || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)         
+      || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+      || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+      || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+      || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+        {
+          /* store, immediate offset, immediate pre-indexed,
+                      immediate post-indexed.  */          
+          reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+          offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+          /* U == 1 */
+          if (bit (arm_insn_r->arm_insn, 23))
+            {   
+              tgt_mem_addr = u_buf.s_word + offset_12;
+            }
+          else
+            {
+             tgt_mem_addr = u_buf.s_word - offset_12;
+            }
+
+          switch(arm_insn_r->opcode)
+            {
+              case 8:
+              case 12:          
+              case 9:   
+              case 13:   
+              case 1:   
+              case 5:               
+                /* STR insn, STRT insn.  */
+                record_buf_mem[0] = 4;    
+              break;   
+
+              case 10:
+              case 14:            
+              case 11:   
+              case 15:   
+              case 3:   
+              case 7:   
+                /* STRB insn, STRBT insn.  */
+                record_buf_mem[0] = 1;    
+              break;   
+
+              default:
+                gdb_assert_not_reached ("Invalid addressing mode for insn");
+              break;   
+            }       
+          record_buf_mem[1] = tgt_mem_addr;    
+          arm_insn_r->mem_rec_count = 1;
+          
+          if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+          || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+          || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+          || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)          
+          || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+          || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+            {
+              /* we are handling pre-indexed mode; post-indexed mode;
+                             where Rn is going to be changed.  */
+              record_buf[0] = reg_src1;    
+              arm_insn_r->reg_rec_count = 1;
+            }  
+        }  
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;
+}
+
+/* handling opcode 011 insns.  */
+
+static int 
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t shift_imm = 0;
+  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  union
+    {
+      int32_t signed_word;
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset(&u_buf, 0, sizeof(u_buf));
+  arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+  arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+  /* handle enhanced store insns and LDRD DSP insn,
+        let us begin according to addressing modes for store insns 
+        STRH insn.  */
+
+  /* LDR or STR?  */
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+      /* LDR insn has a capability to do branching, if
+              MOV LR, PC is precedded by LDR insn having Rn as R15 
+              in that case, it emulates branch and link insn, and hence we 
+              need to save CSPR and PC as well.  */
+      if (15 != reg_dest)
+        {
+          record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+          arm_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          record_buf[0] = reg_dest;
+          record_buf[1] = ARM_PS_REGNUM; 
+          arm_insn_r->reg_rec_count = 2;
+        } 
+    }
+  else
+    {
+    if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)     
+    || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+    || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+    || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)         
+    || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+    || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+    || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+    || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+      {
+        if (! bits (arm_insn_r->arm_insn, 4, 11))
+          {
+            /* store insn, register offset and register pre-indexed, 
+                          register post-indexed.  */
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, 
&u_buf[1].buf[0]);                        

+            if (15 == reg_src2)
+              {
+                /* if R15 was used as Rn, hence current PC+8.  */
+                /* pre-indexed mode doesnt reach here ; illegal insn.  */
+                u_buf[0].s_word = u_buf[0].s_word + 8;
+              }            
+            /* calculate target store address, Rn +/- Rm, register offset.  */
+            /* U == 1.  */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+              }            
+
+            switch(arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;   
+              }       
+            record_buf_mem[1] = tgt_mem_addr;
+            arm_insn_r->mem_rec_count = 1;
+
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                /* Rn is going to be changed in pre-indexed mode and 
+                                post-indexed mode as well.  */
+                record_buf[0] = reg_src2;  
+                arm_insn_r->reg_rec_count = 1;
+              }     
+          }
+        else
+          {
+            /* store insn, scaled register offset; scaled pre-indexed.  */
+            offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+            /* get Rm.  */
+            reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);  
+            /* get Rn.  */
+            reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+            /* get shift_imm.  */
+            shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+            GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);   
+            /* offset_12 used as shift.  */
+            switch(offset_12)
+              {
+                case 0:
+                  /* offset_12 used as index.  */
+                  offset_12 = u_buf[0].s_word << shift_imm;
+                break;
+                
+                case 1:
+                  offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm; 
+                break;
+                
+                case 2:
+                  if (!shift_imm)
+                    {
+                      if (bit (u_buf[0].s_word, 31))
+                        {
+                          offset_12 = 0xFFFFFFFF;
+                        }
+                      else
+                        {
+                          offset_12 = 0;
+                        }
+                    }
+                  else
+                    {
+                      /* this is arithmetic shift.  */
+                      offset_12 = u_buf[0].signed_word >> shift_imm;
+                    }
+                  break;  
+                  
+                case 3:
+                  if (!shift_imm)
+                    {
+                      GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+                      /* get C flag value and shift it by 31.  */
+                      offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+                                    | (u_buf[0].s_word) >> 1);
+                    }
+                  else
+                    {                      
+                      offset_12 = (u_buf[0].s_word >> shift_imm) \
+                            | (u_buf[0].s_word << 
(sizeof(uint32_t)-shift_imm));
+                    }
+                break;
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;
+              }      
+
+            GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]); 
+            /* U == 1 */
+            if (bit (arm_insn_r->arm_insn, 23))
+              {
+                tgt_mem_addr = u_buf[1].s_word + offset_12;
+              }
+            else
+              {
+                tgt_mem_addr = u_buf[1].s_word - offset_12;
+              }       
+            
+            switch (arm_insn_r->opcode)
+              {
+                case 8:
+                case 12:          
+                case 9:   
+                case 13:   
+                case 1:   
+                case 5:               
+                  /* STR insn, STRT insn.  */
+                  record_buf_mem[0] = 4;    
+                break;   
+
+                case 10:
+                case 14:            
+                case 11:   
+                case 15:   
+                case 3:   
+                case 7:   
+                  /* STRB insn, STRBT insn.  */
+                  record_buf_mem[0] = 1;    
+                break;   
+
+                default:
+                  gdb_assert_not_reached ("Invalid addressing mode for insn");
+                break;   
+              }                   
+            record_buf_mem[1] = tgt_mem_addr;
+            arm_insn_r->mem_rec_count = 1;
+            
+            if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)     
+            || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+            || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)     
+            || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)         
+            || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+            || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+              {
+                /* Rn is going to be changed in register scaled pre-indexed 
+                                mode, and scaled post indexed mode.  */
+                record_buf[0] = reg_src2;  
+                arm_insn_r->reg_rec_count = 1;
+              }
+          }            
+      }  
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;   
+}
+
+/* handling opcode 100 insns.  */
+
+static int 
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{   
+  struct regcache *reg_cache =  arm_insn_r->regcache;
+
+  uint32_t register_list[16]={0}, register_count=0, register_bits=0;       
+  uint32_t shift_imm=0;
+  uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+  uint32_t start_address=0, index = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  /* this mode is exclusively for load and store multiple.  */
+  /* handle incremenrt after/before and decrment after.before mode;
+        Rn is changing depending on W bit, but as of now we store Rn too 
without optmization.  */
+
+  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+    {
+      /* LDR (1,2,3) where LDR (3) changes CPSR too.  */
+
+      register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+      /* get Rn.  */
+      reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+      while (register_bits)
+       {
+         if (register_bits & 0x00000001)
+           register_list[register_count++] = 1;
+         register_bits = register_bits >> 1;
+       }
+      
+        /* extra space for Base Register and CPSR; wihtout optmization.  */
+        record_buf[register_count] = reg_src1;
+        record_buf[register_count + 1] = ARM_PS_REGNUM;
+        for (register_count = 0; register_count < 8; register_count++)
+          {
+            if  (register_list[register_count])
+              {
+              /* register_count gives total no of registers and dually working 
+                             as reg number.  */
+                record_buf[index] = register_count;
+                index++;
+              }
+          }
+        arm_insn_r->reg_rec_count = register_count + 2;
+    }
+  else
+    {
+    /* it handles both STM(1) and STM(2).  */
+    addr_mode = bits (arm_insn_r->arm_insn, 23, 24);    
+
+    register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+    /* get Rn.  */
+    reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+    GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+    while (register_bits)
+      {
+        if (register_bits & 0x00000001)
+           register_count++;
+        register_bits = register_bits >> 1;
+      }
+
+    switch(addr_mode)
+      {
+        /* Decrement after.  */ 
+        case 0:                          
+          start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
+          while (register_count)
+            {
+              record_buf_mem[(register_count * 2) - 1] = start_address;
+              record_buf_mem[(register_count * 2) - 2] = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment after.  */
+        case 1:
+          start_address = u_buf[0].s_word;
+          while (register_count)
+            {
+              record_buf_mem[(register_count * 2) - 1] = start_address;
+              record_buf_mem[(register_count * 2) - 2] = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Decrement before.  */
+        case 2:
+          
+          start_address = (u_buf[0].s_word) - (register_count * 4);
+          while (register_count)
+            {    
+              record_buf_mem[(register_count * 2) - 1] = start_address;
+              record_buf_mem[(register_count * 2) - 2] = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        /* Increment before.  */
+        case 3:
+          start_address = u_buf[0].s_word + 4;
+          while (register_count)
+            {
+              record_buf_mem[(register_count * 2) - 1] = start_address;
+              record_buf_mem[(register_count * 2) - 2] = 4;
+              start_address = start_address + 4;
+              register_count--;
+            }
+          arm_insn_r->mem_rec_count = register_count;
+        break;    
+
+        default:
+          gdb_assert_not_reached ("Invalid addressing mode for insn");
+        break;    
+      }
+
+    /* base register also changes; based on condition and W bit.  */
+    /* we save it anyway without optimization.  */
+    record_buf[0] = reg_src1;
+    arm_insn_r->reg_rec_count = 1;
+    }
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem);
+  return 0;   
+}
+
+/* handling opcode 101 insns.  */
+
+static int 
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+  uint32_t record_buf[8];
+
+  /* handle B, BL, BLX(1) insns.  */
+  /* wihtout optmization we save link register, 
+        CSPR for the insn which changes T bit.  */
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  arm_insn_r->reg_rec_count = 2;  
+
+  REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+    
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+   return -1;   
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+   struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+   struct regcache *reg_cache = arm_insn_r->regcache;
+   
+   uint32_t shift_imm = 0;
+   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+   uint32_t start_address = 0;
+
+   /* handle SWI insn; system call would be handled over here.  */
+
+   arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+   if (15 == arm_insn_r->opcode) 
+   {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+   }
+     
+   return -1;   
+}
+
+/* handling opcode 000 insns.  */
+
+static int 
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_src1 = 0;
+
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = reg_src1;
+  thumb_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+  return 0;   
+}
+
+
+/* handling opcode 001 insns.  */
+
+static int 
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8]; 
+  uint32_t reg_src1 = 0;
+
+  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = reg_src1;
+  thumb_insn_r->reg_rec_count = 2;
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+  return 0;  
+}
+
+/* handling opcode 010 insns.  */
+
+static int 
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache =  thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+
+  uint32_t reg_src1 = 0, reg_src2 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+  
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf[2];
+
+  if (bit (thumb_insn_r->arm_insn, 12))
+    {
+      /* handle load/store register offset.  */ 
+      opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);  
+      if ((opcode2 >= 12) && (opcode2 <= 15))
+        {         
+          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);           
+          record_buf[0] = reg_src1;
+          thumb_insn_r->reg_rec_count = 1;
+        }
+      else if ((opcode2 >= 8) && (opcode2 <= 10))
+        {
+          /* STR(2), STRB(2), STRH(2) .  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+          reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+          GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+          GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+          if (8 == opcode2)
+            record_buf_mem[0] = 4;    /* STR (2).  */             
+          else if (10 == opcode2)
+            record_buf_mem[0] = 1;    /*  STRB (2).  */
+          else if (9 == opcode2)
+            record_buf_mem[0] = 2;    /* STRH (2).  */
+          record_buf_mem[1] = u_buf[0].s_word+u_buf[1].s_word; 
+          thumb_insn_r->mem_rec_count = 1;
+        }                 
+      goto end;
+    }            
+  else if (bit (thumb_insn_r->arm_insn, 11))
+    {
+      /* handle load from literal pool.  */  
+      /* LDR(3).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);                          

+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+      goto end;
+    }
+    
+  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+  if (opcode1)
+    {
+      opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+      opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if ((3 == opcode2) && (!opcode3))
+        {
+          /* branch with exchange.  */
+          record_buf[0] = ARM_PS_REGNUM;
+          thumb_insn_r->reg_rec_count = 1;
+        }
+      else
+        {
+          /* format 8; special data processing insns.  */
+          reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+          record_buf[0] = ARM_PS_REGNUM;
+          record_buf[1] = reg_src1;
+          thumb_insn_r->reg_rec_count = 2;
+        }
+    }
+  else
+    {
+      /* format 5; data processing insns.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      if (bit (thumb_insn_r->arm_insn, 7))
+        {
+          reg_src1 = reg_src1 + 8;
+        }
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = reg_src1;
+      thumb_insn_r->reg_rec_count = 2;
+    }  
+
+  end:
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
record_buf_mem);
+  
+  return 0;
+}
+
+/* handling opcode 001 insns.  */
+
+static int 
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (opcode)
+    {
+      /* LDR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else
+    {
+      /* STR(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.s_word + (immed_5 * 4);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+  
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
record_buf_mem);
+
+  return 0;
+}
+
+/* handling opcode 100 insns.  */
+
+static int 
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{ 
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  uint32_t record_buf[8], record_buf_mem[8];
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (3 == opcode)
+    {
+      /* LDR(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (1 == opcode)
+    {
+      /* LDRH(1).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (2 == opcode)
+    {
+      /* STR(3).  */
+      immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+      record_buf_mem[0] = 4;
+      record_buf_mem[1] = u_buf.s_word + (immed_8 * 4);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+  else if (0 == opcode)
+    {
+      /* STRH(1).  */
+      immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+      reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      record_buf_mem[0] = 2;
+      record_buf_mem[1] = u_buf.s_word + (immed_5 * 2);
+      thumb_insn_r->mem_rec_count = 1;
+    }
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
record_buf_mem);
+  
+  return 0;
+}
+
+/* handling opcode 101 insns.  */
+
+static int 
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+  uint32_t register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+  if (14 == opcode2)
+    {
+      /* POP.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+      record_buf[register_count] = ARM_PS_REGNUM;
+      record_buf[register_count + 1] = ARM_SP_REGNUM;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+      thumb_insn_r->reg_rec_count = register_count + 2;
+    }
+  else if (10 == opcode2)
+    {
+      /* PUSH.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word -  \
+                   (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+      while (register_count)
+        {
+          record_buf_mem[(register_count * 2) - 1] = start_address;
+          record_buf_mem[(register_count * 2) - 2] = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+      thumb_insn_r->mem_rec_count = register_count;
+      record_buf[0] = ARM_SP_REGNUM;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  else if (0x1E == opcode1)
+    {
+      /* BKPT insn.  */
+      /* handle enhanced software breakpoint insn, BKPT.  */
+      /* CPSR is changed to be executed in ARM state,  disabling normal 
+               interrupts, entering abort mode.  */
+      /* accorindly to high vector configuration PC is set accordingly.  */
+      /* Oza: FIX ME ?  what if user hit breakpoint and type reverse, in 
+               that case, we need to go back with previous CPSR and 
+               Program Counter..  */
+      record_buf[0] = ARM_PS_REGNUM;
+      record_buf[1] = ARM_LR_REGNUM;
+      thumb_insn_r->reg_rec_count = 2;
+      /* save SPSR also; how?.  */
+      return -1;
+    }
+  else if ((0 == opcode) || (1 == opcode))
+    {
+       /* ADD(5), ADD(6).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = reg_src1;
+      thumb_insn_r->reg_rec_count = 1;
+    }  
+  else if (2 == opcode)
+    {
+      /* ADD(7), SUB(4).  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      record_buf[0] = ARM_SP_REGNUM;
+      thumb_insn_r->reg_rec_count = 1;
+    }
+  
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
record_buf_mem);
+  
+  return 0;
+}
+
+/* handling opcode 110 insns.  */
+
+static int 
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)                
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+  struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+  
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+  uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+  uint32_t record_buf[24], record_buf_mem[48];
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+  opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+  if (1 == opcode2)
+    {
+
+      /* LDMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+            register_list[register_count++] = 1;
+          register_bits = register_bits >> 1;
+        }
+      record_buf[register_count] = reg_src1;
+      for (register_count = 0; register_count < 8; register_count++)
+        {
+          if  (register_list[register_count])
+            {
+              record_buf[index] = register_count;
+              index++;
+            }
+        }
+        thumb_insn_r->reg_rec_count = register_count + 1;
+    }
+  else if (0 == opcode2)
+    {
+      /* it handles both STMIA.  */
+      register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+      /* get Rn.  */
+      reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+      GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+      while (register_bits)
+        {
+          if (register_bits & 0x00000001)
+             register_count++;
+          register_bits = register_bits >> 1;
+        }
+      start_address = u_buf.s_word;
+      while (register_count)
+        {
+          record_buf_mem[(register_count * 2) - 1] = start_address;
+          record_buf_mem[(register_count * 2) - 2] = 4;
+          start_address = start_address + 4;
+          register_count--;
+        }
+      thumb_insn_r->mem_rec_count = register_count;
+    }
+  else if (0x1F == opcode1)
+     {
+        /* handle arm syscall insn.  */
+        if (tdep->arm_swi_record != NULL)
+          {
+            tdep->arm_swi_record(reg_cache);
+          }
+        else
+          {
+            return -1;
+          }
+     }
+
+  /* B(1), conditional branch is automatically taken care in process_record, 
+        as PC is saved there.  */
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, 
record_buf_mem);
+  
+  return 0;
+}
+
+/* handling opcode 111 insns.  */
+
+static int 
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+  uint32_t record_buf[8];
+  uint32_t reg_val1 = 0;
+  uint32_t reg_src1 = 0;
+  uint32_t opcode = 0, immed_5 = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+
+  /* BL , BLX(1).  */  
+  record_buf[0] = ARM_PS_REGNUM;
+  record_buf[1] = ARM_LR_REGNUM;
+  thumb_insn_r->reg_rec_count = 2;
+
+  /* B(2) is automatically taken care in process_record, as PC is saved 
+        there.  */
+
+  REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+  
+  return 0;     
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch 
it.  */
+
+static int 
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+  /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm 
instruction.  */
+  static int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) 
+                                      (insn_decode_record*) = 
+  { 
+      arm_handle_data_pro_mic_load_str_insn,  /* 000.  */
+      arm_handle_data_proc_imm_insn,            /* 001.  */
+      arm_handle_ld_st_imm_offset_insn,         /* 010.  */
+      arm_handle_ld_st_reg_offset_insn,         /* 011.  */  
+      arm_handle_ld_st_multiple_insn,           /* 100.  */
+      arm_handle_brn_insn,                      /* 101.  */
+      arm_handle_coproc_insn,                   /* 110.  */
+      arm_handle_coproc_data_proc_insn          /* 111.  */  
+  };
+  
+  /* (starting from numerical 0); bits 13,14,15 decodes type of thumb 
instruction.  */
+  static int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) 
+                                          (insn_decode_record*) =
+  { \
+      thumb_handle_shift_add_sub_insn,         /* 000.  */
+      thumb_handle_add_sub_cmp_mov_insn,       /* 001.  */
+      thumb_handle_ld_st_reg_offset_insn,      /* 010.  */
+      thumb_handle_ld_st_imm_offset_insn,      /* 011.  */  
+      thumb_handle_ld_st_stack_insn,           /* 100.  */
+      thumb_handle_misc_insn,                  /* 101.  */
+      thumb_handle_swi_insn,                   /* 110.  */
+      thumb_handle_branch_insn                 /* 111.  */  
+  };
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[insn_size];
+    } u_buf;
+
+  uint32_t ret=0, insn_id = 0;
+    
+  memset (&u_buf, 0, sizeof(u_buf));
+  if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))    
+    {        
+      if (record_debug)
+        {
+          printf_unfiltered (_("Process record: error reading memory at "
+                               "addr %s len = %d.\n"),
+          paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+          return -1;
+        }
+    }
+  else if (ARM_INSN_SIZE_BYTES == insn_size)
+    {
+      arm_record->arm_insn = u_buf.s_word;
+      arm_record->cond = bits (arm_record->arm_insn, 28, 31); 
+      insn_id = bits (arm_record->arm_insn, 25, 27);
+      ret = (0x0F != arm_record->cond) \
+            ? \
+            arm_handle_insn[insn_id] (arm_record) \
+            : \
+            handle_extension_space(arm_record);
+    }    
+  else if (THUMB_INSN_SIZE_BYTES == insn_size)
+    {
+      /* As thumb does not have condition codes, following field is useless.  
*/
+      arm_record->cond = -1;   
+      arm_record->arm_insn = u_buf.s_word;  
+      insn_id = bits (arm_record->arm_insn, 13, 15);
+      ret = thumb_handle_insn[insn_id] (arm_record);
+    }
+  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+    {
+      /* yet to be implemented; handle thumb2 part here.  */
+    }
+  else
+    {
+      /* throw assertion.  */
+      gdb_assert(0);
+    }
+  
+  return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+   memory that will be changed in current instruction to "record_arch_list".
+   Return -1 if something is wrong..  */
+
+int 
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+                             CORE_ADDR insn_addr)
+{
+
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);  
+  uint32_t no_of_rec = 0;
+  uint32_t ret = 0;
+  ULONGEST t_bit = 0;
+
+  union
+    {
+      uint32_t s_word;
+      gdb_byte buf[4];
+    } u_buf;
+
+  insn_decode_record arm_record;
+  memset (&u_buf, 0, sizeof(u_buf));
+
+  memset (&arm_record, 0, sizeof (insn_decode_record));
+  arm_record.regcache = regcache;
+  arm_record.this_addr = insn_addr;
+  arm_record.gdbarch = gdbarch;
+
+
+  if (record_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+                                      "addr = %s\n",
+      paddress (gdbarch, arm_record.this_addr));
+    }
+
+  /* check the insn, whether it is thumb or arm one.  */
+
+  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+  GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+    
+  if (!(u_buf.s_word & t_bit))
+    {
+      /* we are decoding arm insn.  */
+      ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);      
+    }
+  else
+    {
+      /* we are decoding thumb insn.  */
+      ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);    
+    }
+
+  /* record registers.  */
+  if (0 == ret)
+    {
+      ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+      if (arm_record.arm_regs)
+        {
+          for (no_of_rec = 0; no_of_rec <= arm_record.reg_rec_count; 
no_of_rec++)
+            {
+              if (ARM_RECORD_ARCH_LIST_ADD_REG 
(arm_record.arm_regs[no_of_rec]))
+              ret = -1;
+            }
+        }   
+      /* record memories.  */
+      if (arm_record.arm_mems)
+        {
+          for (no_of_rec = 0; no_of_rec <= arm_record.mem_rec_count; 
no_of_rec++)
+           {
+              if (record_arch_list_add_mem \
+                ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+                arm_record.arm_mems[no_of_rec].len))
+                ret = -1;
+           }
+        }
+
+      if (record_arch_list_add_end ())
+        ret = -1;
+    }
+
+  if (arm_record.arm_regs)
+    xfree (arm_record.arm_regs);
+  if (arm_record.arm_mems)
+    xfree (arm_record.arm_mems);
+  
+  return ret; 
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
   /* Return the expected next PC if FRAME is stopped at a syscall
      instruction.  */
   CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+   /* Parse swi insn args, sycall record.  */
+  int (*arm_swi_record) (struct regcache *regcache);
 };
 
 /* Structures used for displaced stepping.  */
@@ -310,6 +313,10 @@
                       struct displaced_step_closure *,
                       CORE_ADDR, CORE_ADDR, struct regcache *);
 
+extern int arm_process_record (struct gdbarch *gdbarch,
+                                struct regcache *regcache, CORE_ADDR addr);
+
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

Regards,
Oza.


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

end of thread, other threads:[~2011-05-07 13:56 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-03  4:08 [PATCH] arm reversible : progress <patch_1_phase_2> paawan oza
2011-03-03 18:32 ` Tom Tromey
2011-03-03 18:37   ` Michael Snyder
2011-03-03 18:59     ` Pedro Alves
2011-03-04  3:32   ` paawan oza
2011-03-04  3:56     ` paawan oza
2011-03-04 19:31     ` Tom Tromey
2011-03-04 20:09       ` Michael Snyder
2011-03-04 20:11         ` Tom Tromey
2011-04-10  9:41   ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
2011-04-11  3:05     ` Yao Qi
2011-04-11  4:52       ` paawan oza
2011-04-12 10:58         ` Yao Qi
2011-04-16 21:03       ` 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-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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox