This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] Record and replay: ARM thumb 32bit instructions support
- From: Will Newton <will dot newton at linaro dot org>
- To: Omair Javaid <omair dot javaid at linaro dot org>
- Cc: gdb-patches at sourceware dot org, Patch Tracking <patches at linaro dot org>
- Date: Thu, 10 Oct 2013 13:14:43 +0100
- Subject: Re: [PATCH] Record and replay: ARM thumb 32bit instructions support
- Authentication-results: sourceware.org; auth=none
- References: <CANW4E-0ErD9CWAOjnvQhn2yaQZpAaDh_quMi0R6VDbM8p8uLtg at mail dot gmail dot com> <CANW4E-3aHm772oQtn=N4FNrZA9dhLaX6+nOyyXPkwkWNbxvXsw at mail dot gmail dot com> <CANW4E-04VhnBLveF_7uSjLaPstpwW-Yw02LhRbS=Y1eYr7Mmbg at mail dot gmail dot com>
On 06/10/13 22:16, Omair Javaid wrote:
Hi Omair,
> The patch has been updated with some minor fixes. Reverse debug
> testsuite shows significant improvement. Here are the reverse debug
> test suite statistics taken on Linux chromebook (arm v7) hardware:
>
> * Without thumb32 Patch
> Native GDB (with support process record enabled) # of expected passes 32
> Native GDB (with support process record and reverse debug enabled) #
> of expected passes 518
> Remote GDB (with support process record enabled) # of expected passes 506
> Remote GDB (with support process record and reverse debug enabled) #
> of expected passes 506
>
> * With thumb32 Patch
> Native GDB (with support process record enabled) # of expected passes
> 105 (73 new passed tests after thumb32 patch)
> Native GDB (with support process record and reverse debug enabled) #
> of expected passes 1133 (627 new passed tests after thumb32 patch)
> Remote GDB (with support process record enabled) # of expected passes
> 973 (467 new passed tests after thumb32 patch)
> Remote GDB (with support process record and reverse debug enabled) #
> of expected passes 978 (472 new passed tests after thumb32 patch)
>
> gdb/testsuite/ChangeLog:
>
> 2013-10-06 Omair Javaid <Omair.Javaid@linaro.org>
>
> * arm-tdep.c: Adds support for thumb32 instructions in
> arm process record.
>
> ---
> gdb/arm-tdep.c | 751 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 745 insertions(+), 6 deletions(-)
The patch itself appears to be line-wrapped so I couldn't apply it.
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 7c78a61..0427bdb 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -12414,8 +12414,710 @@ thumb_record_branch (insn_decode_record *thumb_insn_r)
> return 0;
> }
>
> +/* Handler for thumb2 load/store multiple instructions */
Comments should end with a full-stop and two spaces. There's quite a lot of places
where this should be fixed.
> -/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
> 0 on success
> +static int
> +thumb2_record_ld_st_mulitple (insn_decode_record *thumb2_insn_r)
Typo here, "multiple".
> +{
> + struct regcache *reg_cache = thumb2_insn_r->regcache;
> +
> + uint32_t reg_rn = 0;
> + uint32_t op = 0, 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;
> +
> + 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 */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb2_insn_r->arm_insn,
> + paddress (thumb2_insn_r->gdbarch,
> + thumb2_insn_r->this_addr));
> + return -1;
> + }
> + }
> + 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 ld/st dual, ld/st exclusive, 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 = 0, reg_rn = 0, offset_imm = 0;
> + uint32_t reg_dest1 = 0, reg_dest2 = 0;
> + uint32_t address = 0, offset_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> + uint32_t op1 = 0, op2 = 0, op3 = 0;
> + 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 shifted register instructions */
> +
> +static int
> +thumb2_record_data_proc_sreg (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
This does not seem to ever be set to a non-zero value.
> + uint32_t reg_rd = 0;
> + uint32_t op = 0;
These are initialized immediately so we could drop the initialization to zero.
> + uint32_t record_buf[8];
> +
> + op = bits (thumb2_insn_r->arm_insn, 8, 11);
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 co-processor instructions */
> +
> +static int
> +thumb2_record_coproc (insn_decode_record *thumb2_insn_r)
> +{
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),thumb2_insn_r->arm_insn,
> + paddress (thumb2_insn_r->gdbarch,
> + thumb2_insn_r->this_addr));
> +
> + return -1;
> +}
> +
> +/* Handler for thumb2 data-processing (modified immediate) instructions */
> +
> +static int
> +thumb2_record_data_proc_mod_imm (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0 ; /* Return value: -1:record failure ; 0:success */
> + uint32_t reg_rd = 0;
> + uint32_t op = 0;
Same comments as above.
> + uint32_t record_buf[8];
> +
> + op = bits (thumb2_insn_r->arm_insn, 8, 11);
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 data-processing (plain binary immediate) instructions */
> +
> +static int
> +thumb2_record_data_proc_bin_imm (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
> + uint32_t reg_rd = 0;
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 branch and miscellaneous control instructions */
> +
> +static int
> +thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t op = 0, op1 = 0, op2 = 0;
These initializations are not required either.
> + 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
> + {
> + /* SPSR is going to be changed. */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb2_insn_r->arm_insn,
> + paddress (thumb2_insn_r->gdbarch,
> + thumb2_insn_r->this_addr));
> + 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 = 0, reg_rm = 0, offset_imm = 0, shift_imm = 0;
> + uint32_t address = 0, offset_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> + uint32_t op1 = 0, op2 = 0;
> +
> + 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 SIMD element and structure load/store instructions */
> +
> +static int
> +thumb2_record_simd_struct_ld_st (insn_decode_record *thumb2_insn_r)
> +{
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"), thumb2_insn_r->arm_insn,
> + paddress (thumb2_insn_r->gdbarch,
> + thumb2_insn_r->this_addr));
> + return -1;
> +}
This function and the one for coproc instructions are identical, and the same
string is also used for misc_cntrl decoding. It shoudl be possibel to refactor
the code to just use the same function.
> +
> +/* 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 = 0, reg_rn=0;
Space around the =, but these initializations can just be removed.
> +
> + reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15);
> + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19);
> +
> + if (15 != 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 ret = 0; /* Return value: -1:record failure ; 0:success */
> + uint32_t opcode1 = 0, opcode2 = 0;
ret is not required and opcode1 and opcode2 do not seem to be used.
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 data processing (register) instructions */
> +
> +static int
> +thumb2_record_data_proc_reg (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
> + uint32_t opcode1 = 0, opcode2 = 0;
As above.
> + uint32_t record_buf[8];
> +
> + record_buf[0] = bits (thumb2_insn_r->arm_insn, 8, 11);
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 multiply, multiply accumulate, and
> + absolute difference instructions */
> +
> +static int
> +thumb2_record_mul_mla_abs_diff (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
> + uint32_t opcode1 = 0, opcode2 = 0;
> + uint32_t record_buf[8];
> +
> + record_buf[0] = bits (thumb2_insn_r->arm_insn, 8, 11);
> + 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 ret;
> +}
> +
> +/* Handler for thumb2 long multiply, long multiply accumulate, and
> + divide instructions */
> +
> +static int
> +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
> + 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 ))
Trailing space can be removed.
> + {
> + /* Load/store multiple instruction */
> + return 0;
> + }
> + else if (!((op2 & 0x64) ^ 0x04))
> + {
> + /* Load/store dual, load/store exclusive, 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 */
Indentation seems off here and a couple of places below too.
> + return 7;
> + }
> + else if (!((op2 & 0x71) ^ 0x10))
> + {
> + /* Advanced SIMD element 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, absolute difference 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. */
This line is too long an typo "failure".
> static int
> @@ -12469,6 +13171,27 @@ 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. */
This line also looks long.
> + static const sti_arm_hdl_fp_t const thumb2_handle_insn[16] =
> + { \
> + thumb2_record_ld_st_mulitple, /* 00. */
> + thumb2_record_ld_st_dual_ex_tbb, /* 01. */
> + thumb2_record_data_proc_sreg, /* 02. */
> + thumb2_record_coproc, /* 03. */
> + thumb2_record_data_proc_mod_imm, /* 04. */
> + thumb2_record_data_proc_bin_imm, /* 05. */
> + thumb2_record_branch_misc_cntrl, /* 06. */
> + thumb2_record_str_single_data, /* 07. */
> + thumb2_record_simd_struct_ld_st, /* 08. */
> + thumb2_record_ld_mem_hints, /* 09. */
> + thumb2_record_ld_mem_hints, /* 10. */
> + thumb2_record_ld_word, /* 11. */
> + thumb2_record_data_proc_reg, /* 12. */
> + thumb2_record_mul_mla_abs_diff, /* 13. */
> + thumb2_record_lmul_lmla_div, /* 14. */
> + thumb2_record_coproc /* 15. */
> + };
> +
> uint32_t ret = 0; /* return value: negative:failure 0:success. */
> uint32_t insn_id = 0;
>
> @@ -12503,11 +13226,27 @@ 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
> + {
> + printf_unfiltered (_("Process record doesnt support instruction "
> + "0x%0x at address %s.\n"),arm_record->arm_insn,
> + paddress (arm_record->gdbarch,
> + arm_record->this_addr));
> + ret = -1;
> + }
> }
> else
> {
> --
>