From patchwork Sun Nov 24 23:49:20 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omair Javaid X-Patchwork-Id: 21730 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f71.google.com (mail-oa0-f71.google.com [209.85.219.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 246F323FCB for ; Sun, 24 Nov 2013 23:49:30 +0000 (UTC) Received: by mail-oa0-f71.google.com with SMTP id i4sf12722323oah.2 for ; Sun, 24 Nov 2013 15:49:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:date:from:user-agent :mime-version:to:cc:subject:references:in-reply-to:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe:content-type :content-transfer-encoding; bh=jWKz+aL27bAKlDFp9y1edQEEkveUyem9PdBoqjWbC9s=; b=PlkDs/52zZWSQvTfNrridcT6SLVjdt0TEZHd7uWq0HfM85RsyejG0q51P14mVEZ88G sO+C3gWl+FNG/v3CMGAUs8vJWt7vjubWbLv7lOllby+xhtIxHscWypqiD3K82xzL+SKW 52qMdM5R6N+9+AJCOn3osvM86LAvaFy7OJXPPTjhdY1gEjBzm1ceKn0yrdl3ajzDjaDw cQbzkFXWwKH6pIXOg6u15V9g+c0daHx7+C7nACoRf1uQz81RLWINO+wCJNgWeXN80OUA RRu8qeT32A8iSxM4B8LyYv2zC6/ozsEXXpFrt5EUyqbL8lfm3QpsvxxzrzuhRPHhQ7Py rtfA== X-Gm-Message-State: ALoCoQkFkDQGKoMKFt4SrSojBIo3vEnTpG2ZtobuuRScYIqzhFPcNw8dsemUQNihasXhi9l7Jf9G X-Received: by 10.182.186.105 with SMTP id fj9mr8253486obc.5.1385336969722; Sun, 24 Nov 2013 15:49:29 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.104.40 with SMTP id gb8ls1903825qeb.27.gmail; Sun, 24 Nov 2013 15:49:29 -0800 (PST) X-Received: by 10.58.133.77 with SMTP id pa13mr148130veb.21.1385336969598; Sun, 24 Nov 2013 15:49:29 -0800 (PST) Received: from mail-vc0-f181.google.com (mail-vc0-f181.google.com [209.85.220.181]) by mx.google.com with ESMTPS id a6si16740862vdp.13.2013.11.24.15.49.29 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 24 Nov 2013 15:49:29 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.181 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.181; Received: by mail-vc0-f181.google.com with SMTP id ks9so2222618vcb.26 for ; Sun, 24 Nov 2013 15:49:29 -0800 (PST) X-Received: by 10.221.64.17 with SMTP id xg17mr23414764vcb.5.1385336969383; Sun, 24 Nov 2013 15:49:29 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp96096vcz; Sun, 24 Nov 2013 15:49:28 -0800 (PST) X-Received: by 10.180.94.100 with SMTP id db4mr11431117wib.14.1385336968188; Sun, 24 Nov 2013 15:49:28 -0800 (PST) Received: from mail-wg0-f45.google.com (mail-wg0-f45.google.com [74.125.82.45]) by mx.google.com with ESMTPS id fz1si6365981wic.55.2013.11.24.15.49.27 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 24 Nov 2013 15:49:27 -0800 (PST) Received-SPF: neutral (google.com: 74.125.82.45 is neither permitted nor denied by best guess record for domain of omair.javaid@linaro.org) client-ip=74.125.82.45; Received: by mail-wg0-f45.google.com with SMTP id y10so1363189wgg.24 for ; Sun, 24 Nov 2013 15:49:27 -0800 (PST) X-Received: by 10.180.210.130 with SMTP id mu2mr11348419wic.61.1385336967437; Sun, 24 Nov 2013 15:49:27 -0800 (PST) Received: from [192.168.1.2] ([182.185.192.168]) by mx.google.com with ESMTPSA id a19sm41924535wib.1.2013.11.24.15.49.25 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 24 Nov 2013 15:49:26 -0800 (PST) Message-ID: <52929080.1030304@linaro.org> Date: Mon, 25 Nov 2013 04:49:20 +0500 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: Yao Qi CC: 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> In-Reply-To: <5280ACE9.9050308@codesourcery.com> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: omair.javaid@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.181 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , 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 {