From patchwork Fri Sep 18 12:42:58 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 8773 Received: (qmail 8000 invoked by alias); 18 Sep 2015 12:43:15 -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 7875 invoked by uid 89); 18 Sep 2015 12:43:14 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wi0-f173.google.com Received: from mail-wi0-f173.google.com (HELO mail-wi0-f173.google.com) (209.85.212.173) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 18 Sep 2015 12:43:13 +0000 Received: by wicfx3 with SMTP id fx3so62702414wic.1 for ; Fri, 18 Sep 2015 05:43:10 -0700 (PDT) X-Received: by 10.194.75.169 with SMTP id d9mr6812552wjw.7.1442580190322; Fri, 18 Sep 2015 05:43:10 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com ([195.154.84.196]) by smtp.gmail.com with ESMTPSA id uq5sm8742676wjc.3.2015.09.18.05.43.09 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 18 Sep 2015 05:43:09 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 2/8] Make aarch64_decode_adrp handle both ADR and ADRP instructions Date: Fri, 18 Sep 2015 13:42:58 +0100 Message-Id: <1442580184-22562-3-git-send-email-yao.qi@linaro.org> In-Reply-To: <1442580184-22562-1-git-send-email-yao.qi@linaro.org> References: <1442230282-20751-1-git-send-email-pierre.langlois@arm.com> <1442580184-22562-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes From: Pierre Langlois 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);