Make aarch64_decode_adrp handle both ADR and ADRP instructions

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.
This commit is contained in:
Pierre Langlois 2015-09-21 15:01:04 +01:00 committed by Yao Qi
parent 787749ead6
commit 6ec5f4be05
4 changed files with 40 additions and 7 deletions

View File

@ -1,3 +1,14 @@
2015-09-21 Pierre Langlois <pierre.langlois@arm.com>
* 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.
2015-09-21 Pierre Langlois <pierre.langlois@arm.com>
* Makefile.in (ALL_64_TARGET_OBS): Add aarch64-insn.o.

View File

@ -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))
{

View File

@ -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;
}

View File

@ -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);