[PATCH] arm reversible : <phase_2_complete>

oza Pawandeep oza.pawandeep@gmail.com
Tue Jul 5 08:47:00 GMT 2011


Hi all,

can anybody from ARM background review the code with functional perspective ?
Chandra K, is assisting for gdb automated testsuite for arm
reversible, but review is equally important specially if ARM folk
could have a look at the patch at functional perspective.

Thanks & Regards,
Oza.


>
> --- On Fri, 3/6/11, "paawan oza" <paawan1982@yahoo.com> wrote:
>> From: paawan oza <paawan1982@yahoo.com>
>> Date: Fri, Jun 3, 2011 at 1:21 PM
>> Subject: Re: [PATCH] arm reversible :
>> <phase_2_complete>
>> To: Tom Tromey <tromey@redhat.com>
>> Cc: gdb-patches@sourceware.org,
>> Petr Hluzín <petr.hluzin@gmail.com>
>>
>>
>> Hi Tom,
>>
>> Fixed almost all comments.
>> any more comments are welcome make this patch ok, if ARM
>> person can have a look
>> at it it would be great.
>>
>> PATCH STARTS
>> ------------------------------------diff -urN
>> arm_orig/arm-linux-tdep.c
>> arm_new/arm-linux-tdep.c
>> --- arm_orig/arm-linux-tdep.c    2011-03-03
>> 09:21:13.000000000 +0530
>> +++ arm_new/arm-linux-tdep.c    2011-05-07
>> 14:20:31.000000000 +0530
>> @@ -998,6 +998,9 @@
>>   set_gdbarch_fetch_tls_load_module_address (gdbarch,
>>
>>      svr4_fetch_objfile_link_map);
>>
>> +  /* Enable process record.  */
>> +  set_gdbarch_process_record (gdbarch,
>> arm_process_record);
>> +
>>   tramp_frame_prepend_unwinder (gdbarch,
>>
>> &arm_linux_sigreturn_tramp_frame);
>>   tramp_frame_prepend_unwinder (gdbarch,
>> @@ -1025,6 +1028,8 @@
>>
>>
>>   tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>> +
>> +  tdep->arm_swi_record = NULL;
>>  }
>>
>>  /* Provide a prototype to silence -Wmissing-prototypes.
>>  */
>> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
>> --- arm_orig/arm-tdep.c    2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.c    2011-06-03 13:16:35.000000000
>> +0530
>> @@ -54,6 +54,8 @@
>>  #include "gdb_assert.h"
>>  #include "vec.h"
>>
>> +#include "record.h"
>> +
>>  #include "features/arm-with-m.c"
>>
>>  static int arm_debug;
>> @@ -7929,3 +7931,1763 @@
>>                NULL, /* FIXME: i18n: "ARM debugging
>> is %s.  */
>>                &setdebuglist,
>> &showdebuglist);
>>  }
>> +
>> +
>> +
>> +/* ARM-reversible process record data structures.  */
>> +
>> +#define ARM_INSN_SIZE_BYTES 4
>> +#define THUMB_INSN_SIZE_BYTES 2
>> +#define THUMB2_INSN_SIZE_BYTES 4
>> +
>> +#define INSN_S_L_BIT_NUM 20
>> +
>> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
>> +do  \
>> +  { \
>> +    unsigned int reg_len = 0; reg_len = LENGTH; \
>> +    if (reg_len) \
>> +      { \
>> +        REGS = (uint32_t*) xmalloc (sizeof(uint32_t) *
>> (reg_len)); \
>> +        while (reg_len) \
>> +          { \
>> +            REGS[reg_len - 1] = RECORD_BUF[reg_len -
>> 1];  \
>> +            reg_len--;  \
>> +          } \
>> +      } \
>> +  } \
>> +while (0)
>> +
>> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>> +do  \
>> +  { \
>> +    unsigned int mem_len = 0; mem_len = LENGTH; \
>> +    if (mem_len) \
>> +      { \
>> +        MEMS = (struct arm_mem_r *)xmalloc \
>> +               (sizeof(struct arm_mem_r) *
>> (mem_len)); \
>> +        while (mem_len) \
>> +          { \
>> +            MEMS[mem_len - 1].addr =
>> RECORD_BUF[(mem_len * 2) - 1]; \
>> +            MEMS[mem_len - 1].len =
>> RECORD_BUF[(mem_len * 2) - 2]; \
>> +            mem_len--;   \
>> +          } \
>> +      } \
>> +  } \
>> +while (0)
>> +
>> +
>> +/* ARM memory record structure.  */
>> +struct arm_mem_r
>> +{
>> +  uint32_t len;     /* Record length.  */
>> +  CORE_ADDR addr;   /* Memory address.  */
>> +};
>> +
>> +/* ARM instruction record contains opcode of current insn
>> and execution state
>> (before entry to
>>
>> +decode_insn() ), contains list of to-be-modified registers
>> and memory blocks
>> (on return from
>>
>> +decode_insn() ).  */
>> +typedef struct insn_decode_record_t
>> +{
>> +  struct gdbarch *gdbarch;
>> +  struct regcache *regcache;
>> +  CORE_ADDR this_addr;          /* Address of the
>> insn being decoded.  */
>> +  uint32_t arm_insn;            /* Should
>> accommodate thumb.  */
>> +  uint32_t cond;                /* Condition
>> code.  */
>> +  uint32_t opcode;              /* Insn opcode.
>>  */
>> +  uint32_t decode;              /* Insn decode
>> bits.  */
>> +  uint32_t mem_rec_count;       /* No of mem recors
>> */
>> +  uint32_t reg_rec_count;       /* No of reg records
>> */
>> +  uint32_t *arm_regs;           /* Registers to be
>> saved for this record.  */
>> +  struct arm_mem_r *arm_mems;   /* Memory to be saved
>> for this record.  */
>> +} insn_decode_record;
>> +
>> +
>> +/* Checks ARM SBZ and SBO mendatory fields.  */
>> +
>> +static int
>> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len,
>> uint32_t sbo)
>> +{
>> +  uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) +
>> (len - 1));
>> +
>> +  if (!len)
>> +    return 1;
>> +
>> +  if(!sbo)
>> +    ones = ~ones;
>> +
>> +  while (ones)
>> +    {
>> +      if (!(ones & sbo))
>> +        {
>> +          return 0;
>> +        }
>> +      ones = ones >> 1;
>> +    }
>> +  return 1;
>> +}
>> +
>> +/* Handling ARM extension space insns.  */
>> +
>> +static int
>> +handle_extension_space (insn_decode_record *arm_insn_r)
>> +{
>> +  uint32_t ret = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0;
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> +  if ((3 == opcode1) && (bit
>> (arm_insn_r->arm_insn, 4)))
>> +    {
>> +      ret = -1;
>> +      /* Undefined instruction on ARM V5; need to
>> handle if later versions
>> +          define it.  */
>> +    }
>> +
>> +  opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> +  if ((!opcode1) && (9 == opcode2))
>> +    {
>> +      ret = -1;
>> +      /* Handle arithmetic insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>> +  opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> +  if ((!opcode1) && (2 == opcode2) &&
>> (!bit (arm_insn_r->arm_insn, 20)))
>> +    {
>> +      ret = -1;
>> +      /* Handle control insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> +  if ((!opcode1) && (bit
>> (arm_insn_r->arm_insn, 7)) \
>> +                 &&
>> (bit(arm_insn_r->arm_insn, 4)))
>> +    {
>> +      ret = -1;
>> +      /* Handle load/store insn extension space.  */
>> +    }
>> +
>> +  opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>> +  if ((24 == opcode1) && (bit
>> (arm_insn_r->arm_insn, 21)))
>> +    {
>> +      ret = -1;
>> +      /* Handle coprocessor insn extension space.  */
>> +    }
>> +
>> +  /* To be done for ARMv5 and later; as of now we return
>> -1.  */
>> +  if (-1 == ret)
>> +    printf_unfiltered (_("Process record does not
>> support instruction 0x%0x "
>> +                       "at address %s.\n"),
>> +
>> arm_insn_r->arm_insn,
>> +                       paddress
>> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>> +  return ret;
>> +}
>> +
>> +/* Handling opcode 000 insns.  */
>> +
>> +static int
>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +
>> +  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> +  uint32_t immed_high = 0, immed_low = 0,offset_8 = 0,
>> tgt_mem_addr = 0;
>> +  uint32_t opcode1 = 0;
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +
>> +  arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> +  arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +  opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
>> +
>> +  /* Data processing insn /multiply insn.  */
>> +  if ((9 == arm_insn_r->decode)
>> +     && (((4 <= arm_insn_r->opcode)
>> && (7 >= arm_insn_r->opcode))
>> +     ||  ((0 == arm_insn_r->opcode) || (1 ==
>> arm_insn_r->opcode))))
>> +    {
>> +      /* Handle multiply instructions.  */
>> +      /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL.  */
>> +        if ((0 == arm_insn_r->opcode) || (1 ==
>> arm_insn_r->opcode))
>> +          {
>> +            /* Handle MLA and MUL.  */
>> +            record_buf[0] = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> +            record_buf[1] = ARM_PS_REGNUM;
>> +            arm_insn_r->reg_rec_count = 2;
>> +          }
>> +        else if ((4 <= arm_insn_r->opcode)
>> && (7 >= arm_insn_r->opcode))
>> +         {
>> +          /* Handle SMLAL, SMULL, UMLAL, UMULL.  */
>> +           record_buf[0] = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> +           record_buf[1] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> +           record_buf[2] = ARM_PS_REGNUM;
>> +           arm_insn_r->reg_rec_count = 3;
>> +         }
>> +      }
>> +  else if ((bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM))
>> +        && ((11 == arm_insn_r->decode) ||
>> (13 == arm_insn_r->decode)))
>> +      {
>> +        /* Handle misc load insns, as 20th bit (L =
>> 1).  */
>> +        /* LDR insn has a capability to do branching,
>> if
>> +                  MOV LR, PC is preccedded by LDR
>> insn having Rn as R15
>> +                  in that case, it emulates
>> branch and link insn, and hence we
>> +                  need to save CSPR and PC as
>> well. I am not sure this is right
>>
>> +                  place as opcode = 010 LDR insn
>> make this happen, if R15 was
>> +                  used.  */
>> +        reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> +        if (15 != reg_dest)
>> +          {
>> +            record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> +            arm_insn_r->reg_rec_count = 1;
>> +          }
>> +        else
>> +          {
>> +            record_buf[0] = reg_dest;
>> +            record_buf[1] = ARM_PS_REGNUM;
>> +            arm_insn_r->reg_rec_count = 2;
>> +          }
>> +      }
>> +  else if (((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode))
>> +      && (sbo_sbz (arm_insn_r->arm_insn, 5,
>> 12, 0))
>> +      && (sbo_sbz (arm_insn_r->arm_insn, 13,
>> 4, 1))
>> +      && (2 == bits (arm_insn_r->arm_insn,
>> 20, 21)))
>> +    {
>> +      /* Handle MSR insn.  */
>> +      if (9 == arm_insn_r->opcode)
>> +        {
>> +          /* CSPR is going to be changed.  */
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          arm_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          /* SPSR is going to be changed. */
>> +          /* How to read SPSR value ?  */
>> +          printf_unfiltered (_("Process record does
>> not support instruction "
>> +                             "0x%0x at
>> address %s.\n"),
>> +
>> arm_insn_r->arm_insn,
>> +                         paddress
>> (arm_insn_r->gdbarch,
>> arm_insn_r->this_addr));
>> +          return -1;
>> +        }
>> +    }
>> +  else if ((9 == arm_insn_r->decode)
>> +           && ((8 == arm_insn_r->opcode)
>> || (10 == arm_insn_r->opcode))
>> +           && (!bit (arm_insn_r->arm_insn,
>>  INSN_S_L_BIT_NUM)))
>> +    {
>> +      /* Handling SWP, SWPB.  */
>> +      /* These insns, changes register and memory as
>> well.  */
>> +      /* SWP or SWPB insn.  */
>> +      /* Get memory address given by Rn.  */
>> +      reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>> +                                  ,
>> &u_buf[0].unsigned_regval);
>> +      /* SWP insn ?, swaps word.  */
>> +      if (8 == arm_insn_r->opcode)
>> +        {
>> +          record_buf_mem[0] = 4;
>> +        }
>> +        else
>> +        {
>> +          /* SWPB insn, swaps only byte.  */
>> +          record_buf_mem[0] = 1;
>> +        }
>> +      record_buf_mem[1] = u_buf[0].unsigned_regval;
>> +      arm_insn_r->mem_rec_count = 1;
>> +      record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> +      arm_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if ((3 == arm_insn_r->decode) && (0x12
>> == opcode1)
>> +           && (sbo_sbz
>> (arm_insn_r->arm_insn, 9, 12, 1)))
>> +    {
>> +      /* Handle BLX, branch and link/exchange.  */
>> +      if (9 == arm_insn_r->opcode)
>> +      {
>> +        /* Branch is chosen by setting T bit of CSPR,
>> bitp[0] of Rm,
>> +                     and R14 stores the return
>> address.  */
>> +        record_buf[0] = ARM_PS_REGNUM;
>> +        record_buf[1] = ARM_LR_REGNUM;
>> +        arm_insn_r->reg_rec_count = 2;
>> +      }
>> +    }
>> +  else if ((7 == arm_insn_r->decode) && (0x12
>> == opcode1))
>> +    {
>> +      /* Handle enhanced software breakpoint insn, BKPT
>> */
>> +      /* CPSR is changed to be executed in ARM state,
>>  disabling normal
>> +               interrupts, entering abort mode.
>>  */
>> +      /* Accorindly to high vector configuration PC is
>> set accordingly */
>> +      /* What if user hit breakpoint and type reverse,
>> in
>> +               that case, we need to go back with
>> previous CPSR and
>> +               Program Counter.  */
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      record_buf[1] = ARM_LR_REGNUM;
>> +      arm_insn_r->reg_rec_count = 2;
>> +
>> +      /* Save SPSR also; how?  */
>> +      printf_unfiltered (_("Process record does not
>> support instruction "
>> +                           "0x%0x at address
>> %s.\n"),
>> +
>> arm_insn_r->arm_insn,
>> +                        paddress
>> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>> +      return -1;
>> +    }
>> +  else if ((11 == arm_insn_r->decode)
>> +          && (!bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM)))
>> +  {
>> +    /* Handle enhanced store insns and DSP insns (e.g.
>> LDRD)
>> +           let us begin according to addressing modes
>> for store insns
>> +           STRH insn, addresing modes are taken
>> following.  */
>> +    if ((14 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode))
>> +      {
>> +        /* 1) Handle misc store, immediate offset.
>>  */
>> +        immed_low = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> +        immed_high = bits (arm_insn_r->arm_insn, 8,
>> 11);
>> +        reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +                                    ,
>> &u_buf[0].unsigned_regval);
>> +        if (15 == reg_src1)
>> +          {
>> +            /* If R15 was used as Rn, hence current
>> PC+8.  */
>> +            u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +          }
>> +        offset_8 = (immed_high << 4) |
>> immed_low;
>> +        /* Calculate target store address.  */
>> +        if (14 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +      }
>> +    else if ((12 == arm_insn_r->opcode) || (8 ==
>> arm_insn_r->opcode))
>> +      {
>> +        /* 2) Store, register offset.  */
>> +        /* Get Rm.  */
>> +        reg_src1 = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> +        /* Get Rn.  */
>> +        reg_src2 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +                                    ,
>> &u_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                    ,
>> &u_buf[1].unsigned_regval);
>>
>> +        if (15 == reg_src2)
>> +          {
>> +            /* If R15 was used as Rn, hence current
>> PC+8.  */
>> +            u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +          }
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if (12 == arm_insn_r->opcode)
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +      }
>> +    else if ((11 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> +      || (2 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode))
>> +      {
>> +        /* 3) Store, immediate pre-indexed.  */
>> +        /* 5) Store, immediate post-indexed.  */
>> +        immed_low = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> +        immed_high = bits (arm_insn_r->arm_insn, 8,
>> 11);
>> +        offset_8 = (immed_high << 4) |
>> immed_low;
>> +        reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +        regcache_raw_read_unsigned(reg_cache,
>> reg_src1
>> +                                   ,
>> &u_buf[0].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if ((15 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> +        arm_insn_r->reg_rec_count = 1;
>> +      }
>> +    else if ((9 == arm_insn_r->opcode) || (13 ==
>> arm_insn_r->opcode)
>> +      || (0 == arm_insn_r->opcode) || (4 ==
>> arm_insn_r->opcode))
>> +      {
>> +        /* 4) Store, register pre-indexed.  */
>> +        /* 6) Store, register post -indexed.  */
>> +        reg_src1 = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> +        reg_src2 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +                                    ,
>> &u_buf[0].unsigned_regval);
>> +        regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                    ,
>> &u_buf[1].unsigned_regval);
>> +        /* Calculate target store address, Rn +/- Rm,
>> register offset.  */
>> +        if ((13 == arm_insn_r->opcode) || (4 ==
>> arm_insn_r->opcode))
>> +          {
>> +            tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> +          }
>> +        else
>> +          {
>> +            tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> +          }
>> +        record_buf_mem[0] = 2;
>> +        record_buf_mem[1] = tgt_mem_addr;
>> +        arm_insn_r->mem_rec_count = 1;
>> +        /* Record Rn also as it changes.  */
>> +        record_buf[0] = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> +        arm_insn_r->reg_rec_count = 1;
>> +      }
>> +    /* DSP insns (e.g. LDRD)  TBD.  */
>> +  }
>> +  else if ((1 == arm_insn_r->decode) && (0x12
>> == opcode1)
>> +           && sbo_sbz
>> (arm_insn_r->arm_insn, 9, 12, 1))
>> +    {
>> +      /* Handle BX, branch and link/exchange.  */
>> +      /* Branch is chosen by setting T bit of CSPR,
>> bitp[0] of Rm.  */
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      arm_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if ((1 == arm_insn_r->decode) && (0x16
>> == opcode1)
>> +           && (sbo_sbz
>> (arm_insn_r->arm_insn, 9, 4, 1))
>> +           && (sbo_sbz
>> (arm_insn_r->arm_insn, 17, 4, 1)))
>> +    {
>> +      /* Count leading zeros: CLZ.  */
>> +      record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> +      arm_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if ((!bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM))
>> +          && ((8 == arm_insn_r->opcode) ||
>> (10 == arm_insn_r->opcode))
>> +          && (sbo_sbz
>> (arm_insn_r->arm_insn, 17, 4, 1))
>> +          && (sbo_sbz
>> (arm_insn_r->arm_insn, 1, 12, 0))
>> +          )
>> +    {
>> +      /* Handle MRS insn.  */
>> +      record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> +      arm_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (arm_insn_r->opcode <= 15)
>> +    {
>> +      /* Normal data processing insns.  */
>> +      /* Out of 11 shifter operands mode, all the insn
>> modifies destination
>> +                register, which is specified by
>> 13-16 decode.  */
>> +      record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> +      record_buf[1] = ARM_PS_REGNUM;
>> +      arm_insn_r->reg_rec_count = 2;
>> +    }
>> +  else
>> +    {
>> +      gdb_assert_not_reached ("no decoding pattern
>> found");
>> +    }
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (arm_insn_r->arm_mems,
>> arm_insn_r->mem_rec_count, record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns.  */
>> +
>> +static int
>> +arm_handle_data_proc_imm_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> +  arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> +  if (((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode))
>> +       && (2 == bits (arm_insn_r->arm_insn,
>> 20, 21))
>> +       && (sbo_sbz (arm_insn_r->arm_insn,
>> 13, 4, 1))
>> +       )
>> +    {
>> +      /* Handle MSR insn.  */
>> +      if (9 == arm_insn_r->opcode)
>> +        {
>> +          /*CSPR is going to be changed.  */
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          arm_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +           /* SPSR is going to be changed.  */
>> +        }
>> +    }
>> +  else if (arm_insn_r->opcode <= 15)
>> +    {
>> +      /* Normal data processing insns.  */
>> +      /* Out of 11 shifter operands mode, all the insn
>> modifies destination
>> +                register, which is specified by
>> 13-16 decode.  */
>> +      record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> +      record_buf[1] = ARM_PS_REGNUM;
>> +      arm_insn_r->reg_rec_count = 2;
>> +    }
>> +  else
>> +    {
>> +      gdb_assert_not_reached ("no decoding pattern
>> found");
>> +    }
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (arm_insn_r->arm_mems,
>> arm_insn_r->mem_rec_count, record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns.  */
>> +
>> +static int
>> +arm_handle_ld_st_imm_offset_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +  uint32_t reg_src1 = 0 , reg_dest = 0;
>> +  uint32_t offset_12 = 0, tgt_mem_addr = 0;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +  arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> +  arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> +  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +    {
>> +      reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> +      /* LDR insn has a capability to do branching, if
>> +              MOV LR, PC is precedded by LDR insn
>> having Rn as R15
>> +              in that case, it emulates branch and
>> link insn, and hence we
>> +              need to save CSPR and PC as well.
>>  */
>> +      if (15 != reg_dest)
>> +        {
>> +          record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> +          arm_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          record_buf[0] = reg_dest;
>> +          record_buf[1] = ARM_PS_REGNUM;
>> +          arm_insn_r->reg_rec_count = 2;
>> +        }
>> +    }
>> +  else
>> +    {
>> +      if ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> +      || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> +      || (9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> +      || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> +      || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> +      || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> +      || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> +      || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> +        {
>> +          /* Store, immediate offset, immediate
>> pre-indexed,
>> +                      immediate post-indexed.
>>  */
>> +          reg_src1 = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> +          offset_12 = bits (arm_insn_r->arm_insn,
>> 0, 11);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +                                      ,
>> &u_buf.unsigned_regval);
>> +          /* U == 1 */
>> +          if (bit (arm_insn_r->arm_insn, 23))
>> +            {
>> +              tgt_mem_addr = u_buf.unsigned_regval
>> + offset_12;
>> +            }
>> +          else
>> +            {
>> +             tgt_mem_addr = u_buf.unsigned_regval -
>> offset_12;
>> +            }
>> +
>> +          switch(arm_insn_r->opcode)
>> +            {
>> +              case 8:
>> +              case 12:
>> +              case 9:
>> +              case 13:
>> +              case 1:
>> +              case 5:
>> +                /* STR insn, STRT insn.  */
>> +                record_buf_mem[0] = 4;
>> +              break;
>> +
>> +              case 10:
>> +              case 14:
>> +              case 11:
>> +              case 15:
>> +              case 3:
>> +              case 7:
>> +                /* STRB insn, STRBT insn.  */
>> +                record_buf_mem[0] = 1;
>> +              break;
>> +
>> +              default:
>> +                gdb_assert_not_reached ("Invalid
>> addressing mode for insn");
>> +              break;
>> +            }
>> +          record_buf_mem[1] = tgt_mem_addr;
>> +          arm_insn_r->mem_rec_count = 1;
>> +
>> +          if ((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> +          || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> +          || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> +          || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> +          || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> +          || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> +            {
>> +              /* We are handling pre-indexed mode;
>> post-indexed mode;
>> +                             where Rn is
>> going to be changed.  */
>> +              record_buf[0] = reg_src1;
>> +              arm_insn_r->reg_rec_count = 1;
>> +            }
>> +        }
>> +    }
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (arm_insn_r->arm_mems,
>> arm_insn_r->mem_rec_count, record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 011 insns.  */
>> +
>> +static int
>> +arm_handle_ld_st_reg_offset_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +  uint32_t shift_imm = 0;
>> +  uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> +  uint32_t immed_high = 0, immed_low = 0, offset_12 = 0,
>> tgt_mem_addr = 0;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  struct
>> +    {
>> +      LONGEST signed_word;
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset(&u_buf, 0, sizeof (u_buf));
>> +  arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> +  arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> +  /* Handle enhanced store insns and LDRD DSP insn,
>> +        let us begin according to addressing modes for
>> store insns
>> +        STRH insn.  */
>> +
>> +  /* LDR or STR?  */
>> +  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +    {
>> +      reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> +      /* LDR insn has a capability to do branching, if
>> +              MOV LR, PC is precedded by LDR insn
>> having Rn as R15
>> +              in that case, it emulates branch and
>> link insn, and hence we
>> +              need to save CSPR and PC as well.
>>  */
>> +      if (15 != reg_dest)
>> +        {
>> +          record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> +          arm_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          record_buf[0] = reg_dest;
>> +          record_buf[1] = ARM_PS_REGNUM;
>> +          arm_insn_r->reg_rec_count = 2;
>> +        }
>> +    }
>> +  else
>> +    {
>> +    if ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> +    || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> +    || (9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> +    || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> +    || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> +    || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> +    || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> +    || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> +      {
>> +        if (! bits (arm_insn_r->arm_insn, 4, 11))
>> +          {
>> +            /* Store insn, register offset and
>> register pre-indexed,
>> +                          register
>> post-indexed.  */
>> +            /* Get Rm.  */
>> +            reg_src1 = bits
>> (arm_insn_r->arm_insn, 0, 3);
>> +            /* Get Rn.  */
>> +            reg_src2 = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +
>>  , &u_buf[0].unsigned_regval);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  ,
>> &u_buf[1].unsigned_regval);
>>
>> +            if (15 == reg_src2)
>> +              {
>> +                /* If R15 was used as Rn, hence
>> current PC+8.  */
>> +                /* Pre-indexed mode doesnt reach
>> here ; illegal insn.  */
>> +                u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> +              }
>> +            /* Calculate target store address, Rn
>> +/- Rm, register offset.  */
>> +            /* U == 1.  */
>> +            if (bit (arm_insn_r->arm_insn, 23))
>> +              {
>> +                tgt_mem_addr =
>> u_buf[0].unsigned_regval +
>> u_buf[1].unsigned_regval;
>> +              }
>> +            else
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval -
>> u_buf[0].unsigned_regval;
>> +              }
>> +
>> +            switch(arm_insn_r->opcode)
>> +              {
>> +                case 8:
>> +                case 12:
>> +                case 9:
>> +                case 13:
>> +                case 1:
>> +                case 5:
>> +                  /* STR insn, STRT insn.  */
>> +                  record_buf_mem[0] = 4;
>> +                break;
>> +
>> +                case 10:
>> +                case 14:
>> +                case 11:
>> +                case 15:
>> +                case 3:
>> +                case 7:
>> +                  /* STRB insn, STRBT insn.  */
>> +                  record_buf_mem[0] = 1;
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                break;
>> +              }
>> +            record_buf_mem[1] = tgt_mem_addr;
>> +            arm_insn_r->mem_rec_count = 1;
>> +
>> +            if ((9 == arm_insn_r->opcode) || (11
>> == arm_insn_r->opcode)
>> +            || (13 == arm_insn_r->opcode) || (15
>> == arm_insn_r->opcode)
>> +            || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> +            || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> +            || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> +            || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> +              {
>> +                /* Rn is going to be changed in
>> pre-indexed mode and
>> +
>>  post-indexed mode as well.  */
>> +                record_buf[0] = reg_src2;
>> +                arm_insn_r->reg_rec_count = 1;
>> +              }
>> +          }
>> +        else
>> +          {
>> +            /* Store insn, scaled register offset;
>> scaled pre-indexed.  */
>> +            offset_12 = bits
>> (arm_insn_r->arm_insn, 5, 6);
>> +            /* Get Rm.  */
>> +            reg_src1 = bits
>> (arm_insn_r->arm_insn, 0, 3);
>> +            /* Get Rn.  */
>> +            reg_src2 = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> +            /* Get shift_imm.  */
>> +            shift_imm = bits
>> (arm_insn_r->arm_insn, 7, 11);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +
>>  , &u_buf[0].unsigned_regval);
>> +            regcache_raw_read_signed (reg_cache,
>> reg_src1
>> +
>>  , &u_buf[0].signed_word);
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  , &u_buf[1].unsigned_regval);
>> +            /* Offset_12 used as shift.  */
>> +            switch(offset_12)
>> +              {
>> +                case 0:
>> +                  /* Offset_12 used as index.
>>  */
>> +                  offset_12 =
>> u_buf[0].unsigned_regval << shift_imm;
>> +                break;
>> +
>> +                case 1:
>> +                  offset_12 =
>> (!shift_imm)?0:u_buf[0].unsigned_regval >>
>> shift_imm;
>>
>> +                break;
>> +
>> +                case 2:
>> +                  if (!shift_imm)
>> +                    {
>> +                      if (bit
>> (u_buf[0].unsigned_regval, 31))
>> +                        {
>> +                          offset_12 =
>> 0xFFFFFFFF;
>> +                        }
>> +                      else
>> +                        {
>> +                          offset_12 = 0;
>> +                        }
>> +                    }
>> +                  else
>> +                    {
>> +                      /* This is arithmetic
>> shift.  */
>> +                      offset_12 =
>> u_buf[0].signed_word >> shift_imm;
>> +                    }
>> +                  break;
>> +
>> +                case 3:
>> +                  if (!shift_imm)
>> +                    {
>> +
>>  regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
>> +
>>            , &u_buf[1].unsigned_regval);
>> +                      /* Get C flag value and
>> shift it by 31.  */
>> +                      offset_12 = (((bit
>> (u_buf[1].unsigned_regval, 29)) << 31)
>> \
>> +                                    |
>> (u_buf[0].unsigned_regval) >> 1);
>> +                    }
>> +                  else
>> +                    {
>> +                      offset_12 =
>> (u_buf[0].unsigned_regval >> shift_imm) \
>> +                         |
>> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
>> shift_imm));
>> +                    }
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                break;
>> +              }
>> +
>> +            regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>>  , &u_buf[1].unsigned_regval);
>> +            /* U == 1 */
>> +            if (bit (arm_insn_r->arm_insn, 23))
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval + offset_12;
>> +              }
>> +            else
>> +              {
>> +                tgt_mem_addr =
>> u_buf[1].unsigned_regval - offset_12;
>> +              }
>> +
>> +            switch (arm_insn_r->opcode)
>> +              {
>> +                case 8:
>> +                case 12:
>> +                case 9:
>> +                case 13:
>> +                case 1:
>> +                case 5:
>> +                  /* STR insn, STRT insn.  */
>> +                  record_buf_mem[0] = 4;
>> +                break;
>> +
>> +                case 10:
>> +                case 14:
>> +                case 11:
>> +                case 15:
>> +                case 3:
>> +                case 7:
>> +                  /* STRB insn, STRBT insn.  */
>> +                  record_buf_mem[0] = 1;
>> +                break;
>> +
>> +                default:
>> +                  gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> +                break;
>> +              }
>> +            record_buf_mem[1] = tgt_mem_addr;
>> +            arm_insn_r->mem_rec_count = 1;
>> +
>> +            if ((9 == arm_insn_r->opcode) || (11
>> == arm_insn_r->opcode)
>> +            || (13 == arm_insn_r->opcode) || (15
>> == arm_insn_r->opcode)
>> +            || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> +            || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> +            || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> +            || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> +              {
>> +                /* Rn is going to be changed in
>> register scaled pre-indexed
>> +                                mode, and
>> scaled post indexed mode.  */
>> +                record_buf[0] = reg_src2;
>> +                arm_insn_r->reg_rec_count = 1;
>> +              }
>> +          }
>> +      }
>> +    }
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (arm_insn_r->arm_mems,
>> arm_insn_r->mem_rec_count, record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns.  */
>> +
>> +static int
>> +arm_handle_ld_st_multiple_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +  struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +  uint32_t register_list[16] = {0}, register_count = 0,
>> register_bits = 0;
>>
>>
>> +  uint32_t shift_imm = 0;
>> +  uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
>> no_of_regs = 0;
>> +  uint32_t start_address = 0, index = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf[2];
>> +
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +
>> +  /* This mode is exclusively for load and store
>> multiple.  */
>> +  /* Handle incremenrt after/before and decrment
>> after.before mode;
>> +        Rn is changing depending on W bit, but as of
>> now we store Rn too
>> without optmization.  */
>> +
>> +  if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +    {
>> +      /* LDM (1,2,3) where LDM (3) changes CPSR too.
>>  */
>> +
>> +      if ((bit (arm_insn_r->arm_insn,20)) &&
>> !(bit (arm_insn_r->arm_insn,22)))
>> +        {
>> +          register_bits = bits
>> (arm_insn_r->arm_insn, 0, 15);
>> +          no_of_regs = 15;
>> +        }
>> +      else
>> +        {
>> +          register_bits = bits
>> (arm_insn_r->arm_insn, 0, 14);
>> +          no_of_regs = 14;
>> +        }
>> +      /* Get Rn.  */
>> +      reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> +      while (register_bits)
>> +       {
>> +         if (register_bits & 0x00000001)
>> +           register_list[register_count++] = 1;
>> +         register_bits = register_bits >> 1;
>> +       }
>> +
>> +        /* Extra space for Base Register and CPSR;
>> wihtout optmization.  */
>> +        record_buf[register_count] = reg_src1;
>> +        record_buf[register_count + 1] =
>> ARM_PS_REGNUM;
>> +        arm_insn_r->reg_rec_count = register_count
>> + 2;
>> +
>> +        for (register_count = 0; register_count <
>> no_of_regs; register_count++)
>> +          {
>> +            if  (register_list[register_count])
>> +              {
>> +              /* Register_count gives total no of
>> registers and dually working
>> +                             as reg number.
>>  */
>> +                record_buf[index] =
>> register_count;
>> +                index++;
>> +              }
>> +          }
>> +
>> +    }
>> +  else
>> +    {
>> +    /* It handles both STM(1) and STM(2).  */
>> +    addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> +    register_bits = bits (arm_insn_r->arm_insn, 0,
>> 15);
>> +    /* Get Rn.  */
>> +    reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> +    regcache_raw_read_unsigned (reg_cache, reg_src1
>> +                                ,
>> &u_buf[0].unsigned_regval);
>> +    while (register_bits)
>> +      {
>> +        if (register_bits & 0x00000001)
>> +           register_count++;
>> +        register_bits = register_bits >> 1;
>> +      }
>> +
>> +    switch(addr_mode)
>> +      {
>> +        /* Decrement after.  */
>> +        case 0:
>> +          start_address = (u_buf[0].unsigned_regval)
>> - (register_count * 4) +
>> 4;
>> +          arm_insn_r->mem_rec_count =
>> register_count;
>> +          while (register_count)
>> +            {
>> +              record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> +              record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> +              start_address = start_address + 4;
>> +              register_count--;
>> +            }
>> +        break;
>> +
>> +        /* Increment after.  */
>> +        case 1:
>> +          start_address = u_buf[0].unsigned_regval;
>> +          arm_insn_r->mem_rec_count =
>> register_count;
>> +          while (register_count)
>> +            {
>> +              record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> +              record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> +              start_address = start_address + 4;
>> +              register_count--;
>> +            }
>> +        break;
>> +
>> +        /* Decrement before.  */
>> +        case 2:
>> +
>> +          start_address = (u_buf[0].unsigned_regval)
>> - (register_count * 4);
>> +          arm_insn_r->mem_rec_count =
>> register_count;
>> +          while (register_count)
>> +            {
>> +              record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> +              record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> +              start_address = start_address + 4;
>> +              register_count--;
>> +            }
>> +        break;
>> +
>> +        /* Increment before.  */
>> +        case 3:
>> +          start_address = u_buf[0].unsigned_regval +
>> 4;
>> +          arm_insn_r->mem_rec_count =
>> register_count;
>> +          while (register_count)
>> +            {
>> +              record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> +              record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> +              start_address = start_address + 4;
>> +              register_count--;
>> +            }
>> +        break;
>> +
>> +        default:
>> +          gdb_assert_not_reached ("Invalid addressing
>> mode for insn");
>> +        break;
>> +      }
>> +
>> +    /* Base register also changes; based on condition
>> and W bit.  */
>> +    /* We save it anyway without optimization.  */
>> +    record_buf[0] = reg_src1;
>> +    arm_insn_r->reg_rec_count = 1;
>> +    }
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (arm_insn_r->arm_mems,
>> arm_insn_r->mem_rec_count, record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 101 insns.  */
>> +
>> +static int
>> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
>> +{
>> +
>> +  uint32_t record_buf[8];
>> +
>> +  /* Handle B, BL, BLX(1) insns.  */
>> +  /* Wihtout optmization we save link register,
>> +        CSPR for the insn which changes T bit.  */
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = ARM_LR_REGNUM;
>> +  arm_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>> +{
>> +  printf_unfiltered (_("Process record does not support
>> instruction "
>> +                     "0x%0x at address %s.\n"),
>> +                     arm_insn_r->arm_insn,
>> +                     paddress
>> (arm_insn_r->gdbarch, arm_insn_r->this_addr));
>> +
>> +   return -1;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +arm_handle_coproc_data_proc_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> +   struct gdbarch_tdep *tdep = gdbarch_tdep
>> (arm_insn_r->gdbarch);
>> +   struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> +   uint32_t shift_imm = 0;
>> +   uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
>> +   uint32_t start_address = 0;
>> +
>> +   /* Handle SWI insn; system call would be handled over
>> here.  */
>> +
>> +   arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 24, 27);
>> +   if (15 == arm_insn_r->opcode)
>> +   {
>> +        /* Handle arm syscall insn.  */
>> +        if (tdep->arm_swi_record != NULL)
>> +          {
>> +            tdep->arm_swi_record(reg_cache);
>> +          }
>> +        else
>> +          {
>> +            printf_unfiltered (_("no syscall record
>> support\n"));
>> +            return -1;
>> +          }
>> +   }
>> +
>> +   printf_unfiltered (_("Process record does not support
>> instruction "
>> +                         "0x%0x at address
>> %s.\n"),
>> +
>> arm_insn_r->arm_insn,
>> +                         paddress
>> (arm_insn_r->gdbarch,
>> arm_insn_r->this_addr));
>> +   return -1;
>> +}
>> +
>> +/* Handling opcode 000 insns.  */
>> +
>> +static int
>> +thumb_handle_shift_add_sub_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_src1 = 0;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>> +
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = reg_src1;
>> +  thumb_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +
>> +/* Handling opcode 001 insns.  */
>> +
>> +static int
>> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_src1 = 0;
>> +
>> +  reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> +
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = reg_src1;
>> +  thumb_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns.  */
>> +
>> +static int
>> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache =
>>  thumb_insn_r->regcache;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  uint32_t reg_src1 = 0, reg_src2 = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
>> +
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +      gdb_byte buf[4];
>> +    } u_buf[2];
>> +
>> +  opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
>> +
>> +  if (bit (thumb_insn_r->arm_insn, 12))
>> +    {
>> +      /* Handle load/store register offset.  */
>> +      opcode2 = bits (thumb_insn_r->arm_insn, 9,
>> 10);
>> +      if ((opcode2 >= 12) && (opcode2 <=
>> 15))
>> +        {
>> +          /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.
>>  */
>> +          reg_src1 = bits
>> (thumb_insn_r->arm_insn,0, 2);
>> +          record_buf[0] = reg_src1;
>> +          thumb_insn_r->reg_rec_count = 1;
>> +        }
>> +      else if ((opcode2 >= 8) && (opcode2
>> <= 10))
>> +        {
>> +          /* STR(2), STRB(2), STRH(2) .  */
>> +          reg_src1 = bits (thumb_insn_r->arm_insn,
>> 3, 5);
>> +          reg_src2 = bits (thumb_insn_r->arm_insn,
>> 6, 8);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +                                      ,
>> &u_buf[0].unsigned_regval);
>> +          regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +                                      ,
>> &u_buf[1].unsigned_regval);
>> +          if (8 == opcode2)
>> +            record_buf_mem[0] = 4;    /* STR (2).
>>  */
>> +          else if (10 == opcode2)
>> +            record_buf_mem[0] = 1;    /*  STRB
>> (2).  */
>> +          else if (9 == opcode2)
>> +            record_buf_mem[0] = 2;    /* STRH (2).
>>  */
>> +          record_buf_mem[1] =
>> u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>
>> +          thumb_insn_r->mem_rec_count = 1;
>> +        }
>> +    }
>> +  else if (bit (thumb_insn_r->arm_insn, 11))
>> +    {
>> +      /* Handle load from literal pool.  */
>> +      /* LDR(3).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>>
>> +      record_buf[0] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (opcode1)
>> +    {
>> +      opcode2 = bits (thumb_insn_r->arm_insn, 8,
>> 9);
>> +      opcode3 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> +      if ((3 == opcode2) && (!opcode3))
>> +        {
>> +          /* Branch with exchange.  */
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          thumb_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          /* Format 8; special data processing insns.
>>  */
>> +          reg_src1 = bits (thumb_insn_r->arm_insn,
>> 0, 2);
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          record_buf[1] = reg_src1;
>> +          thumb_insn_r->reg_rec_count = 2;
>> +        }
>> +    }
>> +  else
>> +    {
>> +      /* Format 5; data processing insns.  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> +      if (bit (thumb_insn_r->arm_insn, 7))
>> +        {
>> +          reg_src1 = reg_src1 + 8;
>> +        }
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      record_buf[1] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 2;
>> +    }
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns.  */
>> +
>> +static int
>> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_5 = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> +  if (opcode)
>> +    {
>> +      /* LDR(1).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> +      record_buf[0] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else
>> +    {
>> +      /* STR(1).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 3,
>> 5);
>> +      immed_5 = bits (thumb_insn_r->arm_insn, 6,
>> 10);
>> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>> +                                  ,
>> &u_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_5 * 4);
>> +      thumb_insn_r->mem_rec_count = 1;
>> +    }
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns.  */
>> +
>> +static int
>> +thumb_handle_ld_st_stack_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> +  if (3 == opcode)
>> +    {
>> +      /* LDR(4).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> +      record_buf[0] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (1 == opcode)
>> +    {
>> +      /* LDRH(1).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> +      record_buf[0] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (2 == opcode)
>> +    {
>> +      /* STR(3).  */
>> +      immed_8 = bits (thumb_insn_r->arm_insn, 0,
>> 7);
>> +      regcache_raw_read_unsigned (reg_cache,
>> ARM_SP_REGNUM
>> +                                  ,
>> &u_buf.unsigned_regval);
>> +      record_buf_mem[0] = 4;
>> +      record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_8 * 4);
>> +      thumb_insn_r->mem_rec_count = 1;
>> +    }
>> +  else if (0 == opcode)
>> +    {
>> +      /* STRH(1).  */
>> +      immed_5 = bits (thumb_insn_r->arm_insn, 6,
>> 10);
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 3,
>> 5);
>> +      regcache_raw_read_unsigned (reg_cache, reg_src1
>> +                                  ,
>> &u_buf.unsigned_regval);
>> +      record_buf_mem[0] = 2;
>> +      record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_5 * 2);
>> +      thumb_insn_r->mem_rec_count = 1;
>> +    }
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 101 insns.  */
>> +
>> +static int
>> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
>> = 0, immed_5 = 0;
>> +  uint32_t register_bits = 0, register_count = 0;
>> +  uint32_t register_list[8] = {0}, index = 0,
>> start_address = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> +  opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
>> +
>> +  if (14 == opcode2)
>> +    {
>> +      /* POP.  */
>> +      register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +            register_list[register_count++] = 1;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      record_buf[register_count] = ARM_PS_REGNUM;
>> +      record_buf[register_count + 1] = ARM_SP_REGNUM;
>> +      thumb_insn_r->reg_rec_count = register_count +
>> 2;
>> +      for (register_count = 0; register_count < 8;
>> register_count++)
>> +        {
>> +          if  (register_list[register_count])
>> +            {
>> +              record_buf[index] = register_count;
>> +              index++;
>> +            }
>> +        }
>> +    }
>> +  else if (10 == opcode2)
>> +    {
>> +      /* PUSH.  */
>> +      register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> +      regcache_raw_read_unsigned (reg_cache,
>> ARM_PC_REGNUM
>> +                                  ,
>> &u_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_regval -  \
>> +                   (4 * (bit
>> (thumb_insn_r->arm_insn, 8) + register_count)) ;
>> +      thumb_insn_r->mem_rec_count = register_count;
>> +      while (register_count)
>> +        {
>> +          record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> +          record_buf_mem[(register_count * 2) - 2] =
>> 4;
>> +          start_address = start_address + 4;
>> +          register_count--;
>> +        }
>> +      record_buf[0] = ARM_SP_REGNUM;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (0x1E == opcode1)
>> +    {
>> +      /* BKPT insn.  */
>> +      /* Handle enhanced software breakpoint insn,
>> BKPT.  */
>> +      /* CPSR is changed to be executed in ARM state,
>>  disabling normal
>> +               interrupts, entering abort mode.
>>  */
>> +      /* Accorindly to high vector configuration PC is
>> set accordingly.  */
>> +      /* FIX ME ?  what if user hit breakpoint and
>> type reverse, in
>> +               that case, we need to go back with
>> previous CPSR and
>> +               Program Counter..  */
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      record_buf[1] = ARM_LR_REGNUM;
>> +      thumb_insn_r->reg_rec_count = 2;
>> +      /* Save SPSR also; how?.  */
>> +      printf_unfiltered (_("Process record does not
>> support instruction "
>> +                           "0x%0x at address
>> %s.\n"),
>> +
>>  thumb_insn_r->arm_insn,
>> +                     paddress
>> (thumb_insn_r->gdbarch,
>> thumb_insn_r->this_addr));
>> +      return -1;
>> +    }
>> +  else if ((0 == opcode) || (1 == opcode))
>> +    {
>> +       /* ADD(5), ADD(6).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> +      record_buf[0] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +  else if (2 == opcode)
>> +    {
>> +      /* ADD(7), SUB(4).  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> +      record_buf[0] = ARM_SP_REGNUM;
>> +      thumb_insn_r->reg_rec_count = 1;
>> +    }
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns.  */
>> +
>> +static int
>> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
>> +{
>> +  struct gdbarch_tdep *tdep = gdbarch_tdep
>> (thumb_insn_r->gdbarch);
>> +  struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0,
>> register_count = 0;
>> +  uint32_t register_list[8] = {0}, index = 0,
>> start_address = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> +  opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> +  if (1 == opcode2)
>> +    {
>> +
>> +      /* LDMIA.  */
>> +      register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> +      /* Get Rn.  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +            register_list[register_count++] = 1;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      record_buf[register_count] = reg_src1;
>> +      thumb_insn_r->reg_rec_count = register_count +
>> 1;
>> +      for (register_count = 0; register_count < 8;
>> register_count++)
>> +        {
>> +          if  (register_list[register_count])
>> +            {
>> +              record_buf[index] = register_count;
>> +              index++;
>> +            }
>> +        }
>> +    }
>> +  else if (0 == opcode2)
>> +    {
>> +      /* It handles both STMIA.  */
>> +      register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> +      /* Get Rn.  */
>> +      reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> +      regcache_raw_read_unsigned (reg_cache, reg_src1,
>> &u_buf.unsigned_regval);
>> +      while (register_bits)
>> +        {
>> +          if (register_bits & 0x00000001)
>> +             register_count++;
>> +          register_bits = register_bits >> 1;
>> +        }
>> +      start_address = u_buf.unsigned_regval;
>> +      thumb_insn_r->mem_rec_count = register_count;
>> +      while (register_count)
>> +        {
>> +          record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> +          record_buf_mem[(register_count * 2) - 2] =
>> 4;
>> +          start_address = start_address + 4;
>> +          register_count--;
>> +        }
>> +    }
>> +  else if (0x1F == opcode1)
>> +     {
>> +        /* Handle arm syscall insn.  */
>> +        if (tdep->arm_swi_record != NULL)
>> +          {
>> +            tdep->arm_swi_record(reg_cache);
>> +          }
>> +        else
>> +          {
>> +            printf_unfiltered (_("no syscall record
>> support\n"));
>> +            return -1;
>> +          }
>> +     }
>> +
>> +  /* B(1), conditional branch is automatically taken care
>> in process_record,
>> +        as PC is saved there.  */
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +  MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> +  return 0;
>> +}
>> +
>> +/* Handling opcode 111 insns.  */
>> +
>> +static int
>> +thumb_handle_branch_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_val1 = 0;
>> +  uint32_t reg_src1 = 0;
>> +  uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> +  /* BL , BLX(1).  */
>> +  record_buf[0] = ARM_PS_REGNUM;
>> +  record_buf[1] = ARM_LR_REGNUM;
>> +  thumb_insn_r->reg_rec_count = 2;
>> +
>> +  /* B(2) is automatically taken care in process_record,
>> as PC is saved
>> +        there.  */
>> +
>> +  REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> +  return 0;
>> +}
>> +
>> +
>> +/* Decode arm/thumb insn depending on condition cods and
>> opcodes; and dispatch
>> it.  */
>> +
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t
>> insn_size)
>> +{
>> +
>> +  /* (Starting from numerical 0); bits 25, 26, 27 decodes
>> type of arm
>> instruction.  */
>> +  static int (*const arm_handle_insn[8])
>> +
>>  (insn_decode_record*) =
>> +  {
>> +      arm_handle_data_proc_misc_ld_str_insn,    /*
>> 000.  */
>> +      arm_handle_data_proc_imm_insn,
>>  /* 001.  */
>> +      arm_handle_ld_st_imm_offset_insn,         /*
>> 010.  */
>> +      arm_handle_ld_st_reg_offset_insn,         /*
>> 011.  */
>> +      arm_handle_ld_st_multiple_insn,           /*
>> 100.  */
>> +      arm_handle_brn_insn,
>>    /* 101.  */
>> +      arm_handle_coproc_insn,
>>   /* 110.  */
>> +      arm_handle_coproc_data_proc_insn          /*
>> 111.  */
>> +  };
>> +
>> +  /* (Starting from numerical 0); bits 13,14,15 decodes
>> type of thumb
>> instruction.  */
>> +  static int (*const thumb_handle_insn[8])
>> +
>>    (insn_decode_record*) =
>> +  { \
>> +      thumb_handle_shift_add_sub_insn,         /*
>> 000.  */
>> +      thumb_handle_add_sub_cmp_mov_insn,       /*
>> 001.  */
>> +      thumb_handle_ld_st_reg_offset_insn,      /*
>> 010.  */
>> +      thumb_handle_ld_st_imm_offset_insn,      /*
>> 011.  */
>> +      thumb_handle_ld_st_stack_insn,           /*
>> 100.  */
>> +      thumb_handle_misc_insn,
>>  /* 101.  */
>> +      thumb_handle_swi_insn,
>> /* 110.  */
>> +      thumb_handle_branch_insn
>> /* 111.  */
>> +  };
>> +
>> +  struct
>> +    {
>> +      gdb_byte buf[insn_size];
>> +    } u_buf;
>> +
>> +  uint32_t ret=0, insn_id = 0;
>> +
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +  if (target_read_memory (arm_record->this_addr,
>> &u_buf.buf[0], insn_size))
>> +    {
>> +      if (record_debug)
>> +        {
>> +          printf_unfiltered (_("Process record: error
>> reading memory at "
>> +                               "addr %s len
>> = %d.\n"),
>> +          paddress (arm_record->gdbarch,
>> arm_record->this_addr), insn_size);
>> +          return -1;
>> +        }
>> +    }
>> +  else if (ARM_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> +             , ARM_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>>
>> +      arm_record->cond = bits
>> (arm_record->arm_insn, 28, 31);
>> +      insn_id = bits (arm_record->arm_insn, 25,
>> 27);
>> +      ret = (0x0F != arm_record->cond)
>> +            ? arm_handle_insn[insn_id] (arm_record)
>> +            : handle_extension_space (arm_record);
>> +    }
>> +  else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* As thumb does not have condition codes,
>> following field is useless.
>> */
>> +      arm_record->cond = -1;
>> +      arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> +           , THUMB_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>> +
>> +      insn_id = bits (arm_record->arm_insn, 13,
>> 15);
>> +      ret = thumb_handle_insn[insn_id] (arm_record);
>> +    }
>> +  else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>> +    {
>> +      /* Yet to be implemented; handle thumb2 part
>> here.  */
>> +      printf_unfiltered (_("Process record does not
>> support instruction 0x%0x "
>> +                         "at address %s.\n"),
>> +
>> arm_record->arm_insn,
>> +                         paddress
>> (arm_record->gdbarch,
>> arm_record->this_addr));
>> +      ret = -1;
>> +    }
>> +  else
>> +    {
>> +      /* Throw assertion.  */
>> +      gdb_assert(0);
>> +    }
>> +
>> +  return ret;
>> +}
>> +
>> +/* Parse the current instruction and record the values of
>> the registers and
>> +   memory that will be changed in current instruction to
>> "record_arch_list".
>> +   Return -1 if something is wrong..  */
>> +
>> +int
>> +arm_process_record (struct gdbarch *gdbarch, struct
>> regcache *regcache,
>> +                             CORE_ADDR
>> insn_addr)
>> +{
>> +
>> +  enum bfd_endian byte_order = gdbarch_byte_order
>> (gdbarch);
>> +  uint32_t no_of_rec = 0;
>> +  uint32_t ret = 0;
>> +  ULONGEST t_bit = 0;
>> +
>> +  struct
>> +    {
>> +      ULONGEST unsigned_regval;
>> +    } u_buf;
>> +
>> +  insn_decode_record arm_record;
>> +  memset (&u_buf, 0, sizeof(u_buf));
>> +
>> +  memset (&arm_record, 0, sizeof
>> (insn_decode_record));
>> +  arm_record.regcache = regcache;
>> +  arm_record.this_addr = insn_addr;
>> +  arm_record.gdbarch = gdbarch;
>> +
>> +
>> +  if (record_debug > 1)
>> +    {
>> +      fprintf_unfiltered (gdb_stdlog, "Process record:
>> arm_process_record "
>> +
>>  "addr = %s\n",
>> +      paddress (gdbarch, arm_record.this_addr));
>> +    }
>> +
>> +  /* Check the insn, whether it is thumb or arm one.
>>  */
>> +
>> +  t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
>> +  regcache_raw_read_unsigned (arm_record.regcache,
>> ARM_PS_REGNUM
>> +                              ,
>> &u_buf.unsigned_regval);
>> +
>> +  if (!(u_buf.unsigned_regval & t_bit))
>> +    {
>> +      /* We are decoding arm insn.  */
>> +      ret = decode_insn (&arm_record,
>> ARM_INSN_SIZE_BYTES);
>> +    }
>> +  else
>> +    {
>> +      /* We are decoding thumb insn.  */
>> +      ret = decode_insn (&arm_record,
>> THUMB_INSN_SIZE_BYTES);
>> +    }
>> +
>> +  if (0 == ret)
>> +    {
>> +      /* Record registers.  */
>> +      record_arch_list_add_reg (arm_record.regcache,
>> ARM_PC_REGNUM);
>> +      if (arm_record.arm_regs)
>> +        {
>> +          for (no_of_rec = 0; no_of_rec <
>> arm_record.reg_rec_count;
>> no_of_rec++)
>> +            {
>> +              if (record_arch_list_add_reg
>> (arm_record.regcache \
>> +
>>     , (arm_record.arm_regs[no_of_rec])))
>> +              ret = -1;
>> +            }
>> +        }
>> +      /* Record memories.  */
>> +      if (arm_record.arm_mems)
>> +        {
>> +          for (no_of_rec = 0; no_of_rec <
>> arm_record.mem_rec_count;
>> no_of_rec++)
>> +           {
>> +              if (record_arch_list_add_mem \
>> +
>>  ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
>> +
>>  arm_record.arm_mems[no_of_rec].len))
>> +                ret = -1;
>> +           }
>> +        }
>> +
>> +      if (record_arch_list_add_end ())
>> +        ret = -1;
>> +    }
>> +
>> +  if (arm_record.arm_regs)
>> +    xfree (arm_record.arm_regs);
>> +  if (arm_record.arm_mems)
>> +    xfree (arm_record.arm_mems);
>> +
>> +  return ret;
>> +}
>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>> --- arm_orig/arm-tdep.h    2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.h    2011-05-07 14:20:31.000000000
>> +0530
>> @@ -200,6 +200,9 @@
>>   /* Return the expected next PC if FRAME is stopped at a
>> syscall
>>      instruction.  */
>>   CORE_ADDR (*syscall_next_pc) (struct frame_info
>> *frame);
>> +
>> +   /* Parse swi insn args, sycall record.  */
>> +  int (*arm_swi_record) (struct regcache *regcache);
>>  };
>>
>>  /* Structures used for displaced stepping.  */
>> @@ -310,6 +313,10 @@
>>                       struct
>> displaced_step_closure *,
>>                       CORE_ADDR, CORE_ADDR,
>> struct regcache *);
>>
>> +extern int arm_process_record (struct gdbarch *gdbarch,
>> +                                struct
>> regcache *regcache, CORE_ADDR addr);
>> +
>> +
>>  /* Functions exported from armbsd-tdep.h.  */
>>
>>  /* Return the appropriate register set for the core
>> section identified
>>
>



More information about the Gdb-patches mailing list