mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-26 09:08:59 +00:00
gdb: LoongArch: Add and use cond_branch_destination_address()
In the current loongarch_deal_with_atomic_sequence(), it is just a loop through a ll/sc atomic instruction sequence, the instructions before the condition branch are not actually executed, thus the condition register value is not proper to determine the destination address. Add a new function cond_branch_destination_address() to calculate the destination address of a condition branch instruction under an assumed true condition, then only put a breakpoint at this address when it is outside of the ll/sc atomic instruction sequence. Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
This commit is contained in:
@@ -427,6 +427,39 @@ loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc)
|
||||
return next_pc;
|
||||
}
|
||||
|
||||
/* Calculate the destination address of a condition branch instruction under an
|
||||
assumed true condition */
|
||||
|
||||
static CORE_ADDR
|
||||
cond_branch_destination_address (CORE_ADDR cur_pc, insn_t insn)
|
||||
{
|
||||
size_t insn_len = loongarch_insn_length (insn);
|
||||
CORE_ADDR next_pc = cur_pc + insn_len;
|
||||
|
||||
if ((insn & 0xfc000000) == 0x58000000) /* beq rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x5c000000) /* bne rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x60000000) /* blt rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x64000000) /* bge rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x68000000) /* bltu rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x6c000000) /* bgeu rj, rd, offs16 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x40000000) /* beqz rj, offs21 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000000) == 0x44000000) /* bnez rj, offs21 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000300) == 0x48000000) /* bceqz cj, offs21 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
|
||||
else if ((insn & 0xfc000300) == 0x48000100) /* bcnez cj, offs21 */
|
||||
next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
|
||||
|
||||
return next_pc;
|
||||
}
|
||||
|
||||
/* We can't put a breakpoint in the middle of a ll/sc atomic sequence,
|
||||
so look for the end of the sequence and put the breakpoint there. */
|
||||
|
||||
@@ -459,7 +492,7 @@ loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR cur_pc
|
||||
which is outside of the ll/sc atomic instruction sequence. */
|
||||
else if (loongarch_insn_is_cond_branch (insn))
|
||||
{
|
||||
next_pc = loongarch_next_pc (regcache, cur_pc);
|
||||
next_pc = cond_branch_destination_address (cur_pc, insn);
|
||||
if (next_pc != cur_pc + insn_len)
|
||||
next_pcs.push_back (next_pc);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user