Message ID | CANW4E-0ErD9CWAOjnvQhn2yaQZpAaDh_quMi0R6VDbM8p8uLtg@mail.gmail.com |
---|---|
State | Superseded |
Headers | show |
On 18 September 2013 20:37, Omair Javaid <omair.javaid@linaro.org> wrote: > This patch improves gdb record and replay support for arm targets by > adding support for 32bit thumb instruction set. Record and replay test > suite is disabled for arm targets by default as some instructions and > system calls are still not functional. This patch can be tested by > recording a simple thumb mode C program on arm targets. It will not > work with any programs requiring syscall support or any program that > uses instruction not yet decoded by arm process record code. More > improvements including test suite improvement will be posted in future > patches. > > gdb/testsuite/ChangeLog: > > 2013-09-18 Omair Javaid <Omair.Javaid@linaro.org> > > * arm-tdep.c: Adds support for thumb32 instructions in > arm record and replay > > =================================================================== > RCS file: /cvs/src/src/gdb/arm-tdep.c,v > retrieving revision 1.381 > diff -u -p -r1.381 arm-tdep.c > --- gdb/arm-tdep.c 24 Jun 2013 22:18:31 -0000 1.381 > +++ gdb/arm-tdep.c 18 Sep 2013 12:13:34 -0000 > @@ -12414,6 +12414,709 @@ thumb_record_branch (insn_decode_record > return 0; > } > > +/* Handler for thumb2 load/store multiple instructions. */ > + > +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 and > + 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 instructions. */ > + 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. */ > @@ -12469,6 +13172,28 @@ decode_insn (insn_decode_record *arm_rec > 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_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 +13228,22 @@ decode_insn (insn_decode_record *arm_rec > } > 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; > + insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn); > + > + if (insn_id > 0) > + { > + ret = thumb_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 > { There is an update to this patch and a bunch of testsuite results indicating a good number of test cases passing. I ll be posting them soon.
=================================================================== RCS file: /cvs/src/src/gdb/arm-tdep.c,v retrieving revision 1.381 diff -u -p -r1.381 arm-tdep.c --- gdb/arm-tdep.c 24 Jun 2013 22:18:31 -0000 1.381 +++ gdb/arm-tdep.c 18 Sep 2013 12:13:34 -0000 @@ -12414,6 +12414,709 @@ thumb_record_branch (insn_decode_record return 0; } +/* Handler for thumb2 load/store multiple instructions. */ + +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 and + 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 instructions. */ + 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