summaryrefslogtreecommitdiff
path: root/gcc/config/rs6000/linux.h
diff options
context:
space:
mode:
authoraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-21 12:31:14 +0000
committeraph <aph@138bc75d-0d04-0410-961f-82ee72b054a4>2001-05-21 12:31:14 +0000
commitf204fc480c3fb7cf2953cbda36d5223ceb7a5354 (patch)
tree0a15309b1f84d1549cdd918a0bb0a169c3cf4c5f /gcc/config/rs6000/linux.h
parentd0b0d9d428c4e0b12f1013ccae340f6cdd4e59fc (diff)
downloadgcc-f204fc480c3fb7cf2953cbda36d5223ceb7a5354.tar.gz
2001-05-17 Andrew Haley <aph@redhat.com>
* config/rs6000/linux.h (MD_FALLBACK_FRAME_STATE_FOR): New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42386 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/rs6000/linux.h')
-rw-r--r--gcc/config/rs6000/linux.h53
1 files changed, 53 insertions, 0 deletions
diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h
index f0cf9d18c34..285cf55e5c1 100644
--- a/gcc/config/rs6000/linux.h
+++ b/gcc/config/rs6000/linux.h
@@ -66,3 +66,56 @@ Boston, MA 02111-1307, USA. */
#ifndef USE_GNULIBC_1
#define DEFAULT_VTABLE_THUNKS 1
#endif
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#ifdef IN_LIBGCC2
+#include <signal.h>
+#include <sys/ucontext.h>
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned char *pc_ = (CONTEXT)->ra; \
+ struct sigcontext *sc_; \
+ long new_cfa_; \
+ int i_; \
+ \
+ /* li r0, 0x7777; sc (rt_sigreturn) */ \
+ /* li r0, 0x6666; sc (sigreturn) */ \
+ if (((*(unsigned int *) (pc_+0) == 0x38007777) \
+ || (*(unsigned int *) (pc_+0) == 0x38006666)) \
+ && (*(unsigned int *) (pc_+4) == 0x44000002)) \
+ sc_ = (CONTEXT)->cfa + __SIGNAL_FRAMESIZE; \
+ else \
+ break; \
+ \
+ new_cfa_ = sc_->regs->gpr[STACK_POINTER_REGNUM]; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = STACK_POINTER_REGNUM; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ \
+ for (i_ = 0; i_ < 32; i_++) \
+ if (i_ != STACK_POINTER_REGNUM) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&(sc_->regs->gpr[i_]) - new_cfa_; \
+ } \
+ \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
+ = (long)&(sc_->regs->link) - new_cfa_; \
+ \
+ /* The unwinder expects the IP to point to the following insn, \
+ whereas the kernel returns the address of the actual \
+ faulting insn. */ \
+ sc_->regs->nip += 4; \
+ (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
+ (FS)->regs.reg[CR0_REGNO].loc.offset \
+ = (long)&(sc_->regs->nip) - new_cfa_; \
+ (FS)->retaddr_column = CR0_REGNO; \
+ goto SUCCESS; \
+ } while (0)
+