This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]