This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] Fix TBB TBH decoding in Thumb-2
- From: Richard Earnshaw <Richard dot Earnshaw at buzzard dot freeserve dot co dot uk>
- To: gdb-patches at sourceware dot org
- Date: Wed, 31 Mar 2010 23:13:20 +0100
- Subject: [PATCH] Fix TBB TBH decoding in Thumb-2
I discovered today that the TBB and TBH instructions weren't being
correctly decoded when single-stepping thumb-2 code. It turned out to
be two problems. Firstly TBH was being incorrectly tested for (actually
matching a TBB opcode. Secondly, both TBB and TBH were using the wrong
base address for the jump when the base register was the PC (using the
current PC value rather than PC+4).
Fixed thusly:
2010-03-31 Richard Earnshaw <rearnsha@arm.com>
* arm-tdep.c (thumb_get_next_pc_raw): Correctly detect TBH
instructions. Use the PC+4 if the base of the TBB or TBH is the
PC register.
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.301
diff -p -r1.301 arm-tdep.c
*** arm-tdep.c 24 Mar 2010 20:23:13 -0000 1.301
--- arm-tdep.c 31 Mar 2010 22:07:34 -0000
*************** thumb_get_next_pc_raw (struct frame_info
*** 2959,2977 ****
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
{
/* TBB. */
! CORE_ADDR table, offset, length;
- table = get_frame_register_unsigned (frame, bits (inst1, 0, 3));
offset = get_frame_register_unsigned (frame, bits (inst2, 0, 3));
length = 2 * get_frame_memory_unsigned (frame, table + offset, 1);
nextpc = pc_val + length;
}
! else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
{
/* TBH. */
! CORE_ADDR table, offset, length;
- table = get_frame_register_unsigned (frame, bits (inst1, 0, 3));
offset = 2 * get_frame_register_unsigned (frame, bits (inst2, 0, 3));
length = 2 * get_frame_memory_unsigned (frame, table + offset, 2);
nextpc = pc_val + length;
--- 2959,2987 ----
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
{
/* TBB. */
! CORE_ADDR tbl_reg, table, offset, length;
!
! tbl_reg = bits (inst1, 0, 3);
! if (tbl_reg == 0x0f)
! table = pc + 4; /* Regcache copy of PC isn't right yet. */
! else
! table = get_frame_register_unsigned (frame, tbl_reg);
offset = get_frame_register_unsigned (frame, bits (inst2, 0, 3));
length = 2 * get_frame_memory_unsigned (frame, table + offset, 1);
nextpc = pc_val + length;
}
! else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
{
/* TBH. */
! CORE_ADDR tbl_reg, table, offset, length;
!
! tbl_reg = bits (inst1, 0, 3);
! if (tbl_reg == 0x0f)
! table = pc + 4; /* Regcache copy of PC isn't right yet. */
! else
! table = get_frame_register_unsigned (frame, tbl_reg);
offset = 2 * get_frame_register_unsigned (frame, bits (inst2, 0, 3));
length = 2 * get_frame_memory_unsigned (frame, table + offset, 2);
nextpc = pc_val + length;