| Index: gdb/sparc-tdep.c
|
| diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
|
| index 24d54b741723dd4d6aaaea00adceab840e157001..6da2297a3cb9547ab8c48f8e4e8947fd2cc13ad9 100644
|
| --- a/gdb/sparc-tdep.c
|
| +++ b/gdb/sparc-tdep.c
|
| @@ -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
|
| @@ -601,7 +602,6 @@ static struct sparc_frame_cache *
|
| sparc_alloc_frame_cache (void)
|
| {
|
| struct sparc_frame_cache *cache;
|
| - int i;
|
|
|
| cache = FRAME_OBSTACK_ZALLOC (struct sparc_frame_cache);
|
|
|
| @@ -1353,7 +1353,7 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache,
|
| }
|
|
|
| static enum return_value_convention
|
| -sparc32_return_value (struct gdbarch *gdbarch, struct type *func_type,
|
| +sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
| struct type *type, struct regcache *regcache,
|
| gdb_byte *readbuf, const gdb_byte *writebuf)
|
| {
|
| @@ -1451,14 +1451,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 +1505,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. */
|
|
|