From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3374 invoked by alias); 15 Sep 2015 12:02:49 -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 3343 invoked by uid 89); 15 Sep 2015 12:02:46 -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) (207.82.80.143) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 15 Sep 2015 12:02:36 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-34-B2ThLPOZTqW_9B7l-ee1Xg-1; Tue, 15 Sep 2015 13:02:31 +0100 Received: from e105615-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 15 Sep 2015 13:02:30 +0100 From: Pierre Langlois To: gdb-patches@sourceware.org Cc: Pierre Langlois Subject: [PATCH 2/8 v2] [AArch64] Move instruction decoding into new arch/ directory Date: Tue, 15 Sep 2015 12:02:00 -0000 Message-Id: <1442318549-37447-1-git-send-email-pierre.langlois@arm.com> In-Reply-To: <868u883se9.fsf@gmail.com> References: <868u883se9.fsf@gmail.com> X-MC-Unique: B2ThLPOZTqW_9B7l-ee1Xg-1 Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable X-IsSubscribed: yes X-SW-Source: 2015-09/txt/msg00319.txt.bz2 Here is the rebased patch, making sure the formatting issues propagated through moving file. I've also fixed `gdbserver/configure.srv'. Thanks, Pierre --- This patch moves the following functions into the arch/ common directory, in new files arch/aarch64-insn.{h,c}. They are prefixed with 'aarch64_': - aarch64_decode_adrp - aarch64_decode_b - aarch64_decode_cb - aarch64_decode_tb We will need them to implement fast tracepoints in GDBserver. For consistency, this patch also adds the 'aarch64_' prefix to static decoding functions that do not need to be shared right now. gdb/ChangeLog: * Makefile.in (ALL_64_TARGET_OBS): Add aarch64-insn.o. (HFILES_NO_SRCDIR): Add arch/aarch64-insn.h. (aarch64-insn.o): New rule. * configure.tgt (aarch64*-*-elf): Add aarch64-insn.o. (aarch64*-*-linux*): Likewise. * arch/aarch64-insn.c: New file. * arch/aarch64-insn.h: New file. * aarch64-tdep.c: Include arch/aarch64-insn.h. (aarch64_debug): Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (decode_add_sub_imm): Rename to ... (aarch64_decode_add_sub_imm): ... this. (decode_adrp): Rename to ... (aarch64_decode_adrp): ... this. Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (decode_b): Rename to ... (aarch64_decode_b): ... this. Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (decode_bcond): Rename to ... (aarch64_decode_bcond): ... this. Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (decode_br): Rename to ... (aarch64_decode_br): ... this. (decode_cb): Rename to ... (aarch64_decode_cb): ... this. Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (decode_eret): Rename to ... (aarch64_decode_eret): ... this. (decode_movz): Rename to ... (aarch64_decode_movz): ... this. (decode_orr_shifted_register_x): Rename to ... (aarch64_decode_orr_shifted_register_x): ... this. (decode_ret): Rename to ... (aarch64_decode_ret): ... this. (decode_stp_offset): Rename to ... (aarch64_decode_stp_offset): ... this. (decode_stp_offset_wb): Rename to ... (aarch64_decode_stp_offset_wb): ... this. (decode_stur): Rename to ... (aarch64_decode_stur): ... this. (decode_tb): Rename to ... (aarch64_decode_tb): ... this. Move to arch/aarch64-insn.c. Declare in arch/aarch64-insn.h. (aarch64_analyze_prologue): Adjust calls to renamed functions. gdb/gdbserver/ChangeLog: * gdb/gdbserver/Makefile.in (aarch64-insn.o): New rule. * gdb/gdbserver/configure.srv (aarch64*-*-linux*): Add aarch64-insn.o. --- gdb/Makefile.in | 13 ++- gdb/aarch64-tdep.c | 235 +++++++---------------------------------= ---- gdb/arch/aarch64-insn.c | 218 ++++++++++++++++++++++++++++++++++++++++ gdb/arch/aarch64-insn.h | 38 +++++++ gdb/configure.tgt | 4 +- gdb/gdbserver/Makefile.in | 6 ++ gdb/gdbserver/configure.srv | 1 + 7 files changed, 314 insertions(+), 201 deletions(-) create mode 100644 gdb/arch/aarch64-insn.c create mode 100644 gdb/arch/aarch64-insn.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5659116..d5ca2ee 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -644,7 +644,7 @@ TARGET_OBS =3D @TARGET_OBS@ # All target-dependent objects files that require 64-bit CORE_ADDR # (used with --enable-targets=3Dall --enable-64-bit-bfd). ALL_64_TARGET_OBS =3D \ - aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o \ + aarch64-tdep.o aarch64-linux-tdep.o aarch64-newlib-tdep.o aarch64-insn.o \ alphabsd-tdep.o alphafbsd-tdep.o alpha-linux-tdep.o alpha-mdebug-tdep.o \ alphanbsd-tdep.o alphaobsd-tdep.o alpha-tdep.o \ amd64fbsd-tdep.o amd64-darwin-tdep.o amd64-dicos-tdep.o \ @@ -986,7 +986,7 @@ common/common-debug.h common/cleanups.h common/gdb_setj= mp.h \ common/common-exceptions.h target/target.h common/symbol.h \ common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \ common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \ -nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h +nat/linux-namespaces.h arch/arm.h common/gdb_sys_time.h arch/aarch64-insn.h =20 # Header files that already have srcdir in them, or which are in objdir. =20 @@ -2336,6 +2336,15 @@ aarch64-linux.o: ${srcdir}/nat/aarch64-linux.c $(COMPILE) $(srcdir)/nat/aarch64-linux.c $(POSTCOMPILE) =20 +# gdb/arch/ dependencies +# +# Need to explicitly specify the compile rule as make will do nothing +# or try to compile the object file into the sub-directory. + +aarch64-insn.o: ${srcdir}/arch/aarch64-insn.c + $(COMPILE) $(srcdir)/arch/aarch64-insn.c + $(POSTCOMPILE) + # # gdb/tui/ dependencies # diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index 9a4eda2..92e2404 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -57,6 +57,8 @@ =20 #include "features/aarch64.c" =20 +#include "arch/aarch64-insn.h" + /* Pseudo register base numbers. */ #define AARCH64_Q0_REGNUM 0 #define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + 32) @@ -179,9 +181,6 @@ struct aarch64_prologue_cache struct trad_frame_saved_reg *saved_regs; }; =20 -/* Toggle this file's internal debugging dump. */ -static int aarch64_debug; - static void show_aarch64_debug (struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value) @@ -231,8 +230,8 @@ decode_masked_match (uint32_t insn, uint32_t mask, uint= 32_t pattern) =20 Return 1 if the opcodes matches and is decoded, otherwise 0. */ static int -decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, unsigned = *rn, - int32_t *imm) +aarch64_decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, + unsigned *rn, int32_t *imm) { if ((insn & 0x9f000000) =3D=3D 0x91000000) { @@ -271,94 +270,6 @@ decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, uns= igned *rd, unsigned *rn, return 0; } =20 -/* Decode an opcode if it represents an ADRP instruction. - - ADDR specifies the address of the opcode. - INSN specifies the opcode to test. - RD receives the 'rd' field from the decoded instruction. - - Return 1 if the opcodes matches and is decoded, otherwise 0. */ - -static int -decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd) -{ - if (decode_masked_match (insn, 0x9f000000, 0x90000000)) - { - *rd =3D (insn >> 0) & 0x1f; - - if (aarch64_debug) - { - debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n", - core_addr_to_string_nz (addr), insn, *rd); - } - return 1; - } - return 0; -} - -/* Decode an opcode if it represents an branch immediate or branch - and link immediate instruction. - - ADDR specifies the address of the opcode. - INSN specifies the opcode to test. - IS_BL receives the 'op' bit from the decoded instruction. - OFFSET receives the immediate offset from the decoded instruction. - - Return 1 if the opcodes matches and is decoded, otherwise 0. */ - -static int -decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, int32_t *offset) -{ - /* b 0001 01ii iiii iiii iiii iiii iiii iiii */ - /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */ - if (decode_masked_match (insn, 0x7c000000, 0x14000000)) - { - *is_bl =3D (insn >> 31) & 0x1; - *offset =3D extract_signed_bitfield (insn, 26, 0) << 2; - - if (aarch64_debug) - { - debug_printf ("decode: 0x%s 0x%x %s 0x%s\n", - core_addr_to_string_nz (addr), insn, - *is_bl ? "bl" : "b", - core_addr_to_string_nz (addr + *offset)); - } - - return 1; - } - return 0; -} - -/* Decode an opcode if it represents a conditional branch instruction. - - ADDR specifies the address of the opcode. - INSN specifies the opcode to test. - COND receives the branch condition field from the decoded - instruction. - OFFSET receives the immediate offset from the decoded instruction. - - Return 1 if the opcodes matches and is decoded, otherwise 0. */ - -static int -decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, int32_t *offs= et) -{ - /* b.cond 0101 0100 iiii iiii iiii iiii iii0 cccc */ - if (decode_masked_match (insn, 0xff000010, 0x54000000)) - { - *cond =3D (insn >> 0) & 0xf; - *offset =3D extract_signed_bitfield (insn, 19, 5) << 2; - - if (aarch64_debug) - { - debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s\n", - core_addr_to_string_nz (addr), insn, *cond, - core_addr_to_string_nz (addr + *offset)); - } - return 1; - } - return 0; -} - /* Decode an opcode if it represents a branch via register instruction. =20 ADDR specifies the address of the opcode. @@ -369,7 +280,8 @@ decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *= cond, int32_t *offset) Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr, unsigned *rn) +aarch64_decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr, + unsigned *rn) { /* 8 4 0 6 2 8 4 0 */ /* blr 110101100011111100000000000rrrrr */ @@ -391,42 +303,6 @@ decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr,= unsigned *rn) return 0; } =20 -/* Decode an opcode if it represents a CBZ or CBNZ instruction. - - ADDR specifies the address of the opcode. - INSN specifies the opcode to test. - IS64 receives the 'sf' field from the decoded instruction. - IS_CBNZ receives the 'op' field from the decoded instruction. - RN receives the 'rn' field from the decoded instruction. - OFFSET receives the 'imm19' field from the decoded instruction. - - Return 1 if the opcodes matches and is decoded, otherwise 0. */ - -static int -decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz, - unsigned *rn, int32_t *offset) -{ - /* cbz T011 010o iiii iiii iiii iiii iiir rrrr */ - /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */ - if (decode_masked_match (insn, 0x7e000000, 0x34000000)) - { - *rn =3D (insn >> 0) & 0x1f; - *is64 =3D (insn >> 31) & 0x1; - *is_cbnz =3D (insn >> 24) & 0x1; - *offset =3D extract_signed_bitfield (insn, 19, 5) << 2; - - if (aarch64_debug) - { - debug_printf ("decode: 0x%s 0x%x %s 0x%s\n", - core_addr_to_string_nz (addr), insn, - *is_cbnz ? "cbnz" : "cbz", - core_addr_to_string_nz (addr + *offset)); - } - return 1; - } - return 0; -} - /* Decode an opcode if it represents a ERET instruction. =20 ADDR specifies the address of the opcode. @@ -435,7 +311,7 @@ decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, in= t *is_cbnz, Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_eret (CORE_ADDR addr, uint32_t insn) +aarch64_decode_eret (CORE_ADDR addr, uint32_t insn) { /* eret 1101 0110 1001 1111 0000 0011 1110 0000 */ if (insn =3D=3D 0xd69f03e0) @@ -459,7 +335,7 @@ decode_eret (CORE_ADDR addr, uint32_t insn) Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd) +aarch64_decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd) { if (decode_masked_match (insn, 0xff800000, 0x52800000)) { @@ -488,9 +364,9 @@ decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *r= d) Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_orr_shifted_register_x (CORE_ADDR addr, - uint32_t insn, unsigned *rd, unsigned *rn, - unsigned *rm, int32_t *imm) +aarch64_decode_orr_shifted_register_x (CORE_ADDR addr, uint32_t insn, + unsigned *rd, unsigned *rn, + unsigned *rm, int32_t *imm) { if (decode_masked_match (insn, 0xff200000, 0xaa000000)) { @@ -519,7 +395,7 @@ decode_orr_shifted_register_x (CORE_ADDR addr, Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn) +aarch64_decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn) { if (decode_masked_match (insn, 0xfffffc1f, 0xd65f0000)) { @@ -547,9 +423,8 @@ decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn) Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_stp_offset (CORE_ADDR addr, - uint32_t insn, - unsigned *rt1, unsigned *rt2, unsigned *rn, int32_t *imm) +aarch64_decode_stp_offset (CORE_ADDR addr, uint32_t insn, unsigned *rt1, + unsigned *rt2, unsigned *rn, int32_t *imm) { if (decode_masked_match (insn, 0xffc00000, 0xa9000000)) { @@ -583,10 +458,8 @@ decode_stp_offset (CORE_ADDR addr, Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_stp_offset_wb (CORE_ADDR addr, - uint32_t insn, - unsigned *rt1, unsigned *rt2, unsigned *rn, - int32_t *imm) +aarch64_decode_stp_offset_wb (CORE_ADDR addr, uint32_t insn, unsigned *rt1, + unsigned *rt2, unsigned *rn, int32_t *imm) { if (decode_masked_match (insn, 0xffc00000, 0xa9800000)) { @@ -620,8 +493,8 @@ decode_stp_offset_wb (CORE_ADDR addr, Return 1 if the opcodes matches and is decoded, otherwise 0. */ =20 static int -decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, unsigned *rt, - unsigned *rn, int32_t *imm) +aarch64_decode_stur (CORE_ADDR addr, uint32_t insn, int *is64, + unsigned *rt, unsigned *rn, int32_t *imm) { if (decode_masked_match (insn, 0xbfe00c00, 0xb8000000)) { @@ -641,42 +514,6 @@ decode_stur (CORE_ADDR addr, uint32_t insn, int *is64,= unsigned *rt, return 0; } =20 -/* Decode an opcode if it represents a TBZ or TBNZ instruction. - - ADDR specifies the address of the opcode. - INSN specifies the opcode to test. - IS_TBNZ receives the 'op' field from the decoded instruction. - BIT receives the bit position field from the decoded instruction. - RT receives 'rt' field from the decoded instruction. - IMM receives 'imm' field from the decoded instruction. - - Return 1 if the opcodes matches and is decoded, otherwise 0. */ - -static int -decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, unsigned *bit, - unsigned *rt, int32_t *imm) -{ - /* tbz b011 0110 bbbb biii iiii iiii iiir rrrr */ - /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */ - if (decode_masked_match (insn, 0x7e000000, 0x36000000)) - { - *rt =3D (insn >> 0) & 0x1f; - *is_tbnz =3D (insn >> 24) & 0x1; - *bit =3D ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f); - *imm =3D extract_signed_bitfield (insn, 14, 5) << 2; - - if (aarch64_debug) - { - debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n", - core_addr_to_string_nz (addr), insn, - *is_tbnz ? "tbnz" : "tbz", *rt, *bit, - core_addr_to_string_nz (addr + *imm)); - } - return 1; - } - return 0; -} - /* Analyze a prologue, looking for a recognizable stack frame and frame pointer. Scan until we encounter a store that could clobber the stack frame unexpectedly, or an unknown instruction. */ @@ -718,39 +555,40 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, =20 insn =3D read_memory_unsigned_integer (start, 4, byte_order_for_code= ); =20 - if (decode_add_sub_imm (start, insn, &rd, &rn, &imm)) + if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm)) regs[rd] =3D pv_add_constant (regs[rn], imm); - else if (decode_adrp (start, insn, &rd)) + else if (aarch64_decode_adrp (start, insn, &rd)) regs[rd] =3D pv_unknown (); - else if (decode_b (start, insn, &is_link, &offset)) + else if (aarch64_decode_b (start, insn, &is_link, &offset)) { /* Stop analysis on branch. */ break; } - else if (decode_bcond (start, insn, &cond, &offset)) + else if (aarch64_decode_bcond (start, insn, &cond, &offset)) { /* Stop analysis on branch. */ break; } - else if (decode_br (start, insn, &is_link, &rn)) + else if (aarch64_decode_br (start, insn, &is_link, &rn)) { /* Stop analysis on branch. */ break; } - else if (decode_cb (start, insn, &is64, &is_cbnz, &rn, &offset)) + else if (aarch64_decode_cb (start, insn, &is64, &is_cbnz, &rn, + &offset)) { /* Stop analysis on branch. */ break; } - else if (decode_eret (start, insn)) + else if (aarch64_decode_eret (start, insn)) { /* Stop analysis on branch. */ break; } - else if (decode_movz (start, insn, &rd)) + else if (aarch64_decode_movz (start, insn, &rd)) regs[rd] =3D pv_unknown (); - else - if (decode_orr_shifted_register_x (start, insn, &rd, &rn, &rm, &imm)) + else if (aarch64_decode_orr_shifted_register_x (start, insn, &rd, + &rn, &rm, &imm)) { if (imm =3D=3D 0 && rn =3D=3D 31) regs[rd] =3D regs[rm]; @@ -765,17 +603,18 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, break; } } - else if (decode_ret (start, insn, &rn)) + else if (aarch64_decode_ret (start, insn, &rn)) { /* Stop analysis on branch. */ break; } - else if (decode_stur (start, insn, &is64, &rt, &rn, &offset)) + else if (aarch64_decode_stur (start, insn, &is64, &rt, &rn, &offset)) { pv_area_store (stack, pv_add_constant (regs[rn], offset), is64 ? 8 : 4, regs[rt]); } - else if (decode_stp_offset (start, insn, &rt1, &rt2, &rn, &imm)) + else if (aarch64_decode_stp_offset (start, insn, &rt1, &rt2, &rn, + &imm)) { /* If recording this store would invalidate the store area (perhaps because rn is not known) then we should abandon @@ -793,7 +632,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8, regs[rt2]); } - else if (decode_stp_offset_wb (start, insn, &rt1, &rt2, &rn, &imm)) + else if (aarch64_decode_stp_offset_wb (start, insn, &rt1, &rt2, &rn, + &imm)) { /* If recording this store would invalidate the store area (perhaps because rn is not known) then we should abandon @@ -812,7 +652,8 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch, regs[rt2]); regs[rn] =3D pv_add_constant (regs[rn], imm); } - else if (decode_tb (start, insn, &is_tbnz, &bit, &rn, &offset)) + else if (aarch64_decode_tb (start, insn, &is_tbnz, &bit, &rn, + &offset)) { /* Stop analysis on branch. */ break; @@ -2663,7 +2504,7 @@ aarch64_software_single_step (struct frame_info *fram= e) byte_order_for_code); =20 /* Check if the instruction is a conditional branch. */ - if (decode_bcond (loc, insn, &cond, &offset)) + if (aarch64_decode_bcond (loc, insn, &cond, &offset)) { if (bc_insn_count >=3D 1) return 0; diff --git a/gdb/arch/aarch64-insn.c b/gdb/arch/aarch64-insn.c new file mode 100644 index 0000000..3a289a2 --- /dev/null +++ b/gdb/arch/aarch64-insn.c @@ -0,0 +1,218 @@ +/* Copyright (C) 2009-2015 Free Software Foundation, Inc. + Contributed by ARM Ltd. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . = */ + +#include "common-defs.h" +#include "aarch64-insn.h" + +/* Toggle this file's internal debugging dump. */ +int aarch64_debug =3D 0; + +/* Extract a signed value from a bit field within an instruction + encoding. + + INSN is the instruction opcode. + + WIDTH specifies the width of the bit field to extract (in bits). + + OFFSET specifies the least significant bit of the field where bits + are numbered zero counting from least to most significant. */ + +static int32_t +extract_signed_bitfield (uint32_t insn, unsigned width, unsigned offset) +{ + unsigned shift_l =3D sizeof (int32_t) * 8 - (offset + width); + unsigned shift_r =3D sizeof (int32_t) * 8 - width; + + return ((int32_t) insn << shift_l) >> shift_r; +} + +/* Determine if specified bits within an instruction opcode matches a + specific pattern. + + INSN is the instruction opcode. + + MASK specifies the bits within the opcode that are to be tested + agsinst for a match with PATTERN. */ + +static int +decode_masked_match (uint32_t insn, uint32_t mask, uint32_t pattern) +{ + return (insn & mask) =3D=3D pattern; +} + +/* Decode an opcode if it represents an ADRP instruction. + + ADDR specifies the address of the opcode. + INSN specifies the opcode to test. + RD receives the 'rd' 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) +{ + if (decode_masked_match (insn, 0x9f000000, 0x90000000)) + { + *rd =3D (insn >> 0) & 0x1f; + + if (aarch64_debug) + { + debug_printf ("decode: 0x%s 0x%x adrp x%u, #?\n", + core_addr_to_string_nz (addr), insn, *rd); + } + return 1; + } + return 0; +} + +/* Decode an opcode if it represents an branch immediate or branch + and link immediate instruction. + + ADDR specifies the address of the opcode. + INSN specifies the opcode to test. + IS_BL receives the 'op' bit from the decoded instruction. + OFFSET receives the immediate offset from the decoded instruction. + + Return 1 if the opcodes matches and is decoded, otherwise 0. */ + +int +aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, + int32_t *offset) +{ + /* b 0001 01ii iiii iiii iiii iiii iiii iiii */ + /* bl 1001 01ii iiii iiii iiii iiii iiii iiii */ + if (decode_masked_match (insn, 0x7c000000, 0x14000000)) + { + *is_bl =3D (insn >> 31) & 0x1; + *offset =3D extract_signed_bitfield (insn, 26, 0) << 2; + + if (aarch64_debug) + { + debug_printf ("decode: 0x%s 0x%x %s 0x%s\n", + core_addr_to_string_nz (addr), insn, + *is_bl ? "bl" : "b", + core_addr_to_string_nz (addr + *offset)); + } + + return 1; + } + return 0; +} + +/* Decode an opcode if it represents a conditional branch instruction. + + ADDR specifies the address of the opcode. + INSN specifies the opcode to test. + COND receives the branch condition field from the decoded + instruction. + OFFSET receives the immediate offset from the decoded instruction. + + Return 1 if the opcodes matches and is decoded, otherwise 0. */ + +int +aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, + int32_t *offset) +{ + /* b.cond 0101 0100 iiii iiii iiii iiii iii0 cccc */ + if (decode_masked_match (insn, 0xff000010, 0x54000000)) + { + *cond =3D (insn >> 0) & 0xf; + *offset =3D extract_signed_bitfield (insn, 19, 5) << 2; + + if (aarch64_debug) + { + debug_printf ("decode: 0x%s 0x%x b<%u> 0x%s\n", + core_addr_to_string_nz (addr), insn, *cond, + core_addr_to_string_nz (addr + *offset)); + } + return 1; + } + return 0; +} + +/* Decode an opcode if it represents a CBZ or CBNZ instruction. + + ADDR specifies the address of the opcode. + INSN specifies the opcode to test. + IS64 receives the 'sf' field from the decoded instruction. + IS_CBNZ receives the 'op' field from the decoded instruction. + RN receives the 'rn' field from the decoded instruction. + OFFSET receives the 'imm19' field from the decoded instruction. + + Return 1 if the opcodes matches and is decoded, otherwise 0. */ + +int +aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz, + unsigned *rn, int32_t *offset) +{ + /* cbz T011 010o iiii iiii iiii iiii iiir rrrr */ + /* cbnz T011 010o iiii iiii iiii iiii iiir rrrr */ + if (decode_masked_match (insn, 0x7e000000, 0x34000000)) + { + *rn =3D (insn >> 0) & 0x1f; + *is64 =3D (insn >> 31) & 0x1; + *is_cbnz =3D (insn >> 24) & 0x1; + *offset =3D extract_signed_bitfield (insn, 19, 5) << 2; + + if (aarch64_debug) + { + debug_printf ("decode: 0x%s 0x%x %s 0x%s\n", + core_addr_to_string_nz (addr), insn, + *is_cbnz ? "cbnz" : "cbz", + core_addr_to_string_nz (addr + *offset)); + } + return 1; + } + return 0; +} + +/* Decode an opcode if it represents a TBZ or TBNZ instruction. + + ADDR specifies the address of the opcode. + INSN specifies the opcode to test. + IS_TBNZ receives the 'op' field from the decoded instruction. + BIT receives the bit position field from the decoded instruction. + RT receives 'rt' field from the decoded instruction. + IMM receives 'imm' field from the decoded instruction. + + Return 1 if the opcodes matches and is decoded, otherwise 0. */ + +int +aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, + unsigned *bit, unsigned *rt, int32_t *imm) +{ + /* tbz b011 0110 bbbb biii iiii iiii iiir rrrr */ + /* tbnz B011 0111 bbbb biii iiii iiii iiir rrrr */ + if (decode_masked_match (insn, 0x7e000000, 0x36000000)) + { + *rt =3D (insn >> 0) & 0x1f; + *is_tbnz =3D (insn >> 24) & 0x1; + *bit =3D ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f); + *imm =3D extract_signed_bitfield (insn, 14, 5) << 2; + + if (aarch64_debug) + { + debug_printf ("decode: 0x%s 0x%x %s x%u, #%u, 0x%s\n", + core_addr_to_string_nz (addr), insn, + *is_tbnz ? "tbnz" : "tbz", *rt, *bit, + core_addr_to_string_nz (addr + *imm)); + } + return 1; + } + return 0; +} diff --git a/gdb/arch/aarch64-insn.h b/gdb/arch/aarch64-insn.h new file mode 100644 index 0000000..7775a34 --- /dev/null +++ b/gdb/arch/aarch64-insn.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2009-2015 Free Software Foundation, Inc. + Contributed by ARM Ltd. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . = */ + +#ifndef AARCH64_INSN_H +#define AARCH64_INSN_H 1 + +extern int aarch64_debug; + +int aarch64_decode_adrp (CORE_ADDR addr, uint32_t insn, unsigned *rd); + +int aarch64_decode_b (CORE_ADDR addr, uint32_t insn, int *is_bl, + int32_t *offset); + +int aarch64_decode_bcond (CORE_ADDR addr, uint32_t insn, unsigned *cond, + int32_t *offset); + +int aarch64_decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, + int *is_cbnz, unsigned *rn, int32_t *offset); + +int aarch64_decode_tb (CORE_ADDR addr, uint32_t insn, int *is_tbnz, + unsigned *bit, unsigned *rt, int32_t *imm); + +#endif diff --git a/gdb/configure.tgt b/gdb/configure.tgt index c42b4df..33d4cfc 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -38,12 +38,12 @@ esac case "${targ}" in aarch64*-*-elf) # Target: AArch64 embedded system - gdb_target_obs=3D"aarch64-tdep.o aarch64-newlib-tdep.o" + gdb_target_obs=3D"aarch64-tdep.o aarch64-newlib-tdep.o aarch64-insn.o" ;; =20 aarch64*-*-linux*) # Target: AArch64 linux - gdb_target_obs=3D"aarch64-tdep.o aarch64-linux-tdep.o \ + gdb_target_obs=3D"aarch64-tdep.o aarch64-linux-tdep.o aarch64-insn.o \ arm-tdep.o arm-linux-tdep.o \ glibc-tdep.o linux-tdep.o solib-svr4.o \ symfile-mem.o linux-record.o" diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index b715a32..d096663 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -625,6 +625,12 @@ linux-namespaces.o: ../nat/linux-namespaces.c $(COMPILE) $< $(POSTCOMPILE) =20 +# Architecture specific object files rules from ../arch + +aarch64-insn.o: ../arch/aarch64-insn.c + $(COMPILE) $< + $(POSTCOMPILE) + aarch64.c : $(srcdir)/../regformats/aarch64.dat $(regdat_sh) $(SHELL) $(regdat_sh) $(srcdir)/../regformats/aarch64.dat aarch64.c reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh) diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index aa232f8..a62df83 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -53,6 +53,7 @@ case "${target}" in srv_tgtobj=3D"linux-aarch64-low.o aarch64-linux-hw-point.o" srv_tgtobj=3D"$srv_tgtobj linux-aarch32-low.o" srv_tgtobj=3D"$srv_tgtobj aarch64-linux.o" + srv_tgtobj=3D"$srv_tgtobj aarch64-insn.o" srv_tgtobj=3D"${srv_tgtobj} $srv_linux_obj" srv_xmlfiles=3D"aarch64.xml" srv_xmlfiles=3D"${srv_xmlfiles} aarch64-core.xml" --=20 2.4.6