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 two MD_FALLBACK_FRAME_STATE_FOR macro for darwin PPC


Dale Johannesen wrote:

Saved regs are described in rs6000.h of course.
Floats are F14-F31 and I think you may need CR also, some of its subregs are caller-saved.
And then there's Altivec, V20-V31 and VRSAVE. They don't exist on all machines though!

Ok here a next try, some more saves.


I managed to pass the cleanup-[8-11].c with some modifications too.

The modifications I had to do are on the tests itself.

#ifndef SA_ONESHOT
#define SA_ONESHOT SA_RESETHAND
#endif

Because darwin does not know SA_ONESHOT.

And the signal handler itself has to be loaded with a SIGBUS since this is emitted when a EXC_BAD_ACCESS happens on darwin.

The macro itself does only work with 32 bit CPU's, not with G5, as Andrew pointed out. I think a 64bit macro should be possible after I completed this one?

I have to do some further test if the regs are saved correctly, especially the altivec ones. For now in my test apps they don't get saved. Either I don't need them or my mechanics to check whether to save or not does not work.

Any further comments?

Thanks in advance,

Andreas


Index: 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
--- config/rs6000/darwin.h	17 Jan 2004 19:48:50 -0000	1.46
+++ config/rs6000/darwin.h	22 Jan 2004 21:01:22 -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,134 @@
 #undef REGISTER_TARGET_PRAGMAS
 #define REGISTER_TARGET_PRAGMAS DARWIN_REGISTER_TARGET_PRAGMAS
 
+#ifdef IN_LIBGCC2
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#endif
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS)		\
+  do {									\
+    unsigned int *pc_ = (CONTEXT)->ra;					\
+    struct mcontext *mc_;						\
+    struct ucontext *uc_;						\
+    long new_cfa_;							\
+    int i_;								\
+    int altivec_used = 0;						\
+    unsigned int state_cnt;						\
+									\
+    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)	\
+      {									\
+	struct sigframe {						\
+	  char redzone[216];						\
+	  siginfo_t st;							\
+	  struct ucontext uc;						\
+	  struct mcontext mc;						\
+	} *rt_ = (CONTEXT)->cfa;					\
+	mc_ = &rt_->mc;							\
+	uc_ = &rt_->uc;							\
+      }									\
+    else								\
+	break;								\
+									\
+    new_cfa_ = mc_->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	\
+       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;			\
+	  (FS)->regs.reg[i_].loc.offset					\
+	    = (long)&(mc_->ss.r0) + (i_*4) - 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;			\
+      (FS)->regs.reg[32 + i_].loc.offset				\
+	= (long)&(mc_->fs.fpregs[i_]) - new_cfa_;			\
+    }									\
+									\
+    /* Restore spefscr/fpscr register.  */				\
+    (FS)->regs.reg[SPEFSCR_REGNO].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[SPEFSCR_REGNO].loc.offset				\
+      = (long)&(mc_->fs.fpscr) - new_cfa_;				\
+									\
+    /* To see whether we have to restore altivec registers we check	\
+       the size of the machine context against PPC_MCONTEXT_SIZE minus	\
+       the PPC_VECTOR_STATE_COUNT size.  */				\
+    state_cnt = (size_t)(PPC_MCONTEXT_SIZE -				\
+			 PPC_VECTOR_STATE_COUNT * sizeof(int));		\
+    if (uc_->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; \
+	(FS)->regs.reg[FIRST_ALTIVEC_REGNO + i_].loc.offset		\
+	  = (long)&(mc_->vs.save_vr[i_]) - new_cfa_;			\
+      }									\
+    }									\
+									\
+    /* Restore link register lr.  */					\
+    (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET;	\
+    (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset			\
+      = (long)&(mc_->ss.lr) - new_cfa_;					\
+									\
+    /* Restore vrsave register.  */					\
+    (FS)->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET;		\
+    (FS)->regs.reg[VRSAVE_REGNO].loc.offset				\
+      = (long)&(mc_->ss.vrsave) - new_cfa_;				\
+									\
+    /* Restore CR0 register.  */					\
+    (FS)->regs.reg[CR0_REGNO].how = REG_SAVED_OFFSET;			\
+    (FS)->regs.reg[CR0_REGNO].loc.offset				\
+      = (long)&(mc_->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]