Move instruction decoding into new arch/ directory

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.

V2:
 make sure the formatting issues propagated
 fix `gdbserver/configure.srv'.

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:

	* Makefile.in (aarch64-insn.o): New rule.
	* configure.srv (aarch64*-*-linux*): Add aarch64-insn.o.
This commit is contained in:
Pierre Langlois 2015-09-21 15:01:04 +01:00 committed by Yao Qi
parent 9812b2e607
commit 787749ead6
9 changed files with 366 additions and 201 deletions

View File

@ -1,3 +1,50 @@
2015-09-21 Pierre Langlois <pierre.langlois@arm.com>
* 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.
2015-09-20 Doug Evans <xdje42@gmail.com>
* dwarf2read.c (add_partial_symbol): Remove outdated comments.

View File

@ -644,7 +644,7 @@ TARGET_OBS = @TARGET_OBS@
# All target-dependent objects files that require 64-bit CORE_ADDR
# (used with --enable-targets=all --enable-64-bit-bfd).
ALL_64_TARGET_OBS = \
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_setjmp.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
# Header files that already have srcdir in them, or which are in objdir.
@ -2336,6 +2336,15 @@ aarch64-linux.o: ${srcdir}/nat/aarch64-linux.c
$(COMPILE) $(srcdir)/nat/aarch64-linux.c
$(POSTCOMPILE)
# 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
#

View File

@ -57,6 +57,8 @@
#include "features/aarch64.c"
#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;
};
/* 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, uint32_t pattern)
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) == 0x91000000)
{
@ -271,94 +270,6 @@ decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd, unsigned *rn,
return 0;
}
/* 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 = (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 = (insn >> 31) & 0x1;
*offset = 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 *offset)
{
/* b.cond 0101 0100 iiii iiii iiii iiii iii0 cccc */
if (decode_masked_match (insn, 0xff000010, 0x54000000))
{
*cond = (insn >> 0) & 0xf;
*offset = 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.
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. */
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;
}
/* 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 = (insn >> 0) & 0x1f;
*is64 = (insn >> 31) & 0x1;
*is_cbnz = (insn >> 24) & 0x1;
*offset = 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.
ADDR specifies the address of the opcode.
@ -435,7 +311,7 @@ decode_cb (CORE_ADDR addr, uint32_t insn, int *is64, int *is_cbnz,
Return 1 if the opcodes matches and is decoded, otherwise 0. */
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 == 0xd69f03e0)
@ -459,7 +335,7 @@ decode_eret (CORE_ADDR addr, uint32_t insn)
Return 1 if the opcodes matches and is decoded, otherwise 0. */
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 *rd)
Return 1 if the opcodes matches and is decoded, otherwise 0. */
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. */
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. */
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. */
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. */
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;
}
/* 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 = (insn >> 0) & 0x1f;
*is_tbnz = (insn >> 24) & 0x1;
*bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
*imm = 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,
insn = read_memory_unsigned_integer (start, 4, byte_order_for_code);
if (decode_add_sub_imm (start, insn, &rd, &rn, &imm))
if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm))
regs[rd] = pv_add_constant (regs[rn], imm);
else if (decode_adrp (start, insn, &rd))
else if (aarch64_decode_adrp (start, insn, &rd))
regs[rd] = 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] = 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 == 0 && rn == 31)
regs[rd] = 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] = 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 *frame)
byte_order_for_code);
/* 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 >= 1)
return 0;

218
gdb/arch/aarch64-insn.c Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#include "common-defs.h"
#include "aarch64-insn.h"
/* Toggle this file's internal debugging dump. */
int aarch64_debug = 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 = sizeof (int32_t) * 8 - (offset + width);
unsigned shift_r = 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) == 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 = (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 = (insn >> 31) & 0x1;
*offset = 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 = (insn >> 0) & 0xf;
*offset = 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 = (insn >> 0) & 0x1f;
*is64 = (insn >> 31) & 0x1;
*is_cbnz = (insn >> 24) & 0x1;
*offset = 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 = (insn >> 0) & 0x1f;
*is_tbnz = (insn >> 24) & 0x1;
*bit = ((insn >> (31 - 4)) & 0x20) | ((insn >> 19) & 0x1f);
*imm = 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;
}

38
gdb/arch/aarch64-insn.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>. */
#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

View File

@ -38,12 +38,12 @@ esac
case "${targ}" in
aarch64*-*-elf)
# Target: AArch64 embedded system
gdb_target_obs="aarch64-tdep.o aarch64-newlib-tdep.o"
gdb_target_obs="aarch64-tdep.o aarch64-newlib-tdep.o aarch64-insn.o"
;;
aarch64*-*-linux*)
# Target: AArch64 linux
gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o \
gdb_target_obs="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"

View File

@ -1,3 +1,8 @@
2015-09-21 Pierre Langlois <pierre.langlois@arm.com>
* Makefile.in (aarch64-insn.o): New rule.
* configure.srv (aarch64*-*-linux*): Add aarch64-insn.o.
2015-09-21 Yao Qi <yao.qi@linaro.org>
* ax.c [!IN_PROCESS_AGENT] (gdb_agent_op_sizes): Define it.

View File

@ -625,6 +625,12 @@ linux-namespaces.o: ../nat/linux-namespaces.c
$(COMPILE) $<
$(POSTCOMPILE)
# 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)

View File

@ -53,6 +53,7 @@ case "${target}" in
srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o"
srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
srv_tgtobj="$srv_tgtobj aarch64-linux.o"
srv_tgtobj="$srv_tgtobj aarch64-insn.o"
srv_tgtobj="${srv_tgtobj} $srv_linux_obj"
srv_xmlfiles="aarch64.xml"
srv_xmlfiles="${srv_xmlfiles} aarch64-core.xml"