From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18522 invoked by alias); 27 Nov 2013 22:04:46 -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 18512 invoked by uid 89); 27 Nov 2013 22:04:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.5 required=5.0 tests=AWL,BAYES_50,RDNS_NONE,SPF_PASS,URIBL_BLOCKED autolearn=no version=3.3.2 X-HELO: mail-wg0-f45.google.com Received: from Unknown (HELO mail-wg0-f45.google.com) (74.125.82.45) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 27 Nov 2013 22:04:42 +0000 Received: by mail-wg0-f45.google.com with SMTP id y10so5669919wgg.24 for ; Wed, 27 Nov 2013 14:04:32 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type :content-transfer-encoding; bh=gTgMLfDqSt0GDFjx1U4LHMbt+pQSHU4ucK7V8PhePN0=; b=ff3w9mahjp5TiXVyTvtG7krnky+bo1WV0Zq36CPK7s12ISJyPsJmXkCHcwhtn8wykf fFWoqCq7lli3tGziyHMp9nGTAvlZKgb3rJ1tj0NaO+yS2qCJkmK9fjTJ/JThsXk7eLdR roY1t2QOzjTExglrroPJ91OODOI/OZh8YkAMkz1Rten6iia4HNTzv7MQfO859it3o/8Y Q6lN6kqcbDm3ioGo4vLd1OXMChDUZQVRIowAwZz5v+JUzeIcobk2oVy1c4qQlY0udE3g d81l+aE8RPCtbptGywwjthutDwU+8PLBz69I+b9b0xCBP8ejbxhqgKC02IzvkD3TTqkT V5ow== X-Gm-Message-State: ALoCoQkqGNMqcDkZvcZDPRsCK7M8eU+ephxAO0mYIAIzQxM2Jcyut2l5wt0otdCQsNZzmQ0o1a3U X-Received: by 10.180.9.110 with SMTP id y14mr24799667wia.61.1385589872239; Wed, 27 Nov 2013 14:04:32 -0800 (PST) Received: from [192.168.1.2] ([182.185.192.168]) by mx.google.com with ESMTPSA id a19sm74963658wib.1.2013.11.27.14.04.29 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 27 Nov 2013 14:04:31 -0800 (PST) Message-ID: <52966C69.3080506@linaro.org> Date: Wed, 27 Nov 2013 23:58:00 -0000 From: Omair Javaid User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.1.1 MIME-Version: 1.0 To: Oza Pawandeep CC: Yao Qi , "gdb-patches@sourceware.org" , Patch Tracking Subject: Re: [PATCH 1/2] GDB process record and reverse debugging improvements for arm*-linux* References: <526884D5.309@codesourcery.com> <527C5856.50500@linaro.org> <5280ACE9.9050308@codesourcery.com> <52929080.1030304@linaro.org> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2013-11/txt/msg00864.txt.bz2 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 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 >> { >> -- >