This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC]: try three MD_FALLBACK_FRAME_STATE_FOR macro for darwin PPC
- From: Andreas Tobler <toa at pop dot agri dot ch>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Andrew Pinski <pinskia at physics dot uc dot edu>, Geoff Keating <geoffk at geoffk dot org>
- Date: Fri, 30 Jan 2004 09:05:58 +0100
- Subject: [RFC]: try three MD_FALLBACK_FRAME_STATE_FOR macro for darwin PPC
Ok,
here a third attempt to this macro.
Andrew pointed a few things out, thanks a lot!
So far tested on a G4 Powerbook. Works with libjava too.
The G5 stuff is also implemented but not tested.
Any comments highly appreciated.
Thanks in advance,
Andreas
Index: gcc/config/rs6000/darwin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/darwin.h,v
retrieving revision 1.46
diff -u -r1.46 darwin.h
--- gcc/config/rs6000/darwin.h 17 Jan 2004 19:48:50 -0000 1.46
+++ gcc/config/rs6000/darwin.h 30 Jan 2004 06:16:26 -0000
@@ -1,5 +1,5 @@
/* Target definitions for PowerPC running Darwin (Mac OS X).
- Copyright (C) 1997, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2000, 2001, 2003 2004 Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
This file is part of GCC.
@@ -321,3 +321,208 @@
#undef REGISTER_TARGET_PRAGMAS
#define REGISTER_TARGET_PRAGMAS DARWIN_REGISTER_TARGET_PRAGMAS
+#ifdef IN_LIBGCC2
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/sysctl.h>
+#include <sys/ucontext.h>
+
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
+ do { \
+ unsigned int *pc_ = (CONTEXT)->ra; \
+ struct ucontext *uc_; \
+ struct mcontext *mc_; \
+ struct ucontext64 *uc64_; \
+ struct mcontext64 *mc64_; \
+ unsigned int cpusubtype; \
+ size_t len; \
+ long new_cfa_; \
+ int i_; \
+ unsigned int state_cnt; \
+ int altivec_used = 0; \
+ /* context32 is static int with three states, -1: not set, \
+ 1: context32, 0: context64. This is to reduce the calls to \
+ sysctlbyname below. */ \
+ static int context32 = -1; \
+ \
+ /* We check here if we have a G5, if so, we assume that the context \
+ is stored in mcontext64 and ucontext64. */ \
+ len = sizeof(int); \
+ if(context32 == -1) { \
+ sysctlbyname("hw.cpusubtype", &cpusubtype, &len, 0, 0); \
+ if(cpusubtype == CPU_SUBTYPE_POWERPC_970) \
+ context32 = 0; \
+ else \
+ context32 = 1; \
+ } \
+ \
+ static unsigned int DARWIN_LIBC_SEQ[] = { \
+ /* This is the sequence you should enter when catching a signal \
+ on Darwin. You find this sequence in libSystem around \
+ 0x90025158. This is on powerpc-apple-darwin-7.2.0. \
+ Other versions of libSystem may vary. \
+ We use this sequence to check if we are on the right \
+ OS-X version. */ \
+ \
+ 0x2e1e0032, /* cmpwi cr4,r30,50 */ \
+ 0x41920010, /* beq- cr4,9002516c */ \
+ 0x2f9e0037, /* cmpwi cr7,r30,55 */ \
+ 0x7fc5f378, /* mr r5,r30 */ \
+ 0x40be0050, /* bne+ cr7,900251b8 */ \
+ 0x807d001c, /* lwz r3,28(r29) */ \
+ 0x3bc30408, /* addi r30,r3,1032 */ \
+ 0x7fc4f378, /* mr r4,r30 */ \
+ 0x4807b6c9 /* bl 900a0840 */ \
+ }; \
+ \
+ if (*(unsigned int *) (pc_ + 0) != 0x2e1e0032) { \
+ if (*(unsigned int *) (pc_ + 4) == 0x2e1e0032) { \
+ /* If the signal handler did not skip the faulting instruction \
+ we will do. */ \
+ pc_ = pc_ + 4; \
+ } \
+ else \
+ break; \
+ } \
+ /* Here we have to check that we're on the right libc version. */ \
+ if (memcmp(DARWIN_LIBC_SEQ, pc_, sizeof(DARWIN_LIBC_SEQ)) == 0) \
+ { \
+ /* At compile time I do not no whether we run on a G5 (64-bit) \
+ or on a G3/4 (32-bit). So I prepare the sigframe for \
+ both. */ \
+ struct sigframe { \
+ char redzone[216]; \
+ siginfo_t st; \
+ struct ucontext uc; \
+ struct mcontext mc; \
+ } *rt_ = (CONTEXT)->cfa; \
+ mc_ = &rt_->mc; \
+ uc_ = &rt_->uc; \
+ \
+ struct sigframe64 { \
+ char redzone[216]; \
+ siginfo_t st; \
+ struct ucontext64 uc; \
+ struct mcontext64 mc; \
+ } *rt64_ = (CONTEXT)->cfa; \
+ mc64_ = &rt64_->mc; \
+ uc64_ = &rt64_->uc; \
+ } \
+ else \
+ break; \
+ \
+ if (context32) \
+ new_cfa_ = mc_->ss.r1; \
+ else \
+ new_cfa_ = mc64_->ss.r1; \
+ (FS)->cfa_how = CFA_REG_OFFSET; \
+ (FS)->cfa_reg = STACK_POINTER_REGNUM; \
+ (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
+ \
+ /* r0 to r31 are variable names in the ppc_thread_state struct \
+ since we need the address we just increment the r0 by i_ * 4 \
+ (i_ * 8 for 64 bit) to get the other vars addresses. */ \
+ \
+ for (i_ = 0; i_ < 32; i_++) { \
+ if (i_ != STACK_POINTER_REGNUM) \
+ { \
+ (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&(mc_->ss.r0) + (i_ * 4) - new_cfa_; \
+ else \
+ (FS)->regs.reg[i_].loc.offset \
+ = (long)&(mc64_->ss.r0) + (i_ * 8) - new_cfa_; \
+ } \
+ } \
+ \
+ /* Float registers to be saved according to the Runtime Convention: \
+ f14 - f31. Although, we save all of them. \
+ (FS)->regs.reg[32] is the address of fr0. */ \
+ \
+ for (i_ = 0; i_ < 32; i_++) { \
+ (FS)->regs.reg[32 + i_].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[32 + i_].loc.offset \
+ = (long)&(mc_->fs.fpregs[i_]) - new_cfa_; \
+ else \
+ (FS)->regs.reg[32 + i_].loc.offset \
+ = (long)&(mc64_->fs.fpregs[i_]) - new_cfa_; \
+ } \
+ \
+ /* Restore spefscr/fpscr register. */ \
+ (FS)->regs.reg[SPEFSCR_REGNO].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[SPEFSCR_REGNO].loc.offset \
+ = (long)&(mc_->fs.fpscr) - new_cfa_; \
+ else \
+ (FS)->regs.reg[SPEFSCR_REGNO].loc.offset \
+ = (long)&(mc64_->fs.fpscr) - new_cfa_; \
+ \
+ /* To see whether we have to restore altivec registers we check \
+ the size of the machine context against PPC_MCONTEXT(64)_SIZE \
+ minus the PPC_VECTOR_STATE_COUNT size. If we have a vectorunit \
+ it is not necessary to restore the registers if we do not use \
+ them. */ \
+ if (context32) { \
+ state_cnt = (size_t)(PPC_MCONTEXT_SIZE - \
+ PPC_VECTOR_STATE_COUNT * sizeof(int)); \
+ if (uc_->uc_mcsize > state_cnt) \
+ altivec_used = 1; \
+ } else { \
+ state_cnt = (size_t)(PPC_MCONTEXT64_SIZE - \
+ PPC_VECTOR_STATE_COUNT * sizeof(int)); \
+ if (uc64_->uc_mcsize > state_cnt) \
+ altivec_used = 1; \
+ } \
+ \
+ if (altivec_used) { \
+ /*Alitvec registers to be saved according to the Runtime \
+ Convention: v20 - v31. Although, we save all of them. */ \
+ \
+ for (i_ = 0; i_ < 32; i_++) { \
+ (FS)->regs.reg[FIRST_ALTIVEC_REGNO + i_].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[FIRST_ALTIVEC_REGNO + i_].loc.offset \
+ = (long)&(mc_->vs.save_vr[i_]) - new_cfa_; \
+ else \
+ (FS)->regs.reg[FIRST_ALTIVEC_REGNO + i_].loc.offset \
+ = (long)&(mc64_->vs.save_vr[i_]) - new_cfa_; \
+ } \
+ } \
+ \
+ /* Restore link register lr. */ \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
+ = (long)&(mc_->ss.lr) - new_cfa_; \
+ else \
+ (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
+ = (long)&(mc64_->ss.lr) - new_cfa_; \
+ \
+ if (altivec_used) { \
+ /* Restore vrsave register. */ \
+ (FS)->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[VRSAVE_REGNO].loc.offset \
+ = (long)&(mc_->ss.vrsave) - new_cfa_; \
+ else \
+ (FS)->regs.reg[VRSAVE_REGNO].loc.offset \
+ = (long)&(mc64_->ss.vrsave) - new_cfa_; \
+ } \
+ \
+ /* Restore CR0 register. */ \
+ (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET; \
+ if (context32) \
+ (FS)->regs.reg[CR0_REGNO].loc.offset \
+ = (long)&(mc_->ss.srr0) - new_cfa_; \
+ else \
+ (FS)->regs.reg[CR0_REGNO].loc.offset \
+ = (long)&(mc64_->ss.srr0) - new_cfa_; \
+ (FS)->retaddr_column = CR0_REGNO; \
+ \
+ goto SUCCESS; \
+ } while (0)