mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-27 22:10:32 +00:00
Handle sparc compare-and-branch
SPARC-T4 adds a "compare and branch" instruction which fuses a compare and a branch instruction into one. The branch is non-delayed, there are no anulling facilities, and the displacement is 10-bits. This also corrects the existing bit test for Branch on Integer Register. The distinguising characteristic between Branch on Integer Register and Compare-and-Branch is bit 28. The existing code was checking bit 24 for zero, but that's pointless because bit 24 is already covered by the "X_OP2 (insn) == 3" test. gdb/ * sparc-tdep.c (X_DISP10): Define. (sparc_analyze_control_transfer): Handle compare-and-branch.
This commit is contained in:
parent
4272ccafdd
commit
8d1b3521db
@ -1,3 +1,8 @@
|
||||
2012-04-21 David S. Miller <davem@davemloft.net>
|
||||
|
||||
* sparc-tdep.c (X_DISP10): Define.
|
||||
(sparc_analyze_control_transfer): Handle compare-and-branch.
|
||||
|
||||
2012-04-21 Jonathan Larmour <jifl@eCosCentric.com>
|
||||
|
||||
* features/Makefile (WHICH): Add arm-with-m and arm-with-m-fpa-layout.
|
||||
|
@ -85,6 +85,7 @@ struct regset;
|
||||
/* Sign extension macros. */
|
||||
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
|
||||
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
|
||||
#define X_DISP10(i) ((((((i) >> 11) && 0x300) | (((i) >> 5) & 0xff)) ^ 0x200) - 0x200)
|
||||
#define X_SIMM13(i) ((((i) & 0x1fff) ^ 0x1000) - 0x1000)
|
||||
|
||||
/* Fetch the instruction at PC. Instructions are always big-endian
|
||||
@ -1451,14 +1452,24 @@ sparc_analyze_control_transfer (struct frame_info *frame,
|
||||
{
|
||||
unsigned long insn = sparc_fetch_instruction (pc);
|
||||
int conditional_p = X_COND (insn) & 0x7;
|
||||
int branch_p = 0;
|
||||
int branch_p = 0, fused_p = 0;
|
||||
long offset = 0; /* Must be signed for sign-extend. */
|
||||
|
||||
if (X_OP (insn) == 0 && X_OP2 (insn) == 3 && (insn & 0x1000000) == 0)
|
||||
if (X_OP (insn) == 0 && X_OP2 (insn) == 3)
|
||||
{
|
||||
/* Branch on Integer Register with Prediction (BPr). */
|
||||
branch_p = 1;
|
||||
conditional_p = 1;
|
||||
if ((insn & 0x10000000) == 0)
|
||||
{
|
||||
/* Branch on Integer Register with Prediction (BPr). */
|
||||
branch_p = 1;
|
||||
conditional_p = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Compare and Branch */
|
||||
branch_p = 1;
|
||||
fused_p = 1;
|
||||
offset = 4 * X_DISP10 (insn);
|
||||
}
|
||||
}
|
||||
else if (X_OP (insn) == 0 && X_OP2 (insn) == 6)
|
||||
{
|
||||
@ -1495,7 +1506,16 @@ sparc_analyze_control_transfer (struct frame_info *frame,
|
||||
|
||||
if (branch_p)
|
||||
{
|
||||
if (conditional_p)
|
||||
if (fused_p)
|
||||
{
|
||||
/* Fused compare-and-branch instructions are non-delayed,
|
||||
and do not have an annuling capability. So we need to
|
||||
always set a breakpoint on both the NPC and the branch
|
||||
target address. */
|
||||
gdb_assert (offset != 0);
|
||||
return pc + offset;
|
||||
}
|
||||
else if (conditional_p)
|
||||
{
|
||||
/* For conditional branches, return nPC + 4 iff the annul
|
||||
bit is 1. */
|
||||
|
Loading…
Reference in New Issue
Block a user