Use aarch64_decode_insn in aarch64_analyze_prologue
This patch convert aarch64_analyze_prologue to using aarch64_decode_insn to decode instructions. After this change, aarch64_analyze_prologue looks much simple, and some aarch64_decode_* functions are removed accordingly. gdb: 2015-11-05 Yao Qi <yao.qi@linaro.org> * aarch64-tdep.c (extract_signed_bitfield): Remove. (decode_masked_match): Remove. (aarch64_decode_add_sub_imm): Remove. (aarch64_decode_br): Remove. (aarch64_decode_eret): Remove. (aarch64_decode_movz): Remove. (aarch64_decode_orr_shifted_register_x): Remove. (aarch64_decode_ret): Remove. (aarch64_decode_stp_offset): Remove. (aarch64_decode_stur): Remove. (aarch64_analyze_prologue): Call aarch64_decode_insn and use aarch64_inst to decode instructions.
This commit is contained in:
parent
93d960127c
commit
d9ebcbce29
|
@ -1,3 +1,18 @@
|
||||||
|
2015-11-05 Yao Qi <yao.qi@linaro.org>
|
||||||
|
|
||||||
|
* aarch64-tdep.c (extract_signed_bitfield): Remove.
|
||||||
|
(decode_masked_match): Remove.
|
||||||
|
(aarch64_decode_add_sub_imm): Remove.
|
||||||
|
(aarch64_decode_br): Remove.
|
||||||
|
(aarch64_decode_eret): Remove.
|
||||||
|
(aarch64_decode_movz): Remove.
|
||||||
|
(aarch64_decode_orr_shifted_register_x): Remove.
|
||||||
|
(aarch64_decode_ret): Remove.
|
||||||
|
(aarch64_decode_stp_offset): Remove.
|
||||||
|
(aarch64_decode_stur): Remove.
|
||||||
|
(aarch64_analyze_prologue): Call aarch64_decode_insn
|
||||||
|
and use aarch64_inst to decode instructions.
|
||||||
|
|
||||||
2015-11-05 Yao Qi <yao.qi@linaro.org>
|
2015-11-05 Yao Qi <yao.qi@linaro.org>
|
||||||
|
|
||||||
* aarch64-tdep.c (aarch64_decode_stp_offset): New argument
|
* aarch64-tdep.c (aarch64_decode_stp_offset): New argument
|
||||||
|
|
|
@ -194,302 +194,6 @@ show_aarch64_debug (struct ui_file *file, int from_tty,
|
||||||
fprintf_filtered (file, _("AArch64 debugging is %s.\n"), value);
|
fprintf_filtered (file, _("AArch64 debugging is %s.\n"), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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 immediate ADD or SUB instruction.
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
RD receives the 'rd' field from the decoded instruction.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
static int
|
|
||||||
aarch64_decode_add_sub_imm (CORE_ADDR addr, uint32_t insn, unsigned *rd,
|
|
||||||
unsigned *rn, int32_t *imm)
|
|
||||||
{
|
|
||||||
if ((insn & 0x9f000000) == 0x91000000)
|
|
||||||
{
|
|
||||||
unsigned shift;
|
|
||||||
unsigned op_is_sub;
|
|
||||||
|
|
||||||
*rd = (insn >> 0) & 0x1f;
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
*imm = (insn >> 10) & 0xfff;
|
|
||||||
shift = (insn >> 22) & 0x3;
|
|
||||||
op_is_sub = (insn >> 30) & 0x1;
|
|
||||||
|
|
||||||
switch (shift)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*imm <<= 12;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* UNDEFINED */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (op_is_sub)
|
|
||||||
*imm = -*imm;
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x add x%u, x%u, #%d\n",
|
|
||||||
core_addr_to_string_nz (addr), insn, *rd, *rn,
|
|
||||||
*imm);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents a branch via register instruction.
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
IS_BLR receives the 'op' bit from the decoded instruction.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
aarch64_decode_br (CORE_ADDR addr, uint32_t insn, int *is_blr,
|
|
||||||
unsigned *rn)
|
|
||||||
{
|
|
||||||
/* 8 4 0 6 2 8 4 0 */
|
|
||||||
/* blr 110101100011111100000000000rrrrr */
|
|
||||||
/* br 110101100001111100000000000rrrrr */
|
|
||||||
if (decode_masked_match (insn, 0xffdffc1f, 0xd61f0000))
|
|
||||||
{
|
|
||||||
*is_blr = (insn >> 21) & 1;
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x %s 0x%x\n",
|
|
||||||
core_addr_to_string_nz (addr), insn,
|
|
||||||
*is_blr ? "blr" : "br", *rn);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents a ERET instruction.
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
aarch64_decode_eret (CORE_ADDR addr, uint32_t insn)
|
|
||||||
{
|
|
||||||
/* eret 1101 0110 1001 1111 0000 0011 1110 0000 */
|
|
||||||
if (insn == 0xd69f03e0)
|
|
||||||
{
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x eret\n",
|
|
||||||
core_addr_to_string_nz (addr), insn);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents a MOVZ 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
|
|
||||||
aarch64_decode_movz (CORE_ADDR addr, uint32_t insn, unsigned *rd)
|
|
||||||
{
|
|
||||||
if (decode_masked_match (insn, 0xff800000, 0x52800000))
|
|
||||||
{
|
|
||||||
*rd = (insn >> 0) & 0x1f;
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x movz x%u, #?\n",
|
|
||||||
core_addr_to_string_nz (addr), insn, *rd);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents a ORR (shifted register)
|
|
||||||
instruction.
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
RD receives the 'rd' field from the decoded instruction.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
RM receives the 'rm' field from the decoded instruction.
|
|
||||||
IMM receives the 'imm6' field from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
*rd = (insn >> 0) & 0x1f;
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
*rm = (insn >> 16) & 0x1f;
|
|
||||||
*imm = (insn >> 10) & 0x3f;
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x orr x%u, x%u, x%u, #%u\n",
|
|
||||||
core_addr_to_string_nz (addr), insn, *rd, *rn,
|
|
||||||
*rm, *imm);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents a RET instruction.
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
aarch64_decode_ret (CORE_ADDR addr, uint32_t insn, unsigned *rn)
|
|
||||||
{
|
|
||||||
if (decode_masked_match (insn, 0xfffffc1f, 0xd65f0000))
|
|
||||||
{
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x ret x%u\n",
|
|
||||||
core_addr_to_string_nz (addr), insn, *rn);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents the following instructions:
|
|
||||||
|
|
||||||
STP rt, rt2, [rn, #imm]
|
|
||||||
STP rt, rt2, [rn, #imm]!
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
RT1 receives the 'rt' field from the decoded instruction.
|
|
||||||
RT2 receives the 'rt2' field from the decoded instruction.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
IMM receives the 'imm' field from the decoded instruction.
|
|
||||||
*WBACK receives the bit 23 from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
aarch64_decode_stp_offset (CORE_ADDR addr, uint32_t insn, unsigned *rt1,
|
|
||||||
unsigned *rt2, unsigned *rn, int32_t *imm,
|
|
||||||
int *wback)
|
|
||||||
{
|
|
||||||
if (decode_masked_match (insn, 0xff400000, 0xa9000000))
|
|
||||||
{
|
|
||||||
*rt1 = (insn >> 0) & 0x1f;
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
*rt2 = (insn >> 10) & 0x1f;
|
|
||||||
*imm = extract_signed_bitfield (insn, 7, 15);
|
|
||||||
*imm <<= 3;
|
|
||||||
*wback = bit (insn, 23);
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x stp x%u, x%u, [x%u + #%d]%s\n",
|
|
||||||
core_addr_to_string_nz (addr), insn, *rt1, *rt2,
|
|
||||||
*rn, *imm, *wback ? "" : "!");
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Decode an opcode if it represents the following instruction:
|
|
||||||
STUR rt, [rn, #imm]
|
|
||||||
|
|
||||||
ADDR specifies the address of the opcode.
|
|
||||||
INSN specifies the opcode to test.
|
|
||||||
IS64 receives size field from the decoded instruction.
|
|
||||||
RT receives the 'rt' field from the decoded instruction.
|
|
||||||
RN receives the 'rn' field from the decoded instruction.
|
|
||||||
IMM receives the 'imm' field from the decoded instruction.
|
|
||||||
|
|
||||||
Return 1 if the opcodes matches and is decoded, otherwise 0. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
*is64 = (insn >> 30) & 1;
|
|
||||||
*rt = (insn >> 0) & 0x1f;
|
|
||||||
*rn = (insn >> 5) & 0x1f;
|
|
||||||
*imm = extract_signed_bitfield (insn, 9, 12);
|
|
||||||
|
|
||||||
if (aarch64_debug)
|
|
||||||
{
|
|
||||||
debug_printf ("decode: 0x%s 0x%x stur %c%u, [x%u + #%d]\n",
|
|
||||||
core_addr_to_string_nz (addr), insn,
|
|
||||||
*is64 ? 'x' : 'w', *rt, *rn, *imm);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Analyze a prologue, looking for a recognizable stack frame
|
/* Analyze a prologue, looking for a recognizable stack frame
|
||||||
and frame pointer. Scan until we encounter a store that could
|
and frame pointer. Scan until we encounter a store that could
|
||||||
clobber the stack frame unexpectedly, or an unknown instruction. */
|
clobber the stack frame unexpectedly, or an unknown instruction. */
|
||||||
|
@ -513,63 +217,82 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
|
||||||
for (; start < limit; start += 4)
|
for (; start < limit; start += 4)
|
||||||
{
|
{
|
||||||
uint32_t insn;
|
uint32_t insn;
|
||||||
unsigned rd;
|
aarch64_inst inst;
|
||||||
unsigned rn;
|
|
||||||
unsigned rm;
|
|
||||||
unsigned rt;
|
|
||||||
unsigned rt1;
|
|
||||||
unsigned rt2;
|
|
||||||
int op_is_sub;
|
|
||||||
int wback;
|
|
||||||
int32_t imm;
|
|
||||||
unsigned cond;
|
|
||||||
int is64;
|
|
||||||
int is_link;
|
|
||||||
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);
|
insn = read_memory_unsigned_integer (start, 4, byte_order_for_code);
|
||||||
|
|
||||||
if (aarch64_decode_add_sub_imm (start, insn, &rd, &rn, &imm))
|
if (aarch64_decode_insn (insn, &inst, 1) != 0)
|
||||||
regs[rd] = pv_add_constant (regs[rn], imm);
|
break;
|
||||||
else if (aarch64_decode_adr (start, insn, &is_adrp, &rd, &offset)
|
|
||||||
&& is_adrp)
|
if (inst.opcode->iclass == addsub_imm
|
||||||
regs[rd] = pv_unknown ();
|
&& (inst.opcode->op == OP_ADD
|
||||||
else if (aarch64_decode_b (start, insn, &is_link, &offset))
|
|| strcmp ("sub", inst.opcode->name) == 0))
|
||||||
|
{
|
||||||
|
unsigned rd = inst.operands[0].reg.regno;
|
||||||
|
unsigned rn = inst.operands[1].reg.regno;
|
||||||
|
|
||||||
|
gdb_assert (aarch64_num_of_operands (inst.opcode) == 3);
|
||||||
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rd_SP);
|
||||||
|
gdb_assert (inst.operands[1].type == AARCH64_OPND_Rn_SP);
|
||||||
|
gdb_assert (inst.operands[2].type == AARCH64_OPND_AIMM);
|
||||||
|
|
||||||
|
if (inst.opcode->op == OP_ADD)
|
||||||
|
{
|
||||||
|
regs[rd] = pv_add_constant (regs[rn],
|
||||||
|
inst.operands[2].imm.value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regs[rd] = pv_add_constant (regs[rn],
|
||||||
|
-inst.operands[2].imm.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (inst.opcode->iclass == pcreladdr
|
||||||
|
&& inst.operands[1].type == AARCH64_OPND_ADDR_ADRP)
|
||||||
|
{
|
||||||
|
gdb_assert (aarch64_num_of_operands (inst.opcode) == 2);
|
||||||
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rd);
|
||||||
|
|
||||||
|
regs[inst.operands[0].reg.regno] = pv_unknown ();
|
||||||
|
}
|
||||||
|
else if (inst.opcode->iclass == branch_imm)
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
/* Stop analysis on branch. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_bcond (start, insn, &cond, &offset))
|
else if (inst.opcode->iclass == condbranch)
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
/* Stop analysis on branch. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_br (start, insn, &is_link, &rn))
|
else if (inst.opcode->iclass == branch_reg)
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
/* Stop analysis on branch. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_cb (start, insn, &is64, &is_cbnz, &rn,
|
else if (inst.opcode->iclass == compbranch)
|
||||||
&offset))
|
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
/* Stop analysis on branch. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_eret (start, insn))
|
else if (inst.opcode->op == OP_MOVZ)
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rd);
|
||||||
break;
|
regs[inst.operands[0].reg.regno] = pv_unknown ();
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_movz (start, insn, &rd))
|
else if (inst.opcode->iclass == log_shift
|
||||||
regs[rd] = pv_unknown ();
|
&& strcmp (inst.opcode->name, "orr") == 0)
|
||||||
else if (aarch64_decode_orr_shifted_register_x (start, insn, &rd,
|
|
||||||
&rn, &rm, &imm))
|
|
||||||
{
|
{
|
||||||
if (imm == 0 && rn == 31)
|
unsigned rd = inst.operands[0].reg.regno;
|
||||||
|
unsigned rn = inst.operands[1].reg.regno;
|
||||||
|
unsigned rm = inst.operands[2].reg.regno;
|
||||||
|
|
||||||
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rd);
|
||||||
|
gdb_assert (inst.operands[1].type == AARCH64_OPND_Rn);
|
||||||
|
gdb_assert (inst.operands[2].type == AARCH64_OPND_Rm_SFT);
|
||||||
|
|
||||||
|
if (inst.operands[2].shifter.amount == 0
|
||||||
|
&& rn == AARCH64_SP_REGNUM)
|
||||||
regs[rd] = regs[rm];
|
regs[rd] = regs[rm];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -582,19 +305,37 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_ret (start, insn, &rn))
|
else if (inst.opcode->op == OP_STUR)
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
unsigned rt = inst.operands[0].reg.regno;
|
||||||
break;
|
unsigned rn = inst.operands[1].addr.base_regno;
|
||||||
}
|
int is64
|
||||||
else if (aarch64_decode_stur (start, insn, &is64, &rt, &rn, &offset))
|
= (aarch64_get_qualifier_esize (inst.operands[0].qualifier) == 8);
|
||||||
{
|
|
||||||
pv_area_store (stack, pv_add_constant (regs[rn], offset),
|
gdb_assert (aarch64_num_of_operands (inst.opcode) == 2);
|
||||||
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt);
|
||||||
|
gdb_assert (inst.operands[1].type == AARCH64_OPND_ADDR_SIMM9);
|
||||||
|
gdb_assert (!inst.operands[1].addr.offset.is_reg);
|
||||||
|
|
||||||
|
pv_area_store (stack, pv_add_constant (regs[rn],
|
||||||
|
inst.operands[1].addr.offset.imm),
|
||||||
is64 ? 8 : 4, regs[rt]);
|
is64 ? 8 : 4, regs[rt]);
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_stp_offset (start, insn, &rt1, &rt2, &rn,
|
else if ((inst.opcode->iclass == ldstpair_off
|
||||||
&imm, &wback))
|
|| inst.opcode->iclass == ldstpair_indexed)
|
||||||
|
&& inst.operands[2].addr.preind
|
||||||
|
&& strcmp ("stp", inst.opcode->name) == 0)
|
||||||
{
|
{
|
||||||
|
unsigned rt1 = inst.operands[0].reg.regno;
|
||||||
|
unsigned rt2 = inst.operands[1].reg.regno;
|
||||||
|
unsigned rn = inst.operands[2].addr.base_regno;
|
||||||
|
int32_t imm = inst.operands[2].addr.offset.imm;
|
||||||
|
|
||||||
|
gdb_assert (inst.operands[0].type == AARCH64_OPND_Rt);
|
||||||
|
gdb_assert (inst.operands[1].type == AARCH64_OPND_Rt2);
|
||||||
|
gdb_assert (inst.operands[2].type == AARCH64_OPND_ADDR_SIMM7);
|
||||||
|
gdb_assert (!inst.operands[2].addr.offset.is_reg);
|
||||||
|
|
||||||
/* If recording this store would invalidate the store area
|
/* If recording this store would invalidate the store area
|
||||||
(perhaps because rn is not known) then we should abandon
|
(perhaps because rn is not known) then we should abandon
|
||||||
further prologue analysis. */
|
further prologue analysis. */
|
||||||
|
@ -611,12 +352,11 @@ aarch64_analyze_prologue (struct gdbarch *gdbarch,
|
||||||
pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
|
pv_area_store (stack, pv_add_constant (regs[rn], imm + 8), 8,
|
||||||
regs[rt2]);
|
regs[rt2]);
|
||||||
|
|
||||||
if (wback)
|
if (inst.operands[2].addr.writeback)
|
||||||
regs[rn] = pv_add_constant (regs[rn], imm);
|
regs[rn] = pv_add_constant (regs[rn], imm);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (aarch64_decode_tb (start, insn, &is_tbnz, &bit, &rn,
|
else if (inst.opcode->iclass == testbranch)
|
||||||
&offset))
|
|
||||||
{
|
{
|
||||||
/* Stop analysis on branch. */
|
/* Stop analysis on branch. */
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue