Message ID | CANW4E-04VhnBLveF_7uSjLaPstpwW-Yw02LhRbS=Y1eYr7Mmbg@mail.gmail.com |
---|---|
State | Superseded |
Headers | show |
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 > { > -- >
On 10/07/2013 05:16 AM, Omair Javaid wrote: > * 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) > The result looks good. > gdb/testsuite/ChangeLog: > > 2013-10-06 Omair Javaid<Omair.Javaid@linaro.org> > > * arm-tdep.c: Adds support for thumb32 instructions in > arm process record. Your changelog entry is too simple. We still need to list the added new function names here, even it is quite mechanical. We still need a NEWS entry. > + 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); > + } braces are not needed if the statement is single-line. Here and elsewhere. Why don't you add "arm*-*-linux*" triplet into proc supports_process_record and supports_reverse in testsuite/lib/gdb.exp?
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 */ -/* 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) +{ + 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 */ + uint32_t reg_rd = 0; + uint32_t op = 0; + 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; + 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; + 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; +} + +/* 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; + + 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; + 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; + 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 )) + { + /* 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 */ + 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. */