diff options
Diffstat (limited to 'gdb/arm-tdep.c')
-rw-r--r-- | gdb/arm-tdep.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index b4d2211..325bd80 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -1664,7 +1664,7 @@ thumb_get_next_pc (struct frame_info *frame, CORE_ADDR pc) return nextpc; } -static CORE_ADDR +CORE_ADDR arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc) { unsigned long pc_val; @@ -1680,7 +1680,30 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc) status = get_frame_register_unsigned (frame, ARM_PS_REGNUM); nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */ - if (condition_true (bits (this_instr, 28, 31), status)) + if (bits (this_instr, 28, 31) == INST_NV) + switch (bits (this_instr, 24, 27)) + { + case 0xa: + case 0xb: + { + /* Branch with Link and change to Thumb. */ + nextpc = BranchDest (pc, this_instr); + nextpc |= bit (this_instr, 24) << 1; + + nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc); + if (nextpc == pc) + error (_("Infinite loop detected")); + break; + } + case 0xc: + case 0xd: + case 0xe: + /* Coprocessor register transfer. */ + if (bits (this_instr, 12, 15) == 15) + error (_("Invalid update to pc in instruction")); + break; + } + else if (condition_true (bits (this_instr, 28, 31), status)) { switch (bits (this_instr, 24, 27)) { @@ -1886,10 +1909,6 @@ arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc) { nextpc = BranchDest (pc, this_instr); - /* BLX */ - if (bits (this_instr, 28, 31) == INST_NV) - nextpc |= bit (this_instr, 24) << 1; - nextpc = gdbarch_addr_bits_remove (current_gdbarch, nextpc); if (nextpc == pc) error (_("Infinite loop detected")); |