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:
parent
9812b2e607
commit
787749ead6
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue