From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20543 invoked by alias); 25 Nov 2013 13:07:47 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 20532 invoked by uid 89); 25 Nov 2013 13:07:47 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.2 required=5.0 tests=AWL,BAYES_50,FREEMAIL_FROM,RDNS_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mail-wi0-f176.google.com Received: from Unknown (HELO mail-wi0-f176.google.com) (209.85.212.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 25 Nov 2013 13:07:45 +0000 Received: by mail-wi0-f176.google.com with SMTP id hq4so3524671wib.15 for ; Mon, 25 Nov 2013 05:07:36 -0800 (PST) MIME-Version: 1.0 X-Received: by 10.180.210.206 with SMTP id mw14mr13741777wic.14.1385384855963; Mon, 25 Nov 2013 05:07:35 -0800 (PST) Received: by 10.194.79.194 with HTTP; Mon, 25 Nov 2013 05:07:35 -0800 (PST) In-Reply-To: <52929080.1030304@linaro.org> References: <526884D5.309@codesourcery.com> <527C5856.50500@linaro.org> <5280ACE9.9050308@codesourcery.com> <52929080.1030304@linaro.org> Date: Mon, 25 Nov 2013 14:23:00 -0000 Message-ID: Subject: Re: [PATCH 1/2] GDB process record and reverse debugging improvements for arm*-linux* From: Oza Pawandeep To: Omair Javaid Cc: Yao Qi , "gdb-patches@sourceware.org" , Patch Tracking Content-Type: text/plain; charset=ISO-8859-1 X-IsSubscribed: yes X-SW-Source: 2013-11/txt/msg00769.txt.bz2 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 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 > > * 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 > { > --