summaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config/rs6000/linux-unwind.h18
2 files changed, 16 insertions, 8 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 9108e46c9f0..1685c9fa7c3 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-08-02 Alan Modra <amodra@gmail.com>
+
+ * config/rs6000/linux-unwind.h (frob_update_context <__powerpc64__>):
+ Restore for indirect call bcrtl from correct stack slot, and only
+ if cfa+40 isn't valid.
+
2011-08-01 Julian Brown <julian@codesourcery.com>
* config.host (arm*-*-linux*, arm*-*-uclinux*, arm*-*-eabi*)
diff --git a/libgcc/config/rs6000/linux-unwind.h b/libgcc/config/rs6000/linux-unwind.h
index 48009251fbc..20116326c3c 100644
--- a/libgcc/config/rs6000/linux-unwind.h
+++ b/libgcc/config/rs6000/linux-unwind.h
@@ -354,20 +354,22 @@ frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATT
/* We are in a plt call stub or r2 adjusting long branch stub,
before r2 has been saved. Keep REG_UNSAVED. */
}
- else if (pc[0] == 0x4E800421
- && pc[1] == 0xE8410028)
- {
- /* We are at the bctrl instruction in a call via function
- pointer. gcc always emits the load of the new r2 just
- before the bctrl. */
- _Unwind_SetGRPtr (context, 2, context->cfa + 40);
- }
else
{
unsigned int *insn
= (unsigned int *) _Unwind_GetGR (context, R_LR);
if (insn && *insn == 0xE8410028)
_Unwind_SetGRPtr (context, 2, context->cfa + 40);
+ else if (pc[0] == 0x4E800421
+ && pc[1] == 0xE8410028)
+ {
+ /* We are at the bctrl instruction in a call via function
+ pointer. gcc always emits the load of the new R2 just
+ before the bctrl so this is the first and only place
+ we need to use the stored R2. */
+ _Unwind_Word sp = _Unwind_GetGR (context, 1);
+ _Unwind_SetGRPtr (context, 2, sp + 40);
+ }
}
}
#endif