This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[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)