Message ID | 52929080.1030304@linaro.org |
---|---|
State | Accepted |
Headers | show |
Hi Omar, couple of comments. 1) you this part of code is still using MAGIC numbers. + if (!(op2 & 0x71 )) + { + /* Store single data item. */ + return 7; + } + else if (!((op2 & 0x71) ^ 0x10)) + { + /* Advanced SIMD or structure load/store instructions. */ + return 8; + } + else if (!((op2 & 0x67) ^ 0x01)) + { + /* Load byte, memory hints instruction. */ + return 9; + } + else if (!((op2 & 0x67) ^ 0x03)) + { + /* Load halfword, memory hints instruction. */ + return 10; + } + else if (!((op2 & 0x67) ^ 0x05)) + { + /* Load word instruction. */ + return 11; + } 2) following code else part is not required. /* Handle MSR insn. */ + if (!(op1 & 0x2) && 0x38 == op) + { + if (!(op2 & 0x3)) + { + /* CPSR is going to be changed. */ + record_buf[0] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 1; + } + else + { + arm_record_unsupported_insn( thumb2_insn_r); + return -1; + } because of folowing. // SPSRWriteByInstr() // ================== SPSRWriteByInstr(bits(32) value, bits(4) bytemask) if CurrentModeIsUserOrSystem() then UNPREDICTABLE; gdb is for user space; and use space is not allowed to use SPSR directly using MSR instruction. so old code base + new code base whereever we have got SPSR getting modified we need to remove the same. 3) did you run the testsuite at whole code-base ? ps: I am still struggling to get my public key setup at gdb git. will try to get it done as soonas I can. Regards, Oza. On Mon, Nov 25, 2013 at 5:19 AM, Omair Javaid <omair.javaid@linaro.org> wrote: > On 11/11/2013 03:09 PM, Yao Qi wrote: >> Patch looks good to me, and you still need a maintainer's approval. >> >> Some of the comments are too long. Please make sure they don't exceed >> the limitation (around 74 characters should be fine). >> >> On 11/08/2013 11:19 AM, Omair Javaid wrote: >>> +/* Handler for thumb2 ld/st dual, ld/st exclusive, table branch >>> instructions. */ >>> + >> >> here. >> >>> +static int >>> +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r) >>> +{ >>> + struct regcache *reg_cache = thumb2_insn_r->regcache; >>> + >> >> .... >> >>> + >>> +/* Decodes thumb2 instruction type and return an instruction id. */ >>> + >>> +static unsigned int >>> +thumb2_record_decode_inst_id (uint32_t thumb2_insn) >>> +{ >>> + uint32_t op = 0; >>> + uint32_t op1 = 0; >>> + uint32_t op2 = 0; >>> + >>> + op = bit (thumb2_insn, 15); >>> + op1 = bits (thumb2_insn, 27, 28); >>> + op2 = bits (thumb2_insn, 20, 26); >>> + >>> + if (op1 == 0x01) >>> + { >>> + if (!(op2 & 0x64 )) >>> + { >>> + /* Load/store multiple instruction. */ >>> + return 0; >>> + } >>> + else if (!((op2 & 0x64) ^ 0x04)) >>> + { >>> + /* Load/store dual, load/store exclusive, table branch >>> instruction. */ >> >> and here. >> >> >>> + return 1; >>> + } >>> + else if (!((op2 & 0x20) ^ 0x20)) >>> + { >>> + /* Data-processing (shifted register). */ >>> + return 2; >>> + } >>> + else if (op2 & 0x40) >>> + { >>> + /* Co-processor instructions. */ >>> + return 3; >>> + } >>> + } >>> + else if (op1 == 0x02) >>> + { >>> + if (op) >>> + { >>> + /* Branches and miscellaneous control instructions. */ >>> + return 6; >>> + } >>> + else if (op2 & 0x20) >>> + { >>> + /* Data-processing (plain binary immediate) instruction. */ >>> + return 5; >>> + } >>> + else >>> + { >>> + /* Data-processing (modified immediate). */ >>> + return 4; >>> + } >>> + } >>> + else if (op1 == 0x03) >>> + { >>> + if (!(op2 & 0x71 )) >>> + { >>> + /* Store single data item. */ >>> + return 7; >>> + } >>> + else if (!((op2 & 0x71) ^ 0x10)) >>> + { >>> + /* Advanced SIMD element or structure load/store >>> instructions. */ >> >> here. >> >>> + return 8; >>> + } >>> + else if (!((op2 & 0x67) ^ 0x01)) >>> + { >>> + /* Load byte, memory hints instruction. */ >>> + return 9; >>> + } >>> + else if (!((op2 & 0x67) ^ 0x03)) >>> + { >>> + /* Load halfword, memory hints instruction. */ >>> + return 10; >>> + } >>> + else if (!((op2 & 0x67) ^ 0x05)) >>> + { >>> + /* Load word instruction. */ >>> + return 11; >>> + } >>> + else if (!((op2 & 0x70) ^ 0x20)) >>> + { >>> + /* Data-processing (register) instruction. */ >>> + return 12; >>> + } >>> + else if (!((op2 & 0x78) ^ 0x30)) >>> + { >>> + /* Multiply, multiply accumulate, absolute difference >>> instruction. */ >> >> here. >> >>> + return 13; >>> + } >>> + else if (!((op2 & 0x78) ^ 0x38)) >>> + { >>> + /* Long multiply, long multiply accumulate, and divide. */ >>> + return 14; >>> + } >>> + else if (op2 & 0x40) >>> + { >>> + /* Co-processor instructions. */ >>> + return 15; >>> + } >>> + } >>> + >>> + return -1; >>> +} >>> >>> /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 >>> on success >>> and positive val on fauilure. */ >>> @@ -12452,7 +13034,7 @@ decode_insn (insn_decode_record *arm_rec >>> arm_record_ld_st_reg_offset, /* 011. */ >>> arm_record_ld_st_multiple, /* 100. */ >>> arm_record_b_bl, /* 101. */ >>> - arm_record_coproc, /* 110. */ >>> + arm_record_unsupported_insn, /* 110. */ >>> arm_record_coproc_data_proc /* 111. */ >>> }; >>> >>> @@ -12469,6 +13051,27 @@ decode_insn (insn_decode_record *arm_rec >>> thumb_record_branch /* 111. */ >>> }; >>> >>> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb >>> instruction. */ >> >> here. >> > > Patch has been updated after incorporating suggestions. Looking for a final > commit verdict. > > This patch adds support for recording thumb32 instructions. This patch also > fixes bugs in arm process record instruction decoding. > > gdb: > > 2013-11-08 Omair Javaid <omair.javaid@linaro.org> > > * arm-tdep.c (struct arm_mem_r): Use uint32_t for memory address. > (arm_record_unsupported_insn): New function. > (arm_record_coproc_data_proc): Removed. > (thumb2_record_ld_st_multiple): New function. > (thumb2_record_ld_st_dual_ex_tbb): New function. > (thumb2_record_data_proc_sreg_mimm): New function. > (thumb2_record_ps_dest_generic): New function. > (thumb2_record_branch_misc_cntrl): New function. > (thumb2_record_str_single_data): New function. > (thumb2_record_ld_mem_hints): New function. > (thumb2_record_ld_word): New function. > (thumb2_record_lmul_lmla_div): New function. > (thumb2_record_decode_inst_id): New function. > (decode_insn): Add thumb32 instruction handlers. > > --- > gdb/arm-tdep.c | 627 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 619 insertions(+), 8 deletions(-) > > diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c > index 7c78a61..ecaced7 100644 > --- a/gdb/arm-tdep.c > +++ b/gdb/arm-tdep.c > @@ -10618,7 +10618,7 @@ vfp - VFP co-processor."), > struct arm_mem_r > { > uint32_t len; /* Record length. */ > - CORE_ADDR addr; /* Memory address. */ > + uint32_t addr; /* Memory address. */ > }; > > /* ARM instruction record contains opcode of current insn > @@ -11919,7 +11919,7 @@ arm_record_b_bl (insn_decode_record *arm_insn_r) > /* Handling opcode 110 insns. */ > > static int > -arm_record_coproc (insn_decode_record *arm_insn_r) > +arm_record_unsupported_insn (insn_decode_record *arm_insn_r) > { > printf_unfiltered (_("Process record does not support instruction " > "0x%0x at address %s.\n"),arm_insn_r->arm_insn, > @@ -12414,6 +12414,584 @@ thumb_record_branch (insn_decode_record *thumb_insn_r) > return 0; > } > > +/* Handler for thumb2 load/store multiple instructions. */ > + > +static int > +thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r) > +{ > + struct regcache *reg_cache = thumb2_insn_r->regcache; > + > + uint32_t reg_rn, op; > + uint32_t register_bits = 0, register_count = 0; > + uint32_t index = 0, start_address = 0; > + uint32_t record_buf[24], record_buf_mem[48]; > + > + ULONGEST u_regval = 0; > + > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + op = bits (thumb2_insn_r->arm_insn, 23, 24); > + > + if (0 == op || 3 == op) > + { > + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) > + { > + /* Handle RFE instruction. */ > + record_buf[0] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else > + { > + /* Handle SRS instruction after reading banked SP. */ > + return arm_record_unsupported_insn (thumb2_insn_r); > + } > + } > + else if(1 == op || 2 == op) > + { > + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) > + { > + /* Handle LDM/LDMIA/LDMFD and LDMDB/LDMEA instructions. */ > + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); > + while (register_bits) > + { > + if (register_bits & 0x00000001) > + record_buf[index++] = register_count; > + > + register_count++; > + register_bits = register_bits >> 1; > + } > + record_buf[index++] = reg_rn; > + record_buf[index++] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = index; > + } > + else > + { > + /* Handle STM/STMIA/STMEA and STMDB/STMFD. */ > + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); > + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); > + while (register_bits) > + { > + if (register_bits & 0x00000001) > + register_count++; > + > + register_bits = register_bits >> 1; > + } > + > + if (1 == op) > + { > + /* Start address calculation for LDMDB/LDMEA. */ > + start_address = u_regval; > + } > + else if (2 == op) > + { > + /* Start address calculation for LDMDB/LDMEA. */ > + start_address = (u_regval) - (register_count * 4); > + } > + > + thumb2_insn_r->mem_rec_count = register_count; > + while (register_count) > + { > + record_buf_mem[(register_count * 2) - 1] = start_address; > + record_buf_mem[(register_count * 2) - 2] = 4; > + start_address = start_address + 4; > + register_count--; > + } > + record_buf[0] = reg_rn; > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + } > + } > + > + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, > + record_buf_mem); > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Handler for thumb2 load/store (dual/exclusive) and table branch > + instructions. */ > + > +static int > +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r) > +{ > + struct regcache *reg_cache = thumb2_insn_r->regcache; > + > + uint32_t reg_rd, reg_rn, offset_imm; > + uint32_t reg_dest1, reg_dest2; > + uint32_t address, offset_addr; > + uint32_t record_buf[8], record_buf_mem[8]; > + uint32_t op1, op2, op3; > + LONGEST s_word; > + > + ULONGEST u_regval[2]; > + > + op1 = bits (thumb2_insn_r->arm_insn, 23, 24); > + op2 = bits (thumb2_insn_r->arm_insn, 20, 21); > + op3 = bits (thumb2_insn_r->arm_insn, 4, 7); > + > + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) > + { > + if(!(1 == op1 && 1 == op2 && (0 == op3 || 1 == op3))) > + { > + reg_dest1 = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[0] = reg_dest1; > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + } > + > + if (3 == op2 || (op1 & 2) || (1 == op1 && 1 == op2 && 7 == op3)) > + { > + reg_dest2 = bits (thumb2_insn_r->arm_insn, 8, 11); > + record_buf[2] = reg_dest2; > + thumb2_insn_r->reg_rec_count = 3; > + } > + } > + else > + { > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); > + > + if (0 == op1 && 0 == op2) > + { > + /* Handle STREX. */ > + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); > + address = u_regval[0] + (offset_imm * 4); > + record_buf_mem[0] = 4; > + record_buf_mem[1] = address; > + thumb2_insn_r->mem_rec_count = 1; > + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); > + record_buf[0] = reg_rd; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else if (1 == op1 && 0 == op2) > + { > + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); > + record_buf[0] = reg_rd; > + thumb2_insn_r->reg_rec_count = 1; > + address = u_regval[0]; > + record_buf_mem[1] = address; > + > + if (4 == op3) > + { > + /* Handle STREXB. */ > + record_buf_mem[0] = 1; > + thumb2_insn_r->mem_rec_count = 1; > + } > + else if (5 == op3) > + { > + /* Handle STREXH. */ > + record_buf_mem[0] = 2 ; > + thumb2_insn_r->mem_rec_count = 1; > + } > + else if (7 == op3) > + { > + /* Handle STREXD. */ > + address = u_regval[0]; > + record_buf_mem[0] = 4; > + record_buf_mem[2] = 4; > + record_buf_mem[3] = address + 4; > + thumb2_insn_r->mem_rec_count = 2; > + } > + } > + else > + { > + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); > + > + if (bit (thumb2_insn_r->arm_insn, 24)) > + { > + if (bit (thumb2_insn_r->arm_insn, 23)) > + offset_addr = u_regval[0] + (offset_imm * 4); > + else > + offset_addr = u_regval[0] - (offset_imm * 4); > + > + address = offset_addr; > + } > + else > + address = u_regval[0]; > + > + record_buf_mem[0] = 4; > + record_buf_mem[1] = address; > + record_buf_mem[2] = 4; > + record_buf_mem[3] = address + 4; > + thumb2_insn_r->mem_rec_count = 2; > + record_buf[0] = reg_rn; > + thumb2_insn_r->reg_rec_count = 1; > + } > + } > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, > + record_buf_mem); > + return 0; > +} > + > +/* Handler for thumb2 data processing (shift register and modified immediate) > + instructions. */ > + > +static int > +thumb2_record_data_proc_sreg_mimm (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t reg_rd, op; > + uint32_t record_buf[8]; > + > + op = bits (thumb2_insn_r->arm_insn, 21, 24); > + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); > + > + if ((0 == op || 4 == op || 8 == op || 13 == op) && 15 == reg_rd) > + { > + record_buf[0] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else > + { > + record_buf[0] = reg_rd; > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + } > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Generic handler for thumb2 instructions which effect destination and PS > + registers. */ > + > +static int > +thumb2_record_ps_dest_generic (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t reg_rd; > + uint32_t record_buf[8]; > + > + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); > + > + record_buf[0] = reg_rd; > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Handler for thumb2 branch and miscellaneous control instructions. */ > + > +static int > +thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t op, op1, op2; > + uint32_t record_buf[8]; > + > + op = bits (thumb2_insn_r->arm_insn, 20, 26); > + op1 = bits (thumb2_insn_r->arm_insn, 12, 14); > + op2 = bits (thumb2_insn_r->arm_insn, 8, 11); > + > + /* Handle MSR insn. */ > + if (!(op1 & 0x2) && 0x38 == op) > + { > + if (!(op2 & 0x3)) > + { > + /* CPSR is going to be changed. */ > + record_buf[0] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else > + { > + arm_record_unsupported_insn(thumb2_insn_r); > + return -1; > + } > + } > + else if (4 == (op1 & 0x5) || 5 == (op1 & 0x5)) > + { > + /* BLX. */ > + record_buf[0] = ARM_PS_REGNUM; > + record_buf[1] = ARM_LR_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + } > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Handler for thumb2 store single data item instructions. */ > + > +static int > +thumb2_record_str_single_data (insn_decode_record *thumb2_insn_r) > +{ > + struct regcache *reg_cache = thumb2_insn_r->regcache; > + > + uint32_t reg_rn, reg_rm, offset_imm, shift_imm; > + uint32_t address, offset_addr; > + uint32_t record_buf[8], record_buf_mem[8]; > + uint32_t op1, op2; > + > + ULONGEST u_regval[2]; > + > + op1 = bits (thumb2_insn_r->arm_insn, 21, 23); > + op2 = bits (thumb2_insn_r->arm_insn, 6, 11); > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); > + > + if (bit (thumb2_insn_r->arm_insn, 23)) > + { > + /* T2 encoding. */ > + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 11); > + offset_addr = u_regval[0] + offset_imm; > + address = offset_addr; > + } > + else > + { > + /* T3 encoding. */ > + if ((0 == op1 || 1 == op1 || 2 == op1) && !(op2 & 0x20)) > + { > + /* Handle STRB (register). */ > + reg_rm = bits (thumb2_insn_r->arm_insn, 0, 3); > + regcache_raw_read_unsigned (reg_cache, reg_rm, &u_regval[1]); > + shift_imm = bits (thumb2_insn_r->arm_insn, 4, 5); > + offset_addr = u_regval[1] << shift_imm; > + address = u_regval[0] + offset_addr; > + } > + else > + { > + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); > + if (bit (thumb2_insn_r->arm_insn, 10)) > + { > + if (bit (thumb2_insn_r->arm_insn, 9)) > + offset_addr = u_regval[0] + offset_imm; > + else > + offset_addr = u_regval[0] - offset_imm; > + > + address = offset_addr; > + } > + else > + address = u_regval[0]; > + } > + } > + > + switch (op1) > + { > + /* Store byte instructions. */ > + case 4: > + case 0: > + record_buf_mem[0] = 1; > + break; > + /* Store half word instructions. */ > + case 1: > + case 5: > + record_buf_mem[0] = 2; > + break; > + /* Store word instructions. */ > + case 2: > + case 6: > + record_buf_mem[0] = 4; > + break; > + > + default: > + gdb_assert_not_reached ("no decoding pattern found"); > + break; > + } > + > + record_buf_mem[1] = address; > + thumb2_insn_r->mem_rec_count = 1; > + record_buf[0] = reg_rn; > + thumb2_insn_r->reg_rec_count = 1; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, > + record_buf_mem); > + return 0; > +} > + > +/* Handler for thumb2 load memory hints instructions. */ > + > +static int > +thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t record_buf[8]; > + uint32_t reg_rt, reg_rn; > + > + reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15); > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + > + if (ARM_PC_REGNUM != reg_rt) > + { > + record_buf[0] = reg_rt; > + record_buf[1] = reg_rn; > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > + } > + > + return -1; > +} > + > +/* Handler for thumb2 load word instructions. */ > + > +static int > +thumb2_record_ld_word (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t opcode1 = 0, opcode2 = 0; > + uint32_t record_buf[8]; > + > + record_buf[0] = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Handler for thumb2 long multiply, long multiply accumulate, and > + divide instructions. Return value: -1:record failure ; 0:success. */ > + > +static int > +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t ret = 0; > + uint32_t opcode1 = 0, opcode2 = 0; > + uint32_t record_buf[8]; > + uint32_t reg_src1 = 0; > + > + opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22); > + opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7); > + > + if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6)) > + { > + /* Handle SMULL, UMULL, SMULAL. */ > + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */ > + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); > + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + } > + else if (1 == opcode1 || 3 == opcode2) > + { > + /* Handle SDIV and UDIV. */ > + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); > + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + } > + else > + ret = -1; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return ret; > +} > + > +/* Decodes thumb2 instruction type and return an instruction id. */ > + > +static unsigned int > +thumb2_record_decode_inst_id (uint32_t thumb2_insn) > +{ > + uint32_t op = 0; > + uint32_t op1 = 0; > + uint32_t op2 = 0; > + > + op = bit (thumb2_insn, 15); > + op1 = bits (thumb2_insn, 27, 28); > + op2 = bits (thumb2_insn, 20, 26); > + > + if (op1 == 0x01) > + { > + if (!(op2 & 0x64 )) > + { > + /* Load/store multiple instruction. */ > + return 0; > + } > + else if (!((op2 & 0x64) ^ 0x04)) > + { > + /* Load/store (dual/exclusive) and table branch instruction. */ > + return 1; > + } > + else if (!((op2 & 0x20) ^ 0x20)) > + { > + /* Data-processing (shifted register). */ > + return 2; > + } > + else if (op2 & 0x40) > + { > + /* Co-processor instructions. */ > + return 3; > + } > + } > + else if (op1 == 0x02) > + { > + if (op) > + { > + /* Branches and miscellaneous control instructions. */ > + return 6; > + } > + else if (op2 & 0x20) > + { > + /* Data-processing (plain binary immediate) instruction. */ > + return 5; > + } > + else > + { > + /* Data-processing (modified immediate). */ > + return 4; > + } > + } > + else if (op1 == 0x03) > + { > + if (!(op2 & 0x71 )) > + { > + /* Store single data item. */ > + return 7; > + } > + else if (!((op2 & 0x71) ^ 0x10)) > + { > + /* Advanced SIMD or structure load/store instructions. */ > + return 8; > + } > + else if (!((op2 & 0x67) ^ 0x01)) > + { > + /* Load byte, memory hints instruction. */ > + return 9; > + } > + else if (!((op2 & 0x67) ^ 0x03)) > + { > + /* Load halfword, memory hints instruction. */ > + return 10; > + } > + else if (!((op2 & 0x67) ^ 0x05)) > + { > + /* Load word instruction. */ > + return 11; > + } > + else if (!((op2 & 0x70) ^ 0x20)) > + { > + /* Data-processing (register) instruction. */ > + return 12; > + } > + else if (!((op2 & 0x78) ^ 0x30)) > + { > + /* Multiply, multiply accumulate, abs diff instruction. */ > + return 13; > + } > + else if (!((op2 & 0x78) ^ 0x38)) > + { > + /* Long multiply, long multiply accumulate, and divide. */ > + return 14; > + } > + else if (op2 & 0x40) > + { > + /* Co-processor instructions. */ > + return 15; > + } > + } > + > + return -1; > +} > > /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success > and positive val on fauilure. */ > @@ -12452,7 +13030,7 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, > arm_record_ld_st_reg_offset, /* 011. */ > arm_record_ld_st_multiple, /* 100. */ > arm_record_b_bl, /* 101. */ > - arm_record_coproc, /* 110. */ > + arm_record_unsupported_insn, /* 110. */ > arm_record_coproc_data_proc /* 111. */ > }; > > @@ -12469,6 +13047,28 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, > thumb_record_branch /* 111. */ > }; > > + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb > + instruction. */ > + static const sti_arm_hdl_fp_t const thumb2_handle_insn[16] = > + { \ > + thumb2_record_ld_st_multiple, /* 00. */ > + thumb2_record_ld_st_dual_ex_tbb, /* 01. */ > + thumb2_record_data_proc_sreg_mimm, /* 02. */ > + arm_record_unsupported_insn, /* 03. */ > + thumb2_record_data_proc_sreg_mimm, /* 04. */ > + thumb2_record_ps_dest_generic, /* 05. */ > + thumb2_record_branch_misc_cntrl, /* 06. */ > + thumb2_record_str_single_data, /* 07. */ > + arm_record_unsupported_insn, /* 08. */ > + thumb2_record_ld_mem_hints, /* 09. */ > + thumb2_record_ld_mem_hints, /* 10. */ > + thumb2_record_ld_word, /* 11. */ > + thumb2_record_ps_dest_generic, /* 12. */ > + thumb2_record_ps_dest_generic, /* 13. */ > + thumb2_record_lmul_lmla_div, /* 14. */ > + arm_record_unsupported_insn /* 15. */ > + }; > + > uint32_t ret = 0; /* return value: negative:failure 0:success. */ > uint32_t insn_id = 0; > > @@ -12503,11 +13103,22 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, > } > else if (THUMB2_RECORD == record_type) > { > - printf_unfiltered (_("Process record doesnt support thumb32 instruction " > - "0x%0x at address %s.\n"),arm_record->arm_insn, > - paddress (arm_record->gdbarch, > - arm_record->this_addr)); > - ret = -1; > + /* As thumb does not have condition codes, we set negative. */ > + arm_record->cond = -1; > + > + /* Swap first half of 32bit thumb instruction with second half. */ > + arm_record->arm_insn = (arm_record->arm_insn >> 16) | > + (arm_record->arm_insn << 16); > + > + insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn); > + > + if (insn_id >= 0) > + ret = thumb2_handle_insn[insn_id] (arm_record); > + else > + { > + arm_record_unsupported_insn(arm_record); > + ret = -1; > + } > } > else > { > --
On 11/25/2013 06:07 PM, Oza Pawandeep wrote: > Hi Omar, > > couple of comments. > > 1) you this part of code is still using MAGIC numbers. > + if (!(op2 & 0x71 )) > + { > + /* Store single data item. */ > + return 7; > + } > + else if (!((op2 & 0x71) ^ 0x10)) > + { > + /* Advanced SIMD or structure load/store instructions. */ > + return 8; > + } > + else if (!((op2 & 0x67) ^ 0x01)) > + { > + /* Load byte, memory hints instruction. */ > + return 9; > + } > + else if (!((op2 & 0x67) ^ 0x03)) > + { > + /* Load halfword, memory hints instruction. */ > + return 10; > + } > + else if (!((op2 & 0x67) ^ 0x05)) > + { > + /* Load word instruction. */ > + return 11; > + } > In principle I agree that code must be more readable overall but that is applicable to all the code residing in arm-tdep.c. The nomenclature and bit manipulations in above code is used in line with ARM reference manual and can be understood if we have Thumb32 instruction encoding page infront. > > 2) following code else part is not required. > > /* Handle MSR insn. */ > + if (!(op1 & 0x2) && 0x38 == op) > + { > + if (!(op2 & 0x3)) > + { > + /* CPSR is going to be changed. */ > + record_buf[0] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else > + { > + arm_record_unsupported_insn( > thumb2_insn_r); > + return -1; > + } > > because of folowing. > // SPSRWriteByInstr() > // ================== > SPSRWriteByInstr(bits(32) value, bits(4) bytemask) > if CurrentModeIsUserOrSystem() then UNPREDICTABLE; > > gdb is for user space; and use space is not allowed to use SPSR > directly using MSR instruction. > so old code base + new code base whereever we have got SPSR getting > modified we need to remove the same. > I agree with you that we have to do a lot of rework of previous process record code. But I am not sure it would be productive for us to get working code out and loose the functionality or delay its submission. As Record/Replay is pretty much functional with this set of patches I am hoping that we can do a complete rework if required later on. > 3) did you run the testsuite at whole code-base ? I have tested with a a fresh git checkout alongwith 4 patches I have sent. In native mode on a samsung chromebook there are only 69 failures left out of around 2500 test cases. I am working on more bug fixes and hopefully will be able to resolve rest of issues as well. > > > ps: I am still struggling to get my public key setup at gdb git. will > try to get it done as soonas I can. > > Regards, > Oza. > > > > On Mon, Nov 25, 2013 at 5:19 AM, Omair Javaid <omair.javaid@linaro.org> wrote: >> On 11/11/2013 03:09 PM, Yao Qi wrote: >>> Patch looks good to me, and you still need a maintainer's approval. >>> >>> Some of the comments are too long. Please make sure they don't exceed >>> the limitation (around 74 characters should be fine). >>> >>> On 11/08/2013 11:19 AM, Omair Javaid wrote: >>>> +/* Handler for thumb2 ld/st dual, ld/st exclusive, table branch >>>> instructions. */ >>>> + >>> >>> here. >>> >>>> +static int >>>> +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r) >>>> +{ >>>> + struct regcache *reg_cache = thumb2_insn_r->regcache; >>>> + >>> >>> .... >>> >>>> + >>>> +/* Decodes thumb2 instruction type and return an instruction id. */ >>>> + >>>> +static unsigned int >>>> +thumb2_record_decode_inst_id (uint32_t thumb2_insn) >>>> +{ >>>> + uint32_t op = 0; >>>> + uint32_t op1 = 0; >>>> + uint32_t op2 = 0; >>>> + >>>> + op = bit (thumb2_insn, 15); >>>> + op1 = bits (thumb2_insn, 27, 28); >>>> + op2 = bits (thumb2_insn, 20, 26); >>>> + >>>> + if (op1 == 0x01) >>>> + { >>>> + if (!(op2 & 0x64 )) >>>> + { >>>> + /* Load/store multiple instruction. */ >>>> + return 0; >>>> + } >>>> + else if (!((op2 & 0x64) ^ 0x04)) >>>> + { >>>> + /* Load/store dual, load/store exclusive, table branch >>>> instruction. */ >>> >>> and here. >>> >>> >>>> + return 1; >>>> + } >>>> + else if (!((op2 & 0x20) ^ 0x20)) >>>> + { >>>> + /* Data-processing (shifted register). */ >>>> + return 2; >>>> + } >>>> + else if (op2 & 0x40) >>>> + { >>>> + /* Co-processor instructions. */ >>>> + return 3; >>>> + } >>>> + } >>>> + else if (op1 == 0x02) >>>> + { >>>> + if (op) >>>> + { >>>> + /* Branches and miscellaneous control instructions. */ >>>> + return 6; >>>> + } >>>> + else if (op2 & 0x20) >>>> + { >>>> + /* Data-processing (plain binary immediate) instruction. */ >>>> + return 5; >>>> + } >>>> + else >>>> + { >>>> + /* Data-processing (modified immediate). */ >>>> + return 4; >>>> + } >>>> + } >>>> + else if (op1 == 0x03) >>>> + { >>>> + if (!(op2 & 0x71 )) >>>> + { >>>> + /* Store single data item. */ >>>> + return 7; >>>> + } >>>> + else if (!((op2 & 0x71) ^ 0x10)) >>>> + { >>>> + /* Advanced SIMD element or structure load/store >>>> instructions. */ >>> >>> here. >>> >>>> + return 8; >>>> + } >>>> + else if (!((op2 & 0x67) ^ 0x01)) >>>> + { >>>> + /* Load byte, memory hints instruction. */ >>>> + return 9; >>>> + } >>>> + else if (!((op2 & 0x67) ^ 0x03)) >>>> + { >>>> + /* Load halfword, memory hints instruction. */ >>>> + return 10; >>>> + } >>>> + else if (!((op2 & 0x67) ^ 0x05)) >>>> + { >>>> + /* Load word instruction. */ >>>> + return 11; >>>> + } >>>> + else if (!((op2 & 0x70) ^ 0x20)) >>>> + { >>>> + /* Data-processing (register) instruction. */ >>>> + return 12; >>>> + } >>>> + else if (!((op2 & 0x78) ^ 0x30)) >>>> + { >>>> + /* Multiply, multiply accumulate, absolute difference >>>> instruction. */ >>> >>> here. >>> >>>> + return 13; >>>> + } >>>> + else if (!((op2 & 0x78) ^ 0x38)) >>>> + { >>>> + /* Long multiply, long multiply accumulate, and divide. */ >>>> + return 14; >>>> + } >>>> + else if (op2 & 0x40) >>>> + { >>>> + /* Co-processor instructions. */ >>>> + return 15; >>>> + } >>>> + } >>>> + >>>> + return -1; >>>> +} >>>> >>>> /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 >>>> on success >>>> and positive val on fauilure. */ >>>> @@ -12452,7 +13034,7 @@ decode_insn (insn_decode_record *arm_rec >>>> arm_record_ld_st_reg_offset, /* 011. */ >>>> arm_record_ld_st_multiple, /* 100. */ >>>> arm_record_b_bl, /* 101. */ >>>> - arm_record_coproc, /* 110. */ >>>> + arm_record_unsupported_insn, /* 110. */ >>>> arm_record_coproc_data_proc /* 111. */ >>>> }; >>>> >>>> @@ -12469,6 +13051,27 @@ decode_insn (insn_decode_record *arm_rec >>>> thumb_record_branch /* 111. */ >>>> }; >>>> >>>> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb >>>> instruction. */ >>> >>> here. >>> >> >> Patch has been updated after incorporating suggestions. Looking for a final >> commit verdict. >> >> This patch adds support for recording thumb32 instructions. This patch also >> fixes bugs in arm process record instruction decoding. >> >> gdb: >> >> 2013-11-08 Omair Javaid <omair.javaid@linaro.org> >> >> * arm-tdep.c (struct arm_mem_r): Use uint32_t for memory address. >> (arm_record_unsupported_insn): New function. >> (arm_record_coproc_data_proc): Removed. >> (thumb2_record_ld_st_multiple): New function. >> (thumb2_record_ld_st_dual_ex_tbb): New function. >> (thumb2_record_data_proc_sreg_mimm): New function. >> (thumb2_record_ps_dest_generic): New function. >> (thumb2_record_branch_misc_cntrl): New function. >> (thumb2_record_str_single_data): New function. >> (thumb2_record_ld_mem_hints): New function. >> (thumb2_record_ld_word): New function. >> (thumb2_record_lmul_lmla_div): New function. >> (thumb2_record_decode_inst_id): New function. >> (decode_insn): Add thumb32 instruction handlers. >> >> --- >> gdb/arm-tdep.c | 627 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 619 insertions(+), 8 deletions(-) >> >> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c >> index 7c78a61..ecaced7 100644 >> --- a/gdb/arm-tdep.c >> +++ b/gdb/arm-tdep.c >> @@ -10618,7 +10618,7 @@ vfp - VFP co-processor."), >> struct arm_mem_r >> { >> uint32_t len; /* Record length. */ >> - CORE_ADDR addr; /* Memory address. */ >> + uint32_t addr; /* Memory address. */ >> }; >> >> /* ARM instruction record contains opcode of current insn >> @@ -11919,7 +11919,7 @@ arm_record_b_bl (insn_decode_record *arm_insn_r) >> /* Handling opcode 110 insns. */ >> >> static int >> -arm_record_coproc (insn_decode_record *arm_insn_r) >> +arm_record_unsupported_insn (insn_decode_record *arm_insn_r) >> { >> printf_unfiltered (_("Process record does not support instruction " >> "0x%0x at address %s.\n"),arm_insn_r->arm_insn, >> @@ -12414,6 +12414,584 @@ thumb_record_branch (insn_decode_record *thumb_insn_r) >> return 0; >> } >> >> +/* Handler for thumb2 load/store multiple instructions. */ >> + >> +static int >> +thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r) >> +{ >> + struct regcache *reg_cache = thumb2_insn_r->regcache; >> + >> + uint32_t reg_rn, op; >> + uint32_t register_bits = 0, register_count = 0; >> + uint32_t index = 0, start_address = 0; >> + uint32_t record_buf[24], record_buf_mem[48]; >> + >> + ULONGEST u_regval = 0; >> + >> + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); >> + op = bits (thumb2_insn_r->arm_insn, 23, 24); >> + >> + if (0 == op || 3 == op) >> + { >> + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) >> + { >> + /* Handle RFE instruction. */ >> + record_buf[0] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 1; >> + } >> + else >> + { >> + /* Handle SRS instruction after reading banked SP. */ >> + return arm_record_unsupported_insn (thumb2_insn_r); >> + } >> + } >> + else if(1 == op || 2 == op) >> + { >> + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) >> + { >> + /* Handle LDM/LDMIA/LDMFD and LDMDB/LDMEA instructions. */ >> + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); >> + while (register_bits) >> + { >> + if (register_bits & 0x00000001) >> + record_buf[index++] = register_count; >> + >> + register_count++; >> + register_bits = register_bits >> 1; >> + } >> + record_buf[index++] = reg_rn; >> + record_buf[index++] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = index; >> + } >> + else >> + { >> + /* Handle STM/STMIA/STMEA and STMDB/STMFD. */ >> + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); >> + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); >> + while (register_bits) >> + { >> + if (register_bits & 0x00000001) >> + register_count++; >> + >> + register_bits = register_bits >> 1; >> + } >> + >> + if (1 == op) >> + { >> + /* Start address calculation for LDMDB/LDMEA. */ >> + start_address = u_regval; >> + } >> + else if (2 == op) >> + { >> + /* Start address calculation for LDMDB/LDMEA. */ >> + start_address = (u_regval) - (register_count * 4); >> + } >> + >> + thumb2_insn_r->mem_rec_count = register_count; >> + while (register_count) >> + { >> + record_buf_mem[(register_count * 2) - 1] = start_address; >> + record_buf_mem[(register_count * 2) - 2] = 4; >> + start_address = start_address + 4; >> + register_count--; >> + } >> + record_buf[0] = reg_rn; >> + record_buf[1] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + } >> + } >> + >> + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, >> + record_buf_mem); >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> +} >> + >> +/* Handler for thumb2 load/store (dual/exclusive) and table branch >> + instructions. */ >> + >> +static int >> +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r) >> +{ >> + struct regcache *reg_cache = thumb2_insn_r->regcache; >> + >> + uint32_t reg_rd, reg_rn, offset_imm; >> + uint32_t reg_dest1, reg_dest2; >> + uint32_t address, offset_addr; >> + uint32_t record_buf[8], record_buf_mem[8]; >> + uint32_t op1, op2, op3; >> + LONGEST s_word; >> + >> + ULONGEST u_regval[2]; >> + >> + op1 = bits (thumb2_insn_r->arm_insn, 23, 24); >> + op2 = bits (thumb2_insn_r->arm_insn, 20, 21); >> + op3 = bits (thumb2_insn_r->arm_insn, 4, 7); >> + >> + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) >> + { >> + if(!(1 == op1 && 1 == op2 && (0 == op3 || 1 == op3))) >> + { >> + reg_dest1 = bits (thumb2_insn_r->arm_insn, 12, 15); >> + record_buf[0] = reg_dest1; >> + record_buf[1] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + } >> + >> + if (3 == op2 || (op1 & 2) || (1 == op1 && 1 == op2 && 7 == op3)) >> + { >> + reg_dest2 = bits (thumb2_insn_r->arm_insn, 8, 11); >> + record_buf[2] = reg_dest2; >> + thumb2_insn_r->reg_rec_count = 3; >> + } >> + } >> + else >> + { >> + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); >> + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); >> + >> + if (0 == op1 && 0 == op2) >> + { >> + /* Handle STREX. */ >> + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); >> + address = u_regval[0] + (offset_imm * 4); >> + record_buf_mem[0] = 4; >> + record_buf_mem[1] = address; >> + thumb2_insn_r->mem_rec_count = 1; >> + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); >> + record_buf[0] = reg_rd; >> + thumb2_insn_r->reg_rec_count = 1; >> + } >> + else if (1 == op1 && 0 == op2) >> + { >> + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); >> + record_buf[0] = reg_rd; >> + thumb2_insn_r->reg_rec_count = 1; >> + address = u_regval[0]; >> + record_buf_mem[1] = address; >> + >> + if (4 == op3) >> + { >> + /* Handle STREXB. */ >> + record_buf_mem[0] = 1; >> + thumb2_insn_r->mem_rec_count = 1; >> + } >> + else if (5 == op3) >> + { >> + /* Handle STREXH. */ >> + record_buf_mem[0] = 2 ; >> + thumb2_insn_r->mem_rec_count = 1; >> + } >> + else if (7 == op3) >> + { >> + /* Handle STREXD. */ >> + address = u_regval[0]; >> + record_buf_mem[0] = 4; >> + record_buf_mem[2] = 4; >> + record_buf_mem[3] = address + 4; >> + thumb2_insn_r->mem_rec_count = 2; >> + } >> + } >> + else >> + { >> + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); >> + >> + if (bit (thumb2_insn_r->arm_insn, 24)) >> + { >> + if (bit (thumb2_insn_r->arm_insn, 23)) >> + offset_addr = u_regval[0] + (offset_imm * 4); >> + else >> + offset_addr = u_regval[0] - (offset_imm * 4); >> + >> + address = offset_addr; >> + } >> + else >> + address = u_regval[0]; >> + >> + record_buf_mem[0] = 4; >> + record_buf_mem[1] = address; >> + record_buf_mem[2] = 4; >> + record_buf_mem[3] = address + 4; >> + thumb2_insn_r->mem_rec_count = 2; >> + record_buf[0] = reg_rn; >> + thumb2_insn_r->reg_rec_count = 1; >> + } >> + } >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, >> + record_buf_mem); >> + return 0; >> +} >> + >> +/* Handler for thumb2 data processing (shift register and modified immediate) >> + instructions. */ >> + >> +static int >> +thumb2_record_data_proc_sreg_mimm (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t reg_rd, op; >> + uint32_t record_buf[8]; >> + >> + op = bits (thumb2_insn_r->arm_insn, 21, 24); >> + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); >> + >> + if ((0 == op || 4 == op || 8 == op || 13 == op) && 15 == reg_rd) >> + { >> + record_buf[0] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 1; >> + } >> + else >> + { >> + record_buf[0] = reg_rd; >> + record_buf[1] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + } >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> +} >> + >> +/* Generic handler for thumb2 instructions which effect destination and PS >> + registers. */ >> + >> +static int >> +thumb2_record_ps_dest_generic (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t reg_rd; >> + uint32_t record_buf[8]; >> + >> + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); >> + >> + record_buf[0] = reg_rd; >> + record_buf[1] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> +} >> + >> +/* Handler for thumb2 branch and miscellaneous control instructions. */ >> + >> +static int >> +thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t op, op1, op2; >> + uint32_t record_buf[8]; >> + >> + op = bits (thumb2_insn_r->arm_insn, 20, 26); >> + op1 = bits (thumb2_insn_r->arm_insn, 12, 14); >> + op2 = bits (thumb2_insn_r->arm_insn, 8, 11); >> + >> + /* Handle MSR insn. */ >> + if (!(op1 & 0x2) && 0x38 == op) >> + { >> + if (!(op2 & 0x3)) >> + { >> + /* CPSR is going to be changed. */ >> + record_buf[0] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 1; >> + } >> + else >> + { >> + arm_record_unsupported_insn(thumb2_insn_r); >> + return -1; >> + } >> + } >> + else if (4 == (op1 & 0x5) || 5 == (op1 & 0x5)) >> + { >> + /* BLX. */ >> + record_buf[0] = ARM_PS_REGNUM; >> + record_buf[1] = ARM_LR_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + } >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> +} >> + >> +/* Handler for thumb2 store single data item instructions. */ >> + >> +static int >> +thumb2_record_str_single_data (insn_decode_record *thumb2_insn_r) >> +{ >> + struct regcache *reg_cache = thumb2_insn_r->regcache; >> + >> + uint32_t reg_rn, reg_rm, offset_imm, shift_imm; >> + uint32_t address, offset_addr; >> + uint32_t record_buf[8], record_buf_mem[8]; >> + uint32_t op1, op2; >> + >> + ULONGEST u_regval[2]; >> + >> + op1 = bits (thumb2_insn_r->arm_insn, 21, 23); >> + op2 = bits (thumb2_insn_r->arm_insn, 6, 11); >> + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); >> + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); >> + >> + if (bit (thumb2_insn_r->arm_insn, 23)) >> + { >> + /* T2 encoding. */ >> + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 11); >> + offset_addr = u_regval[0] + offset_imm; >> + address = offset_addr; >> + } >> + else >> + { >> + /* T3 encoding. */ >> + if ((0 == op1 || 1 == op1 || 2 == op1) && !(op2 & 0x20)) >> + { >> + /* Handle STRB (register). */ >> + reg_rm = bits (thumb2_insn_r->arm_insn, 0, 3); >> + regcache_raw_read_unsigned (reg_cache, reg_rm, &u_regval[1]); >> + shift_imm = bits (thumb2_insn_r->arm_insn, 4, 5); >> + offset_addr = u_regval[1] << shift_imm; >> + address = u_regval[0] + offset_addr; >> + } >> + else >> + { >> + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); >> + if (bit (thumb2_insn_r->arm_insn, 10)) >> + { >> + if (bit (thumb2_insn_r->arm_insn, 9)) >> + offset_addr = u_regval[0] + offset_imm; >> + else >> + offset_addr = u_regval[0] - offset_imm; >> + >> + address = offset_addr; >> + } >> + else >> + address = u_regval[0]; >> + } >> + } >> + >> + switch (op1) >> + { >> + /* Store byte instructions. */ >> + case 4: >> + case 0: >> + record_buf_mem[0] = 1; >> + break; >> + /* Store half word instructions. */ >> + case 1: >> + case 5: >> + record_buf_mem[0] = 2; >> + break; >> + /* Store word instructions. */ >> + case 2: >> + case 6: >> + record_buf_mem[0] = 4; >> + break; >> + >> + default: >> + gdb_assert_not_reached ("no decoding pattern found"); >> + break; >> + } >> + >> + record_buf_mem[1] = address; >> + thumb2_insn_r->mem_rec_count = 1; >> + record_buf[0] = reg_rn; >> + thumb2_insn_r->reg_rec_count = 1; >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, >> + record_buf_mem); >> + return 0; >> +} >> + >> +/* Handler for thumb2 load memory hints instructions. */ >> + >> +static int >> +thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t record_buf[8]; >> + uint32_t reg_rt, reg_rn; >> + >> + reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15); >> + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); >> + >> + if (ARM_PC_REGNUM != reg_rt) >> + { >> + record_buf[0] = reg_rt; >> + record_buf[1] = reg_rn; >> + record_buf[2] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 3; >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> + } >> + >> + return -1; >> +} >> + >> +/* Handler for thumb2 load word instructions. */ >> + >> +static int >> +thumb2_record_ld_word (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t opcode1 = 0, opcode2 = 0; >> + uint32_t record_buf[8]; >> + >> + record_buf[0] = bits (thumb2_insn_r->arm_insn, 12, 15); >> + record_buf[1] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 2; >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return 0; >> +} >> + >> +/* Handler for thumb2 long multiply, long multiply accumulate, and >> + divide instructions. Return value: -1:record failure ; 0:success. */ >> + >> +static int >> +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r) >> +{ >> + uint32_t ret = 0; >> + uint32_t opcode1 = 0, opcode2 = 0; >> + uint32_t record_buf[8]; >> + uint32_t reg_src1 = 0; >> + >> + opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22); >> + opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7); >> + >> + if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6)) >> + { >> + /* Handle SMULL, UMULL, SMULAL. */ >> + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */ >> + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); >> + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); >> + record_buf[2] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 3; >> + } >> + else if (1 == opcode1 || 3 == opcode2) >> + { >> + /* Handle SDIV and UDIV. */ >> + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); >> + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); >> + record_buf[2] = ARM_PS_REGNUM; >> + thumb2_insn_r->reg_rec_count = 3; >> + } >> + else >> + ret = -1; >> + >> + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, >> + record_buf); >> + return ret; >> +} >> + >> +/* Decodes thumb2 instruction type and return an instruction id. */ >> + >> +static unsigned int >> +thumb2_record_decode_inst_id (uint32_t thumb2_insn) >> +{ >> + uint32_t op = 0; >> + uint32_t op1 = 0; >> + uint32_t op2 = 0; >> + >> + op = bit (thumb2_insn, 15); >> + op1 = bits (thumb2_insn, 27, 28); >> + op2 = bits (thumb2_insn, 20, 26); >> + >> + if (op1 == 0x01) >> + { >> + if (!(op2 & 0x64 )) >> + { >> + /* Load/store multiple instruction. */ >> + return 0; >> + } >> + else if (!((op2 & 0x64) ^ 0x04)) >> + { >> + /* Load/store (dual/exclusive) and table branch instruction. */ >> + return 1; >> + } >> + else if (!((op2 & 0x20) ^ 0x20)) >> + { >> + /* Data-processing (shifted register). */ >> + return 2; >> + } >> + else if (op2 & 0x40) >> + { >> + /* Co-processor instructions. */ >> + return 3; >> + } >> + } >> + else if (op1 == 0x02) >> + { >> + if (op) >> + { >> + /* Branches and miscellaneous control instructions. */ >> + return 6; >> + } >> + else if (op2 & 0x20) >> + { >> + /* Data-processing (plain binary immediate) instruction. */ >> + return 5; >> + } >> + else >> + { >> + /* Data-processing (modified immediate). */ >> + return 4; >> + } >> + } >> + else if (op1 == 0x03) >> + { >> + if (!(op2 & 0x71 )) >> + { >> + /* Store single data item. */ >> + return 7; >> + } >> + else if (!((op2 & 0x71) ^ 0x10)) >> + { >> + /* Advanced SIMD or structure load/store instructions. */ >> + return 8; >> + } >> + else if (!((op2 & 0x67) ^ 0x01)) >> + { >> + /* Load byte, memory hints instruction. */ >> + return 9; >> + } >> + else if (!((op2 & 0x67) ^ 0x03)) >> + { >> + /* Load halfword, memory hints instruction. */ >> + return 10; >> + } >> + else if (!((op2 & 0x67) ^ 0x05)) >> + { >> + /* Load word instruction. */ >> + return 11; >> + } >> + else if (!((op2 & 0x70) ^ 0x20)) >> + { >> + /* Data-processing (register) instruction. */ >> + return 12; >> + } >> + else if (!((op2 & 0x78) ^ 0x30)) >> + { >> + /* Multiply, multiply accumulate, abs diff instruction. */ >> + return 13; >> + } >> + else if (!((op2 & 0x78) ^ 0x38)) >> + { >> + /* Long multiply, long multiply accumulate, and divide. */ >> + return 14; >> + } >> + else if (op2 & 0x40) >> + { >> + /* Co-processor instructions. */ >> + return 15; >> + } >> + } >> + >> + return -1; >> +} >> >> /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success >> and positive val on fauilure. */ >> @@ -12452,7 +13030,7 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, >> arm_record_ld_st_reg_offset, /* 011. */ >> arm_record_ld_st_multiple, /* 100. */ >> arm_record_b_bl, /* 101. */ >> - arm_record_coproc, /* 110. */ >> + arm_record_unsupported_insn, /* 110. */ >> arm_record_coproc_data_proc /* 111. */ >> }; >> >> @@ -12469,6 +13047,28 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, >> thumb_record_branch /* 111. */ >> }; >> >> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb >> + instruction. */ >> + static const sti_arm_hdl_fp_t const thumb2_handle_insn[16] = >> + { \ >> + thumb2_record_ld_st_multiple, /* 00. */ >> + thumb2_record_ld_st_dual_ex_tbb, /* 01. */ >> + thumb2_record_data_proc_sreg_mimm, /* 02. */ >> + arm_record_unsupported_insn, /* 03. */ >> + thumb2_record_data_proc_sreg_mimm, /* 04. */ >> + thumb2_record_ps_dest_generic, /* 05. */ >> + thumb2_record_branch_misc_cntrl, /* 06. */ >> + thumb2_record_str_single_data, /* 07. */ >> + arm_record_unsupported_insn, /* 08. */ >> + thumb2_record_ld_mem_hints, /* 09. */ >> + thumb2_record_ld_mem_hints, /* 10. */ >> + thumb2_record_ld_word, /* 11. */ >> + thumb2_record_ps_dest_generic, /* 12. */ >> + thumb2_record_ps_dest_generic, /* 13. */ >> + thumb2_record_lmul_lmla_div, /* 14. */ >> + arm_record_unsupported_insn /* 15. */ >> + }; >> + >> uint32_t ret = 0; /* return value: negative:failure 0:success. */ >> uint32_t insn_id = 0; >> >> @@ -12503,11 +13103,22 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, >> } >> else if (THUMB2_RECORD == record_type) >> { >> - printf_unfiltered (_("Process record doesnt support thumb32 instruction " >> - "0x%0x at address %s.\n"),arm_record->arm_insn, >> - paddress (arm_record->gdbarch, >> - arm_record->this_addr)); >> - ret = -1; >> + /* As thumb does not have condition codes, we set negative. */ >> + arm_record->cond = -1; >> + >> + /* Swap first half of 32bit thumb instruction with second half. */ >> + arm_record->arm_insn = (arm_record->arm_insn >> 16) | >> + (arm_record->arm_insn << 16); >> + >> + insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn); >> + >> + if (insn_id >= 0) >> + ret = thumb2_handle_insn[insn_id] (arm_record); >> + else >> + { >> + arm_record_unsupported_insn(arm_record); >> + ret = -1; >> + } >> } >> else >> { >> -- >
On 11/28/2013 06:04 AM, Omair Javaid wrote: >> gdb is for user space; and use space is not allowed to use SPSR >> >directly using MSR instruction. >> >so old code base + new code base whereever we have got SPSR getting >> >modified we need to remove the same. >> > > I agree with you that we have to do a lot of rework of previous process record code. But I am not sure it would be productive for us to get working code out and loose the functionality or delay its submission. As Record/Replay is pretty much functional with this set of patches I am hoping that we can do a complete rework if required later on. > If there is something broken related to the submissions, the common practise could be one of them below: 1. Fix them first, 2. Document the existing limitations/problems or write a test case to kfail it. In this way, people are aware of this. 3. Continue the submission and revisit the problems later. Personally, I choose one of them, depending on the complexity of fixing the existing problems. This patch series is a large one, and based on some existing code. I would like to fix existing problems first, before doing something new, if it doesn't take much time on fixing existing problems. These patches are preparatory, and usually simple. so they have more chances to be reviewed in a timely manner. These preparatory patches set up a context for your large patch series, and the context is helpful to understanding your patch series. As a result, the review process may be shortened. I don't want you to fix existing problems first, or take other actions. Just let you know something submitters can do to help maintainers to approve patches.
On Thu 28 Nov 2013 05:19:15 PM PKT, Yao Qi wrote: > On 11/28/2013 06:04 AM, Omair Javaid wrote: >>> gdb is for user space; and use space is not allowed to use SPSR >>>> directly using MSR instruction. >>>> so old code base + new code base whereever we have got SPSR getting >>>> modified we need to remove the same. >>>> >> I agree with you that we have to do a lot of rework of previous process record code. But I am not sure it would be productive for us to get working code out and loose the functionality or delay its submission. As Record/Replay is pretty much functional with this set of patches I am hoping that we can do a complete rework if required later on. >> > > If there is something broken related to the submissions, the common > practise could be one of them below: > > 1. Fix them first, > 2. Document the existing limitations/problems or write a test case to > kfail it. In this way, people are aware of this. > 3. Continue the submission and revisit the problems later. > > Personally, I choose one of them, depending on the complexity of fixing > the existing problems. This patch series is a large one, and based on > some existing code. I would like to fix existing problems first, before > doing something new, if it doesn't take much time on fixing existing > problems. These patches are preparatory, and usually simple. so they > have more chances to be reviewed in a timely manner. These preparatory > patches set up a context for your large patch series, and the context is > helpful to understanding your patch series. As a result, the review > process may be shortened. > > I don't want you to fix existing problems first, or take other actions. > Just let you know something submitters can do to help maintainers to > approve patches. > Ping! Looking for maintainer's approval for arm process record/replay improvement patches.
On 11/24/2013 11:49 PM, Omair Javaid wrote: > Patch has been updated after incorporating suggestions. Looking for a final > commit verdict. > > This patch adds support for recording thumb32 instructions. This patch also > fixes bugs in arm process record instruction decoding. It's not clear what this "also fixes bugs" refers to. Could that part be something that could be split into it's own patch? > gdb: > > 2013-11-08 Omair Javaid <omair.javaid@linaro.org> > > * arm-tdep.c (struct arm_mem_r): Use uint32_t for memory address. > (arm_record_unsupported_insn): New function. > (arm_record_coproc_data_proc): Removed. > (thumb2_record_ld_st_multiple): New function. > (thumb2_record_ld_st_dual_ex_tbb): New function. > (thumb2_record_data_proc_sreg_mimm): New function. > (thumb2_record_ps_dest_generic): New function. > (thumb2_record_branch_misc_cntrl): New function. > (thumb2_record_str_single_data): New function. > (thumb2_record_ld_mem_hints): New function. > (thumb2_record_ld_word): New function. > (thumb2_record_lmul_lmla_div): New function. > (thumb2_record_decode_inst_id): New function. > (decode_insn): Add thumb32 instruction handlers. > > +/* Handler for thumb2 load/store multiple instructions. */ > + > +static int > +thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r) > +{ > + struct regcache *reg_cache = thumb2_insn_r->regcache; > + > + uint32_t reg_rn, op; > + uint32_t register_bits = 0, register_count = 0; > + uint32_t index = 0, start_address = 0; > + uint32_t record_buf[24], record_buf_mem[48]; > + > + ULONGEST u_regval = 0; > + > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + op = bits (thumb2_insn_r->arm_insn, 23, 24); > + > + if (0 == op || 3 == op) > + { > + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) > + { > + /* Handle RFE instruction. */ > + record_buf[0] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 1; > + } > + else > + { > + /* Handle SRS instruction after reading banked SP. */ > + return arm_record_unsupported_insn (thumb2_insn_r); > + } > + } > + else if(1 == op || 2 == op) Missing space before parens. > + { > + 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); Unnecessary parens. > + } > + > + thumb2_insn_r->mem_rec_count = register_count; > + while (register_count) while (register_count > 0) > + { > + record_buf_mem[(register_count * 2) - 1] = start_address; > + record_buf_mem[(register_count * 2) - 2] = 4; Unnecessary parens. > + start_address = start_address + 4; > + register_count--; > + } > + record_buf[0] = reg_rn; > + record_buf[1] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 2; > + } > + } > + > + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, > + record_buf_mem); > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > +} > + > +/* Handler for thumb2 load memory hints instructions. */ > + > +static int > +thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t record_buf[8]; > + uint32_t reg_rt, reg_rn; > + > + reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15); > + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); > + > + if (ARM_PC_REGNUM != reg_rt) > + { > + record_buf[0] = reg_rt; > + record_buf[1] = reg_rn; > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return 0; > + } > + > + return -1; > +} > + > +/* Handler for thumb2 long multiply, long multiply accumulate, and > + divide instructions. Return value: -1:record failure ; 0:success. */ "Returns -1 on failure, 0 on success." Most of the other functions lack describing the return. Please update them too. > + > +static int > +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r) > +{ > + uint32_t ret = 0; > + uint32_t opcode1 = 0, opcode2 = 0; > + uint32_t record_buf[8]; > + uint32_t reg_src1 = 0; > + > + opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22); > + opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7); > + > + if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6)) > + { > + /* Handle SMULL, UMULL, SMULAL. */ > + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */ > + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); > + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + } > + else if (1 == opcode1 || 3 == opcode2) > + { > + /* Handle SDIV and UDIV. */ > + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); > + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); > + record_buf[2] = ARM_PS_REGNUM; > + thumb2_insn_r->reg_rec_count = 3; > + } > + else > + ret = -1; > + > + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, > + record_buf); > + return ret; > +} > + > +/* Decodes thumb2 instruction type and return an instruction id. */ Mention also the -1 on failure. But, where are these instruction ids described? Can this be an enum? > + > +static unsigned int > +thumb2_record_decode_inst_id (uint32_t thumb2_insn) > +{ > + return -1; > +} > > + /* (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] = > + { \ No need for that \. > + thumb2_record_ld_st_multiple, /* 00. */ > + thumb2_record_ld_st_dual_ex_tbb, /* 01. */ > + thumb2_record_data_proc_sreg_mimm, /* 02. */ > + arm_record_unsupported_insn, /* 03. */ > + thumb2_record_data_proc_sreg_mimm, /* 04. */ > + thumb2_record_ps_dest_generic, /* 05. */ > + thumb2_record_branch_misc_cntrl, /* 06. */ > + thumb2_record_str_single_data, /* 07. */ > + arm_record_unsupported_insn, /* 08. */ > + thumb2_record_ld_mem_hints, /* 09. */ > + thumb2_record_ld_mem_hints, /* 10. */ > + thumb2_record_ld_word, /* 11. */ > + thumb2_record_ps_dest_generic, /* 12. */ > + thumb2_record_ps_dest_generic, /* 13. */ > + thumb2_record_lmul_lmla_div, /* 14. */ > + arm_record_unsupported_insn /* 15. */ > + }; So, that number was an index into this table? Why not simply have thumb2_record_decode_inst_id return a sti_arm_hdl_fp_t directly? Or better, just have thumb2_record_decode_inst_id call the function directly (renamed to thumb2_record_handle_insn)? AFAICS, this is only used in one place: > + > + insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn); > + > + if (insn_id >= 0) > + ret = thumb2_handle_insn[insn_id] (arm_record); > + else > + { > + arm_record_unsupported_insn(arm_record); > + ret = -1; > + } That could then just be: ret = thumb2_record_handle_insn (arm_record->arm_insn); BTW, "insn" is much more common in GDB as short for instruction than inst. > + > uint32_t ret = 0; /* return value: negative:failure 0:success. */ Please use full sentences instead of that ':' syntax. Document the return code in the function's intro instead, and then you don't need to document it here. A variable called 'ret' becomes self describing.
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 7c78a61..ecaced7 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10618,7 +10618,7 @@ vfp - VFP co-processor."), struct arm_mem_r { uint32_t len; /* Record length. */ - CORE_ADDR addr; /* Memory address. */ + uint32_t addr; /* Memory address. */ }; /* ARM instruction record contains opcode of current insn @@ -11919,7 +11919,7 @@ arm_record_b_bl (insn_decode_record *arm_insn_r) /* Handling opcode 110 insns. */ static int -arm_record_coproc (insn_decode_record *arm_insn_r) +arm_record_unsupported_insn (insn_decode_record *arm_insn_r) { printf_unfiltered (_("Process record does not support instruction " "0x%0x at address %s.\n"),arm_insn_r->arm_insn, @@ -12414,6 +12414,584 @@ thumb_record_branch (insn_decode_record *thumb_insn_r) return 0; } +/* Handler for thumb2 load/store multiple instructions. */ + +static int +thumb2_record_ld_st_multiple (insn_decode_record *thumb2_insn_r) +{ + struct regcache *reg_cache = thumb2_insn_r->regcache; + + uint32_t reg_rn, op; + uint32_t register_bits = 0, register_count = 0; + uint32_t index = 0, start_address = 0; + uint32_t record_buf[24], record_buf_mem[48]; + + ULONGEST u_regval = 0; + + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); + op = bits (thumb2_insn_r->arm_insn, 23, 24); + + if (0 == op || 3 == op) + { + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) + { + /* Handle RFE instruction. */ + record_buf[0] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 1; + } + else + { + /* Handle SRS instruction after reading banked SP. */ + return arm_record_unsupported_insn (thumb2_insn_r); + } + } + else if(1 == op || 2 == op) + { + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) + { + /* Handle LDM/LDMIA/LDMFD and LDMDB/LDMEA instructions. */ + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); + while (register_bits) + { + if (register_bits & 0x00000001) + record_buf[index++] = register_count; + + register_count++; + register_bits = register_bits >> 1; + } + record_buf[index++] = reg_rn; + record_buf[index++] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = index; + } + else + { + /* Handle STM/STMIA/STMEA and STMDB/STMFD. */ + register_bits = bits (thumb2_insn_r->arm_insn, 0, 15); + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); + while (register_bits) + { + if (register_bits & 0x00000001) + register_count++; + + register_bits = register_bits >> 1; + } + + if (1 == op) + { + /* Start address calculation for LDMDB/LDMEA. */ + start_address = u_regval; + } + else if (2 == op) + { + /* Start address calculation for LDMDB/LDMEA. */ + start_address = (u_regval) - (register_count * 4); + } + + thumb2_insn_r->mem_rec_count = register_count; + while (register_count) + { + record_buf_mem[(register_count * 2) - 1] = start_address; + record_buf_mem[(register_count * 2) - 2] = 4; + start_address = start_address + 4; + register_count--; + } + record_buf[0] = reg_rn; + record_buf[1] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + } + } + + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, + record_buf_mem); + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; +} + +/* Handler for thumb2 load/store (dual/exclusive) and table branch + instructions. */ + +static int +thumb2_record_ld_st_dual_ex_tbb (insn_decode_record *thumb2_insn_r) +{ + struct regcache *reg_cache = thumb2_insn_r->regcache; + + uint32_t reg_rd, reg_rn, offset_imm; + uint32_t reg_dest1, reg_dest2; + uint32_t address, offset_addr; + uint32_t record_buf[8], record_buf_mem[8]; + uint32_t op1, op2, op3; + LONGEST s_word; + + ULONGEST u_regval[2]; + + op1 = bits (thumb2_insn_r->arm_insn, 23, 24); + op2 = bits (thumb2_insn_r->arm_insn, 20, 21); + op3 = bits (thumb2_insn_r->arm_insn, 4, 7); + + if (bit (thumb2_insn_r->arm_insn, INSN_S_L_BIT_NUM)) + { + if(!(1 == op1 && 1 == op2 && (0 == op3 || 1 == op3))) + { + reg_dest1 = bits (thumb2_insn_r->arm_insn, 12, 15); + record_buf[0] = reg_dest1; + record_buf[1] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + } + + if (3 == op2 || (op1 & 2) || (1 == op1 && 1 == op2 && 7 == op3)) + { + reg_dest2 = bits (thumb2_insn_r->arm_insn, 8, 11); + record_buf[2] = reg_dest2; + thumb2_insn_r->reg_rec_count = 3; + } + } + else + { + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); + + if (0 == op1 && 0 == op2) + { + /* Handle STREX. */ + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); + address = u_regval[0] + (offset_imm * 4); + record_buf_mem[0] = 4; + record_buf_mem[1] = address; + thumb2_insn_r->mem_rec_count = 1; + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); + record_buf[0] = reg_rd; + thumb2_insn_r->reg_rec_count = 1; + } + else if (1 == op1 && 0 == op2) + { + reg_rd = bits (thumb2_insn_r->arm_insn, 0, 3); + record_buf[0] = reg_rd; + thumb2_insn_r->reg_rec_count = 1; + address = u_regval[0]; + record_buf_mem[1] = address; + + if (4 == op3) + { + /* Handle STREXB. */ + record_buf_mem[0] = 1; + thumb2_insn_r->mem_rec_count = 1; + } + else if (5 == op3) + { + /* Handle STREXH. */ + record_buf_mem[0] = 2 ; + thumb2_insn_r->mem_rec_count = 1; + } + else if (7 == op3) + { + /* Handle STREXD. */ + address = u_regval[0]; + record_buf_mem[0] = 4; + record_buf_mem[2] = 4; + record_buf_mem[3] = address + 4; + thumb2_insn_r->mem_rec_count = 2; + } + } + else + { + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); + + if (bit (thumb2_insn_r->arm_insn, 24)) + { + if (bit (thumb2_insn_r->arm_insn, 23)) + offset_addr = u_regval[0] + (offset_imm * 4); + else + offset_addr = u_regval[0] - (offset_imm * 4); + + address = offset_addr; + } + else + address = u_regval[0]; + + record_buf_mem[0] = 4; + record_buf_mem[1] = address; + record_buf_mem[2] = 4; + record_buf_mem[3] = address + 4; + thumb2_insn_r->mem_rec_count = 2; + record_buf[0] = reg_rn; + thumb2_insn_r->reg_rec_count = 1; + } + } + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, + record_buf_mem); + return 0; +} + +/* Handler for thumb2 data processing (shift register and modified immediate) + instructions. */ + +static int +thumb2_record_data_proc_sreg_mimm (insn_decode_record *thumb2_insn_r) +{ + uint32_t reg_rd, op; + uint32_t record_buf[8]; + + op = bits (thumb2_insn_r->arm_insn, 21, 24); + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); + + if ((0 == op || 4 == op || 8 == op || 13 == op) && 15 == reg_rd) + { + record_buf[0] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 1; + } + else + { + record_buf[0] = reg_rd; + record_buf[1] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + } + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; +} + +/* Generic handler for thumb2 instructions which effect destination and PS + registers. */ + +static int +thumb2_record_ps_dest_generic (insn_decode_record *thumb2_insn_r) +{ + uint32_t reg_rd; + uint32_t record_buf[8]; + + reg_rd = bits (thumb2_insn_r->arm_insn, 8, 11); + + record_buf[0] = reg_rd; + record_buf[1] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; +} + +/* Handler for thumb2 branch and miscellaneous control instructions. */ + +static int +thumb2_record_branch_misc_cntrl (insn_decode_record *thumb2_insn_r) +{ + uint32_t op, op1, op2; + uint32_t record_buf[8]; + + op = bits (thumb2_insn_r->arm_insn, 20, 26); + op1 = bits (thumb2_insn_r->arm_insn, 12, 14); + op2 = bits (thumb2_insn_r->arm_insn, 8, 11); + + /* Handle MSR insn. */ + if (!(op1 & 0x2) && 0x38 == op) + { + if (!(op2 & 0x3)) + { + /* CPSR is going to be changed. */ + record_buf[0] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 1; + } + else + { + arm_record_unsupported_insn(thumb2_insn_r); + return -1; + } + } + else if (4 == (op1 & 0x5) || 5 == (op1 & 0x5)) + { + /* BLX. */ + record_buf[0] = ARM_PS_REGNUM; + record_buf[1] = ARM_LR_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + } + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; +} + +/* Handler for thumb2 store single data item instructions. */ + +static int +thumb2_record_str_single_data (insn_decode_record *thumb2_insn_r) +{ + struct regcache *reg_cache = thumb2_insn_r->regcache; + + uint32_t reg_rn, reg_rm, offset_imm, shift_imm; + uint32_t address, offset_addr; + uint32_t record_buf[8], record_buf_mem[8]; + uint32_t op1, op2; + + ULONGEST u_regval[2]; + + op1 = bits (thumb2_insn_r->arm_insn, 21, 23); + op2 = bits (thumb2_insn_r->arm_insn, 6, 11); + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); + regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval[0]); + + if (bit (thumb2_insn_r->arm_insn, 23)) + { + /* T2 encoding. */ + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 11); + offset_addr = u_regval[0] + offset_imm; + address = offset_addr; + } + else + { + /* T3 encoding. */ + if ((0 == op1 || 1 == op1 || 2 == op1) && !(op2 & 0x20)) + { + /* Handle STRB (register). */ + reg_rm = bits (thumb2_insn_r->arm_insn, 0, 3); + regcache_raw_read_unsigned (reg_cache, reg_rm, &u_regval[1]); + shift_imm = bits (thumb2_insn_r->arm_insn, 4, 5); + offset_addr = u_regval[1] << shift_imm; + address = u_regval[0] + offset_addr; + } + else + { + offset_imm = bits (thumb2_insn_r->arm_insn, 0, 7); + if (bit (thumb2_insn_r->arm_insn, 10)) + { + if (bit (thumb2_insn_r->arm_insn, 9)) + offset_addr = u_regval[0] + offset_imm; + else + offset_addr = u_regval[0] - offset_imm; + + address = offset_addr; + } + else + address = u_regval[0]; + } + } + + switch (op1) + { + /* Store byte instructions. */ + case 4: + case 0: + record_buf_mem[0] = 1; + break; + /* Store half word instructions. */ + case 1: + case 5: + record_buf_mem[0] = 2; + break; + /* Store word instructions. */ + case 2: + case 6: + record_buf_mem[0] = 4; + break; + + default: + gdb_assert_not_reached ("no decoding pattern found"); + break; + } + + record_buf_mem[1] = address; + thumb2_insn_r->mem_rec_count = 1; + record_buf[0] = reg_rn; + thumb2_insn_r->reg_rec_count = 1; + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + MEM_ALLOC (thumb2_insn_r->arm_mems, thumb2_insn_r->mem_rec_count, + record_buf_mem); + return 0; +} + +/* Handler for thumb2 load memory hints instructions. */ + +static int +thumb2_record_ld_mem_hints (insn_decode_record *thumb2_insn_r) +{ + uint32_t record_buf[8]; + uint32_t reg_rt, reg_rn; + + reg_rt = bits (thumb2_insn_r->arm_insn, 12, 15); + reg_rn = bits (thumb2_insn_r->arm_insn, 16, 19); + + if (ARM_PC_REGNUM != reg_rt) + { + record_buf[0] = reg_rt; + record_buf[1] = reg_rn; + record_buf[2] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 3; + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; + } + + return -1; +} + +/* Handler for thumb2 load word instructions. */ + +static int +thumb2_record_ld_word (insn_decode_record *thumb2_insn_r) +{ + uint32_t opcode1 = 0, opcode2 = 0; + uint32_t record_buf[8]; + + record_buf[0] = bits (thumb2_insn_r->arm_insn, 12, 15); + record_buf[1] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 2; + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return 0; +} + +/* Handler for thumb2 long multiply, long multiply accumulate, and + divide instructions. Return value: -1:record failure ; 0:success. */ + +static int +thumb2_record_lmul_lmla_div (insn_decode_record *thumb2_insn_r) +{ + uint32_t ret = 0; + uint32_t opcode1 = 0, opcode2 = 0; + uint32_t record_buf[8]; + uint32_t reg_src1 = 0; + + opcode1 = bits (thumb2_insn_r->arm_insn, 20, 22); + opcode2 = bits (thumb2_insn_r->arm_insn, 4, 7); + + if (0 == opcode1 || 2 == opcode1 || (opcode1 >= 4 && opcode1 <= 6)) + { + /* Handle SMULL, UMULL, SMULAL. */ + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */ + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); + record_buf[2] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 3; + } + else if (1 == opcode1 || 3 == opcode2) + { + /* Handle SDIV and UDIV. */ + record_buf[0] = bits (thumb2_insn_r->arm_insn, 16, 19); + record_buf[1] = bits (thumb2_insn_r->arm_insn, 12, 15); + record_buf[2] = ARM_PS_REGNUM; + thumb2_insn_r->reg_rec_count = 3; + } + else + ret = -1; + + REG_ALLOC (thumb2_insn_r->arm_regs, thumb2_insn_r->reg_rec_count, + record_buf); + return ret; +} + +/* Decodes thumb2 instruction type and return an instruction id. */ + +static unsigned int +thumb2_record_decode_inst_id (uint32_t thumb2_insn) +{ + uint32_t op = 0; + uint32_t op1 = 0; + uint32_t op2 = 0; + + op = bit (thumb2_insn, 15); + op1 = bits (thumb2_insn, 27, 28); + op2 = bits (thumb2_insn, 20, 26); + + if (op1 == 0x01) + { + if (!(op2 & 0x64 )) + { + /* Load/store multiple instruction. */ + return 0; + } + else if (!((op2 & 0x64) ^ 0x04)) + { + /* Load/store (dual/exclusive) and table branch instruction. */ + return 1; + } + else if (!((op2 & 0x20) ^ 0x20)) + { + /* Data-processing (shifted register). */ + return 2; + } + else if (op2 & 0x40) + { + /* Co-processor instructions. */ + return 3; + } + } + else if (op1 == 0x02) + { + if (op) + { + /* Branches and miscellaneous control instructions. */ + return 6; + } + else if (op2 & 0x20) + { + /* Data-processing (plain binary immediate) instruction. */ + return 5; + } + else + { + /* Data-processing (modified immediate). */ + return 4; + } + } + else if (op1 == 0x03) + { + if (!(op2 & 0x71 )) + { + /* Store single data item. */ + return 7; + } + else if (!((op2 & 0x71) ^ 0x10)) + { + /* Advanced SIMD or structure load/store instructions. */ + return 8; + } + else if (!((op2 & 0x67) ^ 0x01)) + { + /* Load byte, memory hints instruction. */ + return 9; + } + else if (!((op2 & 0x67) ^ 0x03)) + { + /* Load halfword, memory hints instruction. */ + return 10; + } + else if (!((op2 & 0x67) ^ 0x05)) + { + /* Load word instruction. */ + return 11; + } + else if (!((op2 & 0x70) ^ 0x20)) + { + /* Data-processing (register) instruction. */ + return 12; + } + else if (!((op2 & 0x78) ^ 0x30)) + { + /* Multiply, multiply accumulate, abs diff instruction. */ + return 13; + } + else if (!((op2 & 0x78) ^ 0x38)) + { + /* Long multiply, long multiply accumulate, and divide. */ + return 14; + } + else if (op2 & 0x40) + { + /* Co-processor instructions. */ + return 15; + } + } + + return -1; +} /* Extracts arm/thumb/thumb2 insn depending on the size, and returns 0 on success and positive val on fauilure. */ @@ -12452,7 +13030,7 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, arm_record_ld_st_reg_offset, /* 011. */ arm_record_ld_st_multiple, /* 100. */ arm_record_b_bl, /* 101. */ - arm_record_coproc, /* 110. */ + arm_record_unsupported_insn, /* 110. */ arm_record_coproc_data_proc /* 111. */ }; @@ -12469,6 +13047,28 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, thumb_record_branch /* 111. */ }; + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb + instruction. */ + static const sti_arm_hdl_fp_t const thumb2_handle_insn[16] = + { \ + thumb2_record_ld_st_multiple, /* 00. */ + thumb2_record_ld_st_dual_ex_tbb, /* 01. */ + thumb2_record_data_proc_sreg_mimm, /* 02. */ + arm_record_unsupported_insn, /* 03. */ + thumb2_record_data_proc_sreg_mimm, /* 04. */ + thumb2_record_ps_dest_generic, /* 05. */ + thumb2_record_branch_misc_cntrl, /* 06. */ + thumb2_record_str_single_data, /* 07. */ + arm_record_unsupported_insn, /* 08. */ + thumb2_record_ld_mem_hints, /* 09. */ + thumb2_record_ld_mem_hints, /* 10. */ + thumb2_record_ld_word, /* 11. */ + thumb2_record_ps_dest_generic, /* 12. */ + thumb2_record_ps_dest_generic, /* 13. */ + thumb2_record_lmul_lmla_div, /* 14. */ + arm_record_unsupported_insn /* 15. */ + }; + uint32_t ret = 0; /* return value: negative:failure 0:success. */ uint32_t insn_id = 0; @@ -12503,11 +13103,22 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, } else if (THUMB2_RECORD == record_type) { - printf_unfiltered (_("Process record doesnt support thumb32 instruction " - "0x%0x at address %s.\n"),arm_record->arm_insn, - paddress (arm_record->gdbarch, - arm_record->this_addr)); - ret = -1; + /* As thumb does not have condition codes, we set negative. */ + arm_record->cond = -1; + + /* Swap first half of 32bit thumb instruction with second half. */ + arm_record->arm_insn = (arm_record->arm_insn >> 16) | + (arm_record->arm_insn << 16); + + insn_id = thumb2_record_decode_inst_id (arm_record->arm_insn); + + if (insn_id >= 0) + ret = thumb2_handle_insn[insn_id] (arm_record); + else + { + arm_record_unsupported_insn(arm_record); + ret = -1; + } } else {