This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/2] GDB process record and reverse debugging improvements for arm*-linux*


On 11/25/2013 06:07 PM, Oza Pawandeep wrote:
> Hi Omar,
> 
> couple of comments.
> 
> 1) you this part of code is still using MAGIC numbers.
> +      if (!(op2 & 0x71 ))
> +        {
> +          /* Store single data item.  */
> +          return 7;
> +        }
> +      else if (!((op2 & 0x71) ^ 0x10))
> +        {
> +          /* Advanced SIMD or structure load/store instructions.  */
> +          return 8;
> +        }
> +      else if (!((op2 & 0x67) ^ 0x01))
> +        {
> +          /* Load byte, memory hints instruction.  */
> +          return 9;
> +        }
> +      else if (!((op2 & 0x67) ^ 0x03))
> +        {
> +          /* Load halfword, memory hints instruction.  */
> +          return 10;
> +        }
> +      else if (!((op2 & 0x67) ^ 0x05))
> +        {
> +          /* Load word instruction.  */
> +          return 11;
> +        }
> 
In principle I agree that code must be more readable overall but that is applicable to all the code residing in arm-tdep.c. The nomenclature and bit manipulations in above code is used in line with ARM reference manual and can be understood if we have Thumb32 instruction encoding page infront.
> 
> 2) following code else part is not required.
> 
>   /* Handle MSR insn.  */
> +  if (!(op1 & 0x2) && 0x38 == op)
> +    {
> +      if (!(op2 & 0x3))
> +        {
> +          /* CPSR is going to be changed.  */
> +          record_buf[0] = ARM_PS_REGNUM;
> +          thumb2_insn_r->reg_rec_count = 1;
> +        }
> +      else
> +        {
> +          arm_record_unsupported_insn(
> thumb2_insn_r);
> +          return -1;
> +        }
> 
> because of folowing.
> // SPSRWriteByInstr()
> // ==================
> SPSRWriteByInstr(bits(32) value, bits(4) bytemask)
> if CurrentModeIsUserOrSystem() then UNPREDICTABLE;
> 
> gdb is for user space; and use space is not allowed to use SPSR
> directly using MSR instruction.
> so old code base + new code base whereever we have got SPSR getting
> modified we need to remove the same.
> 
I agree with you that we have to do a lot of rework of previous process record code. But I am not sure it would be productive for us to get working code out and loose the functionality or delay its submission. As Record/Replay is pretty much functional with this set of patches I am hoping that we can do a complete rework if required later on.

> 3) did you run the testsuite at whole code-base ?
I have tested with a a fresh git checkout alongwith 4 patches I have sent. In native mode on a samsung chromebook there are only 69 failures left out of around 2500 test cases. I am working on more bug fixes and hopefully will be able to resolve rest of issues as well. 
> 
> 
> ps: I am still struggling to get my public key setup at gdb git. will
> try to get it done as soonas I can.
> 
> Regards,
> Oza.
> 
> 
> 
> On Mon, Nov 25, 2013 at 5:19 AM, Omair Javaid <omair.javaid@linaro.org> wrote:
>> On 11/11/2013 03:09 PM, Yao Qi wrote:
>>> Patch looks good to me, and you still need a maintainer's approval.
>>>
>>> Some of the comments are too long.  Please make sure they don't exceed
>>> the limitation (around 74 characters should be fine).
>>>
>>> On 11/08/2013 11:19 AM, Omair Javaid wrote:
>>>> +/* Handler for thumb2 ld/st dual, ld/st exclusive, table branch
>>>> instructions.  */
>>>> +
>>>
>>> here.
>>>
>>>> +static int
>>>> +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r)
>>>> +{
>>>> +  struct regcache *reg_cache = thumb2_insn_r->regcache;
>>>> +
>>>
>>> ....
>>>
>>>> +
>>>> +/* Decodes thumb2 instruction type and return an instruction id.  */
>>>> +
>>>> +static unsigned int
>>>> +thumb2_record_decode_inst_id (uint32_t thumb2_insn)
>>>> +{
>>>> +  uint32_t op = 0;
>>>> +  uint32_t op1 = 0;
>>>> +  uint32_t op2 = 0;
>>>> +
>>>> +  op = bit (thumb2_insn, 15);
>>>> +  op1 = bits (thumb2_insn, 27, 28);
>>>> +  op2 = bits (thumb2_insn, 20, 26);
>>>> +
>>>> +  if (op1 == 0x01)
>>>> +    {
>>>> +      if (!(op2 & 0x64 ))
>>>> +        {
>>>> +          /* Load/store multiple instruction.  */
>>>> +          return 0;
>>>> +        }
>>>> +      else if (!((op2 & 0x64) ^ 0x04))
>>>> +        {
>>>> +          /* Load/store dual, load/store exclusive, table branch
>>>> instruction.  */
>>>
>>> and here.
>>>
>>>
>>>> +          return 1;
>>>> +        }
>>>> +      else if (!((op2 & 0x20) ^ 0x20))
>>>> +        {
>>>> +          /* Data-processing (shifted register).  */
>>>> +          return 2;
>>>> +        }
>>>> +      else if (op2 & 0x40)
>>>> +        {
>>>> +          /* Co-processor instructions.  */
>>>> +          return 3;
>>>> +        }
>>>> +    }
>>>> +  else if (op1 == 0x02)
>>>> +    {
>>>> +      if (op)
>>>> +        {
>>>> +          /* Branches and miscellaneous control instructions.  */
>>>> +          return 6;
>>>> +        }
>>>> +      else if (op2 & 0x20)
>>>> +        {
>>>> +          /* Data-processing (plain binary immediate) instruction.  */
>>>> +          return 5;
>>>> +        }
>>>> +      else
>>>> +        {
>>>> +          /* Data-processing (modified immediate).  */
>>>> +          return 4;
>>>> +        }
>>>> +    }
>>>> +  else if (op1 == 0x03)
>>>> +   {
>>>> +      if (!(op2 & 0x71 ))
>>>> +        {
>>>> +          /* Store single data item.  */
>>>> +          return 7;
>>>> +        }
>>>> +      else if (!((op2 & 0x71) ^ 0x10))
>>>> +        {
>>>> +          /* Advanced SIMD element or structure load/store
>>>> instructions.  */
>>>
>>> here.
>>>
>>>> +          return 8;
>>>> +        }
>>>> +      else if (!((op2 & 0x67) ^ 0x01))
>>>> +        {
>>>> +          /* Load byte, memory hints instruction.  */
>>>> +          return 9;
>>>> +        }
>>>> +      else if (!((op2 & 0x67) ^ 0x03))
>>>> +        {
>>>> +          /* Load halfword, memory hints instruction.  */
>>>> +          return 10;
>>>> +        }
>>>> +      else if (!((op2 & 0x67) ^ 0x05))
>>>> +        {
>>>> +          /* Load word instruction.  */
>>>> +          return 11;
>>>> +        }
>>>> +      else if (!((op2 & 0x70) ^ 0x20))
>>>> +        {
>>>> +          /* Data-processing (register) instruction.  */
>>>> +          return 12;
>>>> +        }
>>>> +      else if (!((op2 & 0x78) ^ 0x30))
>>>> +        {
>>>> +          /* Multiply, multiply accumulate, absolute difference
>>>> instruction.  */
>>>
>>> here.
>>>
>>>> +          return 13;
>>>> +        }
>>>> +      else if (!((op2 & 0x78) ^ 0x38))
>>>> +        {
>>>> +          /* Long multiply, long multiply accumulate, and divide.  */
>>>> +          return 14;
>>>> +        }
>>>> +      else if (op2 & 0x40)
>>>> +        {
>>>> +          /* Co-processor instructions.  */
>>>> +          return 15;
>>>> +        }
>>>> +   }
>>>> +
>>>> +  return -1;
>>>> +}
>>>>
>>>>   /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0
>>>> on success
>>>>   and positive val on fauilure.  */
>>>> @@ -12452,7 +13034,7 @@ decode_insn (insn_decode_record *arm_rec
>>>>       arm_record_ld_st_reg_offset,        /* 011.  */
>>>>       arm_record_ld_st_multiple,          /* 100.  */
>>>>       arm_record_b_bl,                    /* 101.  */
>>>> -    arm_record_coproc,                  /* 110.  */
>>>> +    arm_record_unsupported_insn,                  /* 110.  */
>>>>       arm_record_coproc_data_proc         /* 111.  */
>>>>     };
>>>>
>>>> @@ -12469,6 +13051,27 @@ decode_insn (insn_decode_record *arm_rec
>>>>       thumb_record_branch                /* 111.  */
>>>>     };
>>>>
>>>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
>>>> instruction.  */
>>>
>>> here.
>>>
>>
>> Patch has been updated after incorporating suggestions. Looking for a final
>> commit verdict.
>>
>> This patch adds support for recording thumb32 instructions. This patch also
>> fixes bugs in arm process record instruction decoding.
>>
>> gdb:
>>
>> 2013-11-08  Omair Javaid  <omair.javaid@linaro.org>
>>
>>         * arm-tdep.c (struct arm_mem_r): Use uint32_t for memory address.
>>         (arm_record_unsupported_insn): New function.
>>         (arm_record_coproc_data_proc): Removed.
>>         (thumb2_record_ld_st_multiple): New function.
>>         (thumb2_record_ld_st_dual_ex_tbb): New function.
>>         (thumb2_record_data_proc_sreg_mimm): New function.
>>         (thumb2_record_ps_dest_generic): New function.
>>         (thumb2_record_branch_misc_cntrl): New function.
>>         (thumb2_record_str_single_data): New function.
>>         (thumb2_record_ld_mem_hints): New function.
>>         (thumb2_record_ld_word): New function.
>>         (thumb2_record_lmul_lmla_div): New function.
>>         (thumb2_record_decode_inst_id): New function.
>>         (decode_insn): Add thumb32 instruction handlers.
>>
>> ---
>>  gdb/arm-tdep.c |  627 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 619 insertions(+), 8 deletions(-)
>>
>> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
>> index 7c78a61..ecaced7 100644
>> --- a/gdb/arm-tdep.c
>> +++ b/gdb/arm-tdep.c
>> @@ -10618,7 +10618,7 @@ vfp - VFP co-processor."),
>>  struct arm_mem_r
>>  {
>>    uint32_t len;    /* Record length.  */
>> -  CORE_ADDR addr;  /* Memory address.  */
>> +  uint32_t addr;   /* Memory address.  */
>>  };
>>
>>  /* ARM instruction record contains opcode of current insn
>> @@ -11919,7 +11919,7 @@ arm_record_b_bl (insn_decode_record *arm_insn_r)
>>  /* Handling opcode 110 insns.  */
>>
>>  static int
>> -arm_record_coproc (insn_decode_record *arm_insn_r)
>> +arm_record_unsupported_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,
>> @@ -12414,6 +12414,584 @@ thumb_record_branch (insn_decode_record *thumb_insn_r)
>>    return 0;
>>  }
>>
>> +/* Handler for thumb2 load/store multiple instructions.  */
>> +
>> +static int
>> +thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r)
>> +{
>> +  struct regcache *reg_cache = thumb2_insn_r->regcache;
>> +
>> +  uint32_t reg_rn, op;
>> +  uint32_t register_bits = 0, register_count = 0;
>> +  uint32_t index = 0, start_address = 0;
>> +  uint32_t record_buf[24], record_buf_mem[48];
>> +
>> +  ULONGEST u_regval = 0;
>> +
>> +  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +  op = bits (thumb2_insn_r->arm_insn, 23, 24);
>> +
>> +  if (0 == op || 3 == op)
>> +    {
>> +      if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +        {
>> +          /* Handle RFE instruction.  */
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          thumb2_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          /* Handle SRS instruction after reading banked SP.  */
>> +          return arm_record_unsupported_insn (thumb2_insn_r);
>> +        }
>> +    }
>> +  else if(1 == op || 2 == op)
>> +    {
>> +      if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +        {
>> +          /* Handle LDM/LDMIA/LDMFD and LDMDB/LDMEA instructions.  */
>> +          register_bits = bits (thumb2_insn_r->arm_insn, 0, 15);
>> +          while (register_bits)
>> +            {
>> +              if (register_bits & 0x00000001)
>> +                record_buf[index++] = register_count;
>> +
>> +              register_count++;
>> +              register_bits = register_bits >> 1;
>> +            }
>> +          record_buf[index++] = reg_rn;
>> +          record_buf[index++] = ARM_PS_REGNUM;
>> +          thumb2_insn_r->reg_rec_count = index;
>> +        }
>> +      else
>> +        {
>> +          /* Handle STM/STMIA/STMEA and STMDB/STMFD.  */
>> +          register_bits = bits (thumb2_insn_r->arm_insn, 0, 15);
>> +          regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval);
>> +          while (register_bits)
>> +            {
>> +              if (register_bits & 0x00000001)
>> +                register_count++;
>> +
>> +              register_bits = register_bits >> 1;
>> +            }
>> +
>> +          if (1 == op)
>> +            {
>> +              /* Start address calculation for LDMDB/LDMEA.  */
>> +              start_address = u_regval;
>> +            }
>> +          else if (2 == op)
>> +            {
>> +              /* Start address calculation for LDMDB/LDMEA.  */
>> +              start_address = (u_regval) - (register_count * 4);
>> +            }
>> +
>> +          thumb2_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] = reg_rn;
>> +          record_buf[1] = ARM_PS_REGNUM;
>> +          thumb2_insn_r->reg_rec_count = 2;
>> +        }
>> +    }
>> +
>> +  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
>> +            record_buf_mem);
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 load/store (dual/exclusive) and table branch
>> +   instructions.  */
>> +
>> +static int
>> +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r)
>> +{
>> +  struct regcache *reg_cache = thumb2_insn_r->regcache;
>> +
>> +  uint32_t reg_rd, reg_rn, offset_imm;
>> +  uint32_t reg_dest1, reg_dest2;
>> +  uint32_t address, offset_addr;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +  uint32_t op1, op2, op3;
>> +  LONGEST s_word;
>> +
>> +  ULONGEST u_regval[2];
>> +
>> +  op1 = bits (thumb2_insn_r->arm_insn, 23, 24);
>> +  op2 = bits (thumb2_insn_r->arm_insn, 20, 21);
>> +  op3 = bits (thumb2_insn_r->arm_insn, 4, 7);
>> +
>> +  if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +    {
>> +      if(!(1 == op1 && 1 == op2 && (0 == op3 || 1 == op3)))
>> +        {
>> +          reg_dest1 = bits (thumb2_insn_r->arm_insn, 12, 15);
>> +          record_buf[0] = reg_dest1;
>> +          record_buf[1] = ARM_PS_REGNUM;
>> +          thumb2_insn_r->reg_rec_count = 2;
>> +        }
>> +
>> +      if (3 == op2 || (op1 & 2) || (1 == op1 && 1 == op2 && 7 == op3))
>> +        {
>> +          reg_dest2 = bits (thumb2_insn_r->arm_insn, 8, 11);
>> +          record_buf[2] = reg_dest2;
>> +          thumb2_insn_r->reg_rec_count = 3;
>> +        }
>> +    }
>> +  else
>> +    {
>> +      reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +      regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]);
>> +
>> +      if (0 == op1 && 0 == op2)
>> +        {
>> +          /* Handle STREX.  */
>> +          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
>> +          address = u_regval[0] + (offset_imm * 4);
>> +          record_buf_mem[0] = 4;
>> +          record_buf_mem[1] = address;
>> +          thumb2_insn_r->mem_rec_count = 1;
>> +          reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3);
>> +          record_buf[0] = reg_rd;
>> +          thumb2_insn_r->reg_rec_count = 1;
>> +        }
>> +      else if (1 == op1 && 0 == op2)
>> +        {
>> +          reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3);
>> +          record_buf[0] = reg_rd;
>> +          thumb2_insn_r->reg_rec_count = 1;
>> +          address = u_regval[0];
>> +          record_buf_mem[1] = address;
>> +
>> +          if (4 == op3)
>> +            {
>> +              /* Handle STREXB.  */
>> +              record_buf_mem[0] = 1;
>> +              thumb2_insn_r->mem_rec_count = 1;
>> +            }
>> +          else if (5 == op3)
>> +            {
>> +              /* Handle STREXH.  */
>> +              record_buf_mem[0] = 2 ;
>> +              thumb2_insn_r->mem_rec_count = 1;
>> +            }
>> +          else if (7 == op3)
>> +            {
>> +              /* Handle STREXD.  */
>> +              address = u_regval[0];
>> +              record_buf_mem[0] = 4;
>> +              record_buf_mem[2] = 4;
>> +              record_buf_mem[3] = address + 4;
>> +              thumb2_insn_r->mem_rec_count = 2;
>> +            }
>> +        }
>> +      else
>> +        {
>> +          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
>> +
>> +          if (bit (thumb2_insn_r->arm_insn, 24))
>> +            {
>> +              if (bit (thumb2_insn_r->arm_insn, 23))
>> +                offset_addr = u_regval[0] + (offset_imm * 4);
>> +              else
>> +                offset_addr = u_regval[0] - (offset_imm * 4);
>> +
>> +              address = offset_addr;
>> +            }
>> +          else
>> +            address = u_regval[0];
>> +
>> +          record_buf_mem[0] = 4;
>> +          record_buf_mem[1] = address;
>> +          record_buf_mem[2] = 4;
>> +          record_buf_mem[3] = address + 4;
>> +          thumb2_insn_r->mem_rec_count = 2;
>> +          record_buf[0] = reg_rn;
>> +          thumb2_insn_r->reg_rec_count = 1;
>> +        }
>> +    }
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
>> +            record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 data processing (shift register and modified immediate)
>> +   instructions.  */
>> +
>> +static int
>> +thumb2_record_data_proc_sreg_mimm (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t reg_rd, op;
>> +  uint32_t record_buf[8];
>> +
>> +  op = bits (thumb2_insn_r->arm_insn, 21, 24);
>> +  reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11);
>> +
>> +  if ((0 == op || 4 == op || 8 == op || 13 == op) && 15 == reg_rd)
>> +    {
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 1;
>> +    }
>> +  else
>> +    {
>> +      record_buf[0] = reg_rd;
>> +      record_buf[1] = ARM_PS_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 2;
>> +    }
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return 0;
>> +}
>> +
>> +/* Generic handler for thumb2 instructions which effect destination and PS
>> +   registers.  */
>> +
>> +static int
>> +thumb2_record_ps_dest_generic (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t reg_rd;
>> +  uint32_t record_buf[8];
>> +
>> +  reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11);
>> +
>> +  record_buf[0] = reg_rd;
>> +  record_buf[1] = ARM_PS_REGNUM;
>> +  thumb2_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 branch and miscellaneous control instructions.  */
>> +
>> +static int
>> +thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t op, op1, op2;
>> +  uint32_t record_buf[8];
>> +
>> +  op = bits (thumb2_insn_r->arm_insn, 20, 26);
>> +  op1 = bits (thumb2_insn_r->arm_insn, 12, 14);
>> +  op2 = bits (thumb2_insn_r->arm_insn, 8, 11);
>> +
>> +  /* Handle MSR insn.  */
>> +  if (!(op1 & 0x2) && 0x38 == op)
>> +    {
>> +      if (!(op2 & 0x3))
>> +        {
>> +          /* CPSR is going to be changed.  */
>> +          record_buf[0] = ARM_PS_REGNUM;
>> +          thumb2_insn_r->reg_rec_count = 1;
>> +        }
>> +      else
>> +        {
>> +          arm_record_unsupported_insn(thumb2_insn_r);
>> +          return -1;
>> +        }
>> +    }
>> +  else if (4 == (op1 & 0x5) || 5 == (op1 & 0x5))
>> +    {
>> +      /* BLX.  */
>> +      record_buf[0] = ARM_PS_REGNUM;
>> +      record_buf[1] = ARM_LR_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 2;
>> +    }
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 store single data item instructions.  */
>> +
>> +static int
>> +thumb2_record_str_single_data (insn_decode_record *thumb2_insn_r)
>> +{
>> +  struct regcache *reg_cache = thumb2_insn_r->regcache;
>> +
>> +  uint32_t reg_rn, reg_rm, offset_imm, shift_imm;
>> +  uint32_t address, offset_addr;
>> +  uint32_t record_buf[8], record_buf_mem[8];
>> +  uint32_t op1, op2;
>> +
>> +  ULONGEST u_regval[2];
>> +
>> +  op1 = bits (thumb2_insn_r->arm_insn, 21, 23);
>> +  op2 = bits (thumb2_insn_r->arm_insn, 6, 11);
>> +  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +  regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]);
>> +
>> +  if (bit (thumb2_insn_r->arm_insn, 23))
>> +    {
>> +      /* T2 encoding.  */
>> +      offset_imm = bits (thumb2_insn_r->arm_insn, 0, 11);
>> +      offset_addr = u_regval[0] + offset_imm;
>> +      address = offset_addr;
>> +    }
>> +  else
>> +    {
>> +      /* T3 encoding.  */
>> +      if ((0 == op1 || 1 == op1 || 2 == op1) && !(op2 & 0x20))
>> +        {
>> +          /* Handle STRB (register).  */
>> +          reg_rm = bits (thumb2_insn_r->arm_insn, 0, 3);
>> +          regcache_raw_read_unsigned (reg_cache, reg_rm, &u_regval[1]);
>> +          shift_imm = bits (thumb2_insn_r->arm_insn, 4, 5);
>> +          offset_addr = u_regval[1] << shift_imm;
>> +          address = u_regval[0] + offset_addr;
>> +        }
>> +      else
>> +        {
>> +          offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7);
>> +          if (bit (thumb2_insn_r->arm_insn, 10))
>> +            {
>> +              if (bit (thumb2_insn_r->arm_insn, 9))
>> +                offset_addr = u_regval[0] + offset_imm;
>> +              else
>> +                offset_addr = u_regval[0] - offset_imm;
>> +
>> +              address = offset_addr;
>> +            }
>> +          else
>> +            address = u_regval[0];
>> +        }
>> +    }
>> +
>> +  switch (op1)
>> +    {
>> +      /* Store byte instructions.  */
>> +      case 4:
>> +      case 0:
>> +        record_buf_mem[0] = 1;
>> +      break;
>> +      /* Store half word instructions.  */
>> +      case 1:
>> +      case 5:
>> +        record_buf_mem[0] = 2;
>> +      break;
>> +      /* Store word instructions.  */
>> +      case 2:
>> +      case 6:
>> +        record_buf_mem[0] = 4;
>> +      break;
>> +
>> +      default:
>> +        gdb_assert_not_reached ("no decoding pattern found");
>> +      break;
>> +    }
>> +
>> +  record_buf_mem[1] = address;
>> +  thumb2_insn_r->mem_rec_count = 1;
>> +  record_buf[0] = reg_rn;
>> +  thumb2_insn_r->reg_rec_count = 1;
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count,
>> +            record_buf_mem);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 load memory hints instructions.  */
>> +
>> +static int
>> +thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_rt, reg_rn;
>> +
>> +  reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15);
>> +  reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +
>> +  if (ARM_PC_REGNUM != reg_rt)
>> +    {
>> +      record_buf[0] = reg_rt;
>> +      record_buf[1] = reg_rn;
>> +      record_buf[2] = ARM_PS_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 3;
>> +
>> +      REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +                record_buf);
>> +      return 0;
>> +    }
>> +
>> +  return -1;
>> +}
>> +
>> +/* Handler for thumb2 load word instructions.  */
>> +
>> +static int
>> +thumb2_record_ld_word (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t opcode1 = 0, opcode2 = 0;
>> +  uint32_t record_buf[8];
>> +
>> +  record_buf[0] = bits (thumb2_insn_r->arm_insn, 12, 15);
>> +  record_buf[1] = ARM_PS_REGNUM;
>> +  thumb2_insn_r->reg_rec_count = 2;
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return 0;
>> +}
>> +
>> +/* Handler for thumb2 long multiply, long multiply accumulate, and
>> +   divide instructions.  Return value: -1:record failure ;  0:success.  */
>> +
>> +static int
>> +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r)
>> +{
>> +  uint32_t ret = 0;
>> +  uint32_t opcode1 = 0, opcode2 = 0;
>> +  uint32_t record_buf[8];
>> +  uint32_t reg_src1 = 0;
>> +
>> +  opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22);
>> +  opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7);
>> +
>> +  if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6))
>> +    {
>> +      /* Handle SMULL, UMULL, SMULAL.  */
>> +      /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S).  */
>> +      record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +      record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15);
>> +      record_buf[2] = ARM_PS_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 3;
>> +    }
>> +  else if (1 == opcode1 || 3 == opcode2)
>> +    {
>> +      /* Handle SDIV and UDIV.  */
>> +      record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19);
>> +      record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15);
>> +      record_buf[2] = ARM_PS_REGNUM;
>> +      thumb2_insn_r->reg_rec_count = 3;
>> +    }
>> +  else
>> +    ret = -1;
>> +
>> +  REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count,
>> +            record_buf);
>> +  return ret;
>> +}
>> +
>> +/* Decodes thumb2 instruction type and return an instruction id.  */
>> +
>> +static unsigned int
>> +thumb2_record_decode_inst_id (uint32_t thumb2_insn)
>> +{
>> +  uint32_t op = 0;
>> +  uint32_t op1 = 0;
>> +  uint32_t op2 = 0;
>> +
>> +  op = bit (thumb2_insn, 15);
>> +  op1 = bits (thumb2_insn, 27, 28);
>> +  op2 = bits (thumb2_insn, 20, 26);
>> +
>> +  if (op1 == 0x01)
>> +    {
>> +      if (!(op2 & 0x64 ))
>> +        {
>> +          /* Load/store multiple instruction.  */
>> +          return 0;
>> +        }
>> +      else if (!((op2 & 0x64) ^ 0x04))
>> +        {
>> +          /* Load/store (dual/exclusive) and table branch instruction.  */
>> +          return 1;
>> +        }
>> +      else if (!((op2 & 0x20) ^ 0x20))
>> +        {
>> +          /* Data-processing (shifted register).  */
>> +          return 2;
>> +        }
>> +      else if (op2 & 0x40)
>> +        {
>> +          /* Co-processor instructions.  */
>> +          return 3;
>> +        }
>> +    }
>> +  else if (op1 == 0x02)
>> +    {
>> +      if (op)
>> +        {
>> +          /* Branches and miscellaneous control instructions.  */
>> +          return 6;
>> +        }
>> +      else if (op2 & 0x20)
>> +        {
>> +          /* Data-processing (plain binary immediate) instruction.  */
>> +          return 5;
>> +        }
>> +      else
>> +        {
>> +          /* Data-processing (modified immediate).  */
>> +          return 4;
>> +        }
>> +    }
>> +  else if (op1 == 0x03)
>> +    {
>> +      if (!(op2 & 0x71 ))
>> +        {
>> +          /* Store single data item.  */
>> +          return 7;
>> +        }
>> +      else if (!((op2 & 0x71) ^ 0x10))
>> +        {
>> +          /* Advanced SIMD or structure load/store instructions.  */
>> +          return 8;
>> +        }
>> +      else if (!((op2 & 0x67) ^ 0x01))
>> +        {
>> +          /* Load byte, memory hints instruction.  */
>> +          return 9;
>> +        }
>> +      else if (!((op2 & 0x67) ^ 0x03))
>> +        {
>> +          /* Load halfword, memory hints instruction.  */
>> +          return 10;
>> +        }
>> +      else if (!((op2 & 0x67) ^ 0x05))
>> +        {
>> +          /* Load word instruction.  */
>> +          return 11;
>> +        }
>> +      else if (!((op2 & 0x70) ^ 0x20))
>> +        {
>> +          /* Data-processing (register) instruction.  */
>> +          return 12;
>> +        }
>> +      else if (!((op2 & 0x78) ^ 0x30))
>> +        {
>> +          /* Multiply, multiply accumulate, abs diff instruction.  */
>> +          return 13;
>> +        }
>> +      else if (!((op2 & 0x78) ^ 0x38))
>> +        {
>> +          /* Long multiply, long multiply accumulate, and divide.  */
>> +          return 14;
>> +        }
>> +      else if (op2 & 0x40)
>> +        {
>> +          /* Co-processor instructions.  */
>> +          return 15;
>> +        }
>> +   }
>> +
>> +  return -1;
>> +}
>>
>>  /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success
>>  and positive val on fauilure.  */
>> @@ -12452,7 +13030,7 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
>>      arm_record_ld_st_reg_offset,        /* 011.  */
>>      arm_record_ld_st_multiple,          /* 100.  */
>>      arm_record_b_bl,                    /* 101.  */
>> -    arm_record_coproc,                  /* 110.  */
>> +    arm_record_unsupported_insn,                  /* 110.  */
>>      arm_record_coproc_data_proc         /* 111.  */
>>    };
>>
>> @@ -12469,6 +13047,28 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
>>      thumb_record_branch                /* 111.  */
>>    };
>>
>> +  /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
>> +     instruction.  */
>> +  static const sti_arm_hdl_fp_t const thumb2_handle_insn[16] =
>> +  { \
>> +    thumb2_record_ld_st_multiple,       /* 00.  */
>> +    thumb2_record_ld_st_dual_ex_tbb,    /* 01.  */
>> +    thumb2_record_data_proc_sreg_mimm,  /* 02.  */
>> +    arm_record_unsupported_insn,        /* 03.  */
>> +    thumb2_record_data_proc_sreg_mimm,  /* 04.  */
>> +    thumb2_record_ps_dest_generic,      /* 05.  */
>> +    thumb2_record_branch_misc_cntrl,    /* 06.  */
>> +    thumb2_record_str_single_data,      /* 07.  */
>> +    arm_record_unsupported_insn,        /* 08.  */
>> +    thumb2_record_ld_mem_hints,         /* 09.  */
>> +    thumb2_record_ld_mem_hints,         /* 10.  */
>> +    thumb2_record_ld_word,              /* 11.  */
>> +    thumb2_record_ps_dest_generic,      /* 12.  */
>> +    thumb2_record_ps_dest_generic,      /* 13.  */
>> +    thumb2_record_lmul_lmla_div,        /* 14.  */
>> +    arm_record_unsupported_insn         /* 15.  */
>> +  };
>> +
>>    uint32_t ret = 0;    /* return value: negative:failure   0:success.  */
>>    uint32_t insn_id = 0;
>>
>> @@ -12503,11 +13103,22 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type,
>>      }
>>    else if (THUMB2_RECORD == record_type)
>>      {
>> -      printf_unfiltered (_("Process record doesnt support thumb32 instruction "
>> -                           "0x%0x at address %s.\n"),arm_record->arm_insn,
>> -                           paddress (arm_record->gdbarch,
>> -                           arm_record->this_addr));
>> -      ret = -1;
>> +      /* As thumb does not have condition codes, we set negative.  */
>> +      arm_record->cond = -1;
>> +
>> +      /* Swap first half of 32bit thumb instruction with second half.  */
>> +      arm_record->arm_insn = (arm_record->arm_insn >> 16) |
>> +                             (arm_record->arm_insn << 16);
>> +
>> +      insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn);
>> +
>> +      if (insn_id >= 0)
>> +        ret = thumb2_handle_insn[insn_id] (arm_record);
>> +      else
>> +        {
>> +          arm_record_unsupported_insn(arm_record);
>> +          ret = -1;
>> +        }
>>      }
>>    else
>>      {
>> --
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]