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:
David S. Miller 2012-04-21 19:03:52 +00:00
parent 4272ccafdd
commit 8d1b3521db
2 changed files with 31 additions and 6 deletions

View File

@ -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.

View File

@ -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. */