From patchwork Tue Sep 15 12:05:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pierre Langlois X-Patchwork-Id: 8698 Received: (qmail 7249 invoked by alias); 15 Sep 2015 12:05:29 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 7226 invoked by uid 89); 15 Sep 2015 12:05:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: eu-smtp-delivery-143.mimecast.com Received: from eu-smtp-delivery-143.mimecast.com (HELO eu-smtp-delivery-143.mimecast.com) (146.101.78.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 15 Sep 2015 12:05:25 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-35-M7vcME-pRbaZVAulKNDJzw-1; Tue, 15 Sep 2015 13:05:20 +0100 Received: from e105615-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 15 Sep 2015 13:05:20 +0100 From: Pierre Langlois To: gdb-patches@sourceware.org Cc: Pierre Langlois Subject: [PATCH 3/8 v2] [AArch64] Make aarch64_decode_adrp handle both ADR and ADRP instructions Date: Tue, 15 Sep 2015 13:05:18 +0100 Message-Id: <1442318718-40470-1-git-send-email-pierre.langlois@arm.com> In-Reply-To: <861te03say.fsf@gmail.com> References: <861te03say.fsf@gmail.com> X-MC-Unique: M7vcME-pRbaZVAulKNDJzw-1 X-IsSubscribed: yes Here is the rebased patch. Thanks, Pierre --- We will need to decode both ADR and ADRP instructions in GDBserver. This patch makes common code handle both cases, even if GDB only needs to decode the ADRP instruction. gdb/ChangeLog: * aarch64-tdep.c (aarch64_analyze_prologue): New is_adrp variable. Call aarch64_decode_adr instead of aarch64_decode_adrp. * arch/aarch64-insn.h (aarch64_decode_adrp): Delete. (aarch64_decode_adr): New function declaration. * arch/aarch64-insn.c (aarch64_decode_adrp): Delete. (aarch64_decode_adr): New function, factored out from aarch64_decode_adrp to decode both adr and adrp instructions. --- gdb/aarch64-tdep.c | 4 +++- gdb/arch/aarch64-insn.c | 29 ++++++++++++++++++++++++----- gdb/arch/aarch64-insn.h | 3 ++- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 92e2404..da61e54 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -551,13 +551,15 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, int is_cbnz; int is_tbnz; unsigned bit; + int is_adrp; int32_t offset; insn = read_memory_unsigned_integer (start, 4, byte_order_for_code); if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm)) regs[rd] = pv_add_constant (regs[rn], imm); - else if (aarch64_decode_adrp (start, insn, &rd)) + else if (aarch64_decode_adr (start, insn, &is_adrp, &rd, &offset) + && is_adrp) regs[rd] = pv_unknown (); else if (aarch64_decode_b (start, insn, &is_link, &offset)) { diff --git a/gdb/arch/aarch64-insn.c b/gdb/arch/aarch64-insn.c index 3a289a2..13d0013 100644 --- a/gdb/arch/aarch64-insn.c +++ b/gdb/arch/aarch64-insn.c @@ -55,25 +55,44 @@ decode_masked_match (uint32_t insn, uint32_t mask, uint32_t pattern) return (insn & mask) == pattern; } -/* Decode an opcode if it represents an ADRP instruction. +/* Decode an opcode if it represents an ADR or ADRP instruction. ADDR specifies the address of the opcode. INSN specifies the opcode to test. + IS_ADRP receives the 'op' field from the decoded instruction. RD receives the 'rd' field from the decoded instruction. + OFFSET receives the 'immhi:immlo' field from the decoded instruction. Return 1 if the opcodes matches and is decoded, otherwise 0. */ int -aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd) +aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp, + unsigned *rd, int32_t *offset) { - if (decode_masked_match (insn, 0x9f000000, 0x90000000)) + /* adr 0ii1 0000 iiii iiii iiii iiii iiir rrrr */ + /* adrp 1ii1 0000 iiii iiii iiii iiii iiir rrrr */ + if (decode_masked_match (insn, 0x1f000000, 0x10000000)) { + uint32_t immlo = (insn >> 29) & 0x3; + int32_t immhi = extract_signed_bitfield (insn, 19, 5) << 2; + + *is_adrp = (insn >> 31) & 0x1; *rd = (insn >> 0) & 0x1f; + if (*is_adrp) + { + /* The ADRP instruction has an offset with a -/+ 4GB range, + encoded as (immhi:immlo * 4096). */ + *offset = (immhi | immlo) * 4096; + } + else + *offset = (immhi | immlo); + if (aarch64_debug) { - debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n", - core_addr_to_string_nz (addr), insn, *rd); + debug_printf ("decode: 0x%s 0x%x %s x%u, #?\n", + core_addr_to_string_nz (addr), insn, + *is_adrp ? "adrp" : "adr", *rd); } return 1; } diff --git a/gdb/arch/aarch64-insn.h b/gdb/arch/aarch64-insn.h index 7775a34..2facb44 100644 --- a/gdb/arch/aarch64-insn.h +++ b/gdb/arch/aarch64-insn.h @@ -21,7 +21,8 @@ extern int aarch64_debug; -int aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd); +int aarch64_decode_adr (CORE_ADDR addr, uint32_t insn, int *is_adrp, + unsigned *rd, int32_t *offset); int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, int32_t *offset);