/* * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. * * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * * Permission is hereby granted to use or copy this program * for any purpose, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice.
*/
staticvoid PushMacRegisters(void)
{
ppc_registers regs; int i;
getRegisters(®s); for (i = 0; i < NONVOLATILE_GPR_COUNT; i++)
GC_push_one(regs.gprs[i]);
}
#else/* M68K */
asmstaticvoid PushMacRegisters(void)
{
sub.w #4,sp /* reserve space for one parameter */
move.l a2,(sp)
jsr GC_push_one
move.l a3,(sp)
jsr GC_push_one
move.l a4,(sp)
jsr GC_push_one # if !__option(a6frames) /* <pcb> perhaps a6 should be pushed if stack frames are not being used */
move.l a6,(sp)
jsr GC_push_one # endif /* skip a5 (globals), a6 (frame pointer), and a7 (stack pointer) */
move.l d2,(sp)
jsr GC_push_one
move.l d3,(sp)
jsr GC_push_one
move.l d4,(sp)
jsr GC_push_one
move.l d5,(sp)
jsr GC_push_one
move.l d6,(sp)
jsr GC_push_one
move.l d7,(sp)
jsr GC_push_one
add.w #4,sp /* fix stack */
rts
}
#endif/* M68K */
#endif/* MACOS && __MWERKS__ */
# ifdefined(SPARC) || defined(IA64) /* Value returned from register flushing routine; either sp (SPARC) */ /* or ar.bsp (IA64). */
GC_INNER ptr_t GC_save_regs_ret_val = NULL; # endif
/* Routine to mark from registers that are preserved by the C compiler. */ /* This must be ported to every new architecture. It is not optional, */ /* and should not be used on platforms that are either UNIX-like, or */ /* require thread support. */
#undef HAVE_PUSH_REGS
#ifdefined(USE_ASM_PUSH_REGS) # define HAVE_PUSH_REGS #else/* No asm implementation */
# elif defined(M68K) && defined(AMIGA) /* This function is not static because it could also be */ /* erroneously defined in .S file, so this error would be caught */ /* by the linker. */ void GC_push_regs(void)
{ /* AMIGA - could be replaced by generic code */ /* a0, a1, d0 and d1 are caller save */
# ifdef __GNUC__ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */
#ifdefined(HAVE_PUSH_REGS) && defined(THREADS) # error GC_push_regs cannot be used with threads /* Would fail for GC_do_blocking. There are probably other safety */ /* issues. */ # undef HAVE_PUSH_REGS #endif
/* Ensure that either registers are pushed, or callee-save registers */ /* are somewhere on the stack, and then call fn(arg, ctxt). */ /* ctxt is either a pointer to a ucontext_t we generated, or NULL. */
GC_ATTR_NO_SANITIZE_ADDR
GC_INNER void GC_with_callee_saves_pushed(void (*fn)(ptr_t, void *), volatile ptr_t arg)
{ volatileint dummy; volatile ptr_t context = 0;
# ifdefined(HAVE_PUSH_REGS)
GC_push_regs(); # elif defined(EMSCRIPTEN) /* No-op, "registers" are pushed in GC_push_other_roots(). */ # else # ifdefined(UNIX_LIKE) && !defined(NO_GETCONTEXT) /* Older versions of Darwin seem to lack getcontext(). */ /* ARM and MIPS Linux often doesn't support a real */ /* getcontext(). */ staticsignedchar getcontext_works = 0; /* (-1) - broken, 1 - works */
ucontext_t ctxt; # ifdef GETCONTEXT_FPU_EXCMASK_BUG /* Workaround a bug (clearing the FPU exception mask) in */ /* getcontext on Linux/x86_64. */ # ifdef X86_64 /* We manipulate FPU control word here just not to force the */ /* client application to use -lm linker option. */ unsignedshort old_fcw;
if (getcontext_works >= 0) { if (getcontext(&ctxt) < 0) {
WARN("getcontext failed:" " using another register retrieval method...\n", 0); /* getcontext() is broken, do not try again. */ /* E.g., to workaround a bug in Docker ubuntu_32bit. */
} else {
context = (ptr_t)&ctxt;
} if (EXPECT(0 == getcontext_works, FALSE))
getcontext_works = context != NULL ? 1 : -1;
} # ifdef GETCONTEXT_FPU_EXCMASK_BUG # ifdef X86_64
__asm__ __volatile__ ("fldcw %0" : : "m" (*&old_fcw));
{ unsigned mxcsr; /* And now correct the exception mask in SSE MXCSR. */
__asm__ __volatile__ ("stmxcsr %0" : "=m" (*&mxcsr));
mxcsr = (mxcsr & ~(FE_ALL_EXCEPT << 7)) |
((old_fcw & FE_ALL_EXCEPT) << 7);
__asm__ __volatile__ ("ldmxcsr %0" : : "m" (*&mxcsr));
} # else/* !X86_64 */ if (feenableexcept(except_mask) < 0)
ABORT("feenableexcept failed"); # endif # endif /* GETCONTEXT_FPU_EXCMASK_BUG */ # ifdefined(E2K) || defined(IA64) || defined(SPARC) /* On a register window machine, we need to save register */ /* contents on the stack for this to work. This may already be */ /* subsumed by the getcontext() call. */ # ifdefined(IA64) || defined(SPARC)
GC_save_regs_ret_val = # endif
GC_save_regs_in_stack(); # endif if (NULL == context) /* getcontext failed */ # endif /* !NO_GETCONTEXT */
{ # ifdefined(HAVE_BUILTIN_UNWIND_INIT) /* This was suggested by Richard Henderson as the way to */ /* force callee-save registers and register windows onto */ /* the stack. */
__builtin_unwind_init(); # elif defined(NO_CRT) && defined(MSWIN32)
CONTEXT ctx;
RtlCaptureContext(&ctx); # else /* Generic code */ /* The idea is due to Parag Patel at HP. */ /* We're not sure whether he would like */ /* to be acknowledged for it or not. */
jmp_buf regs;
word * i = (word *)®s;
ptr_t lim = (ptr_t)(®s) + sizeof(regs);
/* Setjmp doesn't always clear all of the buffer. */ /* That tends to preserve garbage. Clear it. */ for (; (word)i < (word)lim; i++) {
*i = 0;
} # ifdefined(MSWIN32) || defined(MSWINCE) || defined(UTS4) \
|| defined(OS2) || defined(CX_UX) || defined(__CC_ARM) \
|| defined(LINUX) || defined(EWS4800) || defined(RTEMS)
(void) setjmp(regs); # else
(void) _setjmp(regs); /* We don't want to mess with signals. According to */ /* SUSV3, setjmp() may or may not save signal mask. */ /* _setjmp won't, but is less portable. */ # endif # endif /* !HAVE_BUILTIN_UNWIND_INIT */
} # endif /* !HAVE_PUSH_REGS */ /* TODO: context here is sometimes just zero. At the moment, the */ /* callees don't really need it. */
fn(arg, (/* no volatile */ void *)context); /* Strongly discourage the compiler from treating the above */ /* as a tail-call, since that would pop the register */ /* contents before we get a chance to look at them. */
GC_noop1(COVERT_DATAFLOW(&dummy));
}
#endif/* !PLATFORM_MACH_DEP && !SN_TARGET_PSP2 */
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.