📄 mach_dep.c
字号:
asm ("movd r3, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r4, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r5, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r6, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4"); asm ("movd r7, tos"); asm ("bsr ?_GC_push_one"); asm ("adjspb $-4");# define HAVE_PUSH_REGS# endif# if defined(SPARC) GC_save_regs_ret_val = GC_save_regs_in_stack();# define HAVE_PUSH_REGS# endif# ifdef RT GC_push_one(TMP_SP); /* GC_push_one from r11 */ asm("cas r11, r6, r0"); GC_push_one(TMP_SP); /* r6 */ asm("cas r11, r7, r0"); GC_push_one(TMP_SP); /* through */ asm("cas r11, r8, r0"); GC_push_one(TMP_SP); /* r10 */ asm("cas r11, r9, r0"); GC_push_one(TMP_SP); asm("cas r11, r10, r0"); GC_push_one(TMP_SP); asm("cas r11, r12, r0"); GC_push_one(TMP_SP); /* r12 */ asm("cas r11, r13, r0"); GC_push_one(TMP_SP); /* through */ asm("cas r11, r14, r0"); GC_push_one(TMP_SP); /* r15 */ asm("cas r11, r15, r0"); GC_push_one(TMP_SP);# define HAVE_PUSH_REGS# endif# if defined(M68K) && defined(SYSV) /* Once again similar to SUN and HP, though setjmp appears to work. --Parag */# ifdef __GNUC__ asm("subqw #0x4,%sp"); /* allocate word on top of stack */ asm("movl %a2,%sp@"); asm("jbsr GC_push_one"); asm("movl %a3,%sp@"); asm("jbsr GC_push_one"); asm("movl %a4,%sp@"); asm("jbsr GC_push_one"); asm("movl %a5,%sp@"); asm("jbsr GC_push_one"); /* Skip frame pointer and stack pointer */ asm("movl %d1,%sp@"); asm("jbsr GC_push_one"); asm("movl %d2,%sp@"); asm("jbsr GC_push_one"); asm("movl %d3,%sp@"); asm("jbsr GC_push_one"); asm("movl %d4,%sp@"); asm("jbsr GC_push_one"); asm("movl %d5,%sp@"); asm("jbsr GC_push_one"); asm("movl %d6,%sp@"); asm("jbsr GC_push_one"); asm("movl %d7,%sp@"); asm("jbsr GC_push_one"); asm("addqw #0x4,%sp"); /* put stack back where it was */# define HAVE_PUSH_REGS# else /* !__GNUC__*/ asm("subq.w &0x4,%sp"); /* allocate word on top of stack */ asm("mov.l %a2,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %a3,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %a4,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %a5,(%sp)"); asm("jsr GC_push_one"); /* Skip frame pointer and stack pointer */ asm("mov.l %d1,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d2,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d3,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d4,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d5,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d6,(%sp)"); asm("jsr GC_push_one"); asm("mov.l %d7,(%sp)"); asm("jsr GC_push_one"); asm("addq.w &0x4,%sp"); /* put stack back where it was */# define HAVE_PUSH_REGS# endif /* !__GNUC__ */# endif /* M68K/SYSV */# if defined(PJ) { register int * sp asm ("optop"); extern int *__libc_stack_end; GC_push_all_stack (sp, __libc_stack_end);# define HAVE_PUSH_REGS /* Isn't this redundant with the code to push the stack? */ }# endif /* other machines... */# if !defined(HAVE_PUSH_REGS) --> We just generated an empty GC_push_regs, which --> is almost certainly broken. Try defining --> USE_GENERIC_PUSH_REGS instead.# endif}#endif /* !USE_GENERIC_PUSH_REGS && !USE_ASM_PUSH_REGS */void GC_with_callee_saves_pushed(fn, arg)void (*fn)();ptr_t arg;{ word dummy;# if defined(USE_GENERIC_PUSH_REGS)# ifdef 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();# else /* !HAVE_BUILTIN_UNWIND_INIT */# if defined(RS6000) || defined(POWERPC) /* FIXME: RS6000 means AIX. */ /* This should probably be used in all Posix/non-gcc */ /* settings. We defer that change to minimize risk. */ ucontext_t ctxt; getcontext(&ctxt);# else /* Generic code */ /* The idea is due to Parag Patel at HP. */ /* We're not sure whether he would like */ /* to be he acknowledged for it or not. */ jmp_buf regs; register word * i = (word *) regs; register ptr_t lim = (ptr_t)(regs) + (sizeof regs); /* Setjmp doesn't always clear all of the buffer. */ /* That tends to preserve garbage. Clear it. */ for (; (char *)i < lim; i++) { *i = 0; }# if defined(MSWIN32) || defined(MSWINCE) \ || defined(UTS4) || defined(LINUX) || defined(EWS4800) (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 /* !AIX ... */# endif /* !HAVE_BUILTIN_UNWIND_INIT */# else# if defined(PTHREADS) && !defined(MSWIN32) /* !USE_GENERIC_PUSH_REGS */ /* We may still need this to save thread contexts. */ ucontext_t ctxt; getcontext(&ctxt);# else /* Shouldn't be needed */ ABORT("Unexpected call to GC_with_callee_saves_pushed");# endif# endif# if (defined(SPARC) && !defined(HAVE_BUILTIN_UNWIND_INIT)) \ || defined(IA64) /* On a register window machine, we need to save register */ /* contents on the stack for this to work. The setjmp */ /* is probably not needed on SPARC, since pointers are */ /* only stored in windowed or scratch registers. It is */ /* needed on IA64, since some non-windowed registers are */ /* preserved. */ { GC_save_regs_ret_val = GC_save_regs_in_stack(); /* On IA64 gcc, could use __builtin_ia64_flushrs() and */ /* __builtin_ia64_flushrs(). The latter will be done */ /* implicitly by __builtin_unwind_init() for gcc3.0.1 */ /* and later. */ }# endif fn(arg); /* 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((word)(&dummy));}#if defined(USE_GENERIC_PUSH_REGS)void GC_generic_push_regs(cold_gc_frame)ptr_t cold_gc_frame;{ GC_with_callee_saves_pushed(GC_push_current_stack, cold_gc_frame);}#endif /* USE_GENERIC_PUSH_REGS *//* On register window machines, we need a way to force registers into *//* the stack. Return sp. */# ifdef SPARC asm(" .seg \"text\"");# if defined(SVR4) || defined(NETBSD) || defined(FREEBSD) asm(" .globl GC_save_regs_in_stack"); asm("GC_save_regs_in_stack:"); asm(" .type GC_save_regs_in_stack,#function");# else asm(" .globl _GC_save_regs_in_stack"); asm("_GC_save_regs_in_stack:");# endif# if defined(__arch64__) || defined(__sparcv9) asm(" save %sp,-128,%sp"); asm(" flushw"); asm(" ret"); asm(" restore %sp,2047+128,%o0");# else asm(" ta 0x3 ! ST_FLUSH_WINDOWS"); asm(" retl"); asm(" mov %sp,%o0");# endif# ifdef SVR4 asm(" .GC_save_regs_in_stack_end:"); asm(" .size GC_save_regs_in_stack,.GC_save_regs_in_stack_end-GC_save_regs_in_stack");# endif# ifdef LINT word GC_save_regs_in_stack() { return(0 /* sp really */);}# endif# endif/* On IA64, we also need to flush register windows. But they end *//* up on the other side of the stack segment. *//* Returns the backing store pointer for the register stack. *//* We now implement this as a separate assembly file, since inline *//* assembly code here doesn't work with either the Intel or HP *//* compilers. */# if 0# ifdef LINUX asm(" .text"); asm(" .psr abi64"); asm(" .psr lsb"); asm(" .lsb"); asm(""); asm(" .text"); asm(" .align 16"); asm(" .global GC_save_regs_in_stack"); asm(" .proc GC_save_regs_in_stack"); asm("GC_save_regs_in_stack:"); asm(" .body"); asm(" flushrs"); asm(" ;;"); asm(" mov r8=ar.bsp"); asm(" br.ret.sptk.few rp"); asm(" .endp GC_save_regs_in_stack");# endif /* LINUX */# if 0 /* Other alternatives that don't work on HP/UX */ word GC_save_regs_in_stack() {# if USE_BUILTINS __builtin_ia64_flushrs(); return __builtin_ia64_bsp();# else# ifdef HPUX _asm(" flushrs"); _asm(" ;;"); _asm(" mov r8=ar.bsp"); _asm(" br.ret.sptk.few rp");# else asm(" flushrs"); asm(" ;;"); asm(" mov r8=ar.bsp"); asm(" br.ret.sptk.few rp");# endif# endif }# endif# endif/* GC_clear_stack_inner(arg, limit) clears stack area up to limit and *//* returns arg. Stack clearing is crucial on SPARC, so we supply *//* an assembly version that's more careful. Assumes limit is hotter *//* than sp, and limit is 8 byte aligned. */#if defined(ASM_CLEAR_CODE)#ifndef SPARC --> fix it#endif# ifdef SUNOS4 asm(".globl _GC_clear_stack_inner"); asm("_GC_clear_stack_inner:");# else asm(".globl GC_clear_stack_inner"); asm("GC_clear_stack_inner:"); asm(".type GC_save_regs_in_stack,#function");# endif#if defined(__arch64__) || defined(__sparcv9) asm("mov %sp,%o2"); /* Save sp */ asm("add %sp,2047-8,%o3"); /* p = sp+bias-8 */ asm("add %o1,-2047-192,%sp"); /* Move sp out of the way, */ /* so that traps still work. */ /* Includes some extra words */ /* so we can be sloppy below. */ asm("loop:"); asm("stx %g0,[%o3]"); /* *(long *)p = 0 */ asm("cmp %o3,%o1"); asm("bgu,pt %xcc, loop"); /* if (p > limit) goto loop */ asm("add %o3,-8,%o3"); /* p -= 8 (delay slot) */ asm("retl"); asm("mov %o2,%sp"); /* Restore sp., delay slot */#else asm("mov %sp,%o2"); /* Save sp */ asm("add %sp,-8,%o3"); /* p = sp-8 */ asm("clr %g1"); /* [g0,g1] = 0 */ asm("add %o1,-0x60,%sp"); /* Move sp out of the way, */ /* so that traps still work. */ /* Includes some extra words */ /* so we can be sloppy below. */ asm("loop:"); asm("std %g0,[%o3]"); /* *(long long *)p = 0 */ asm("cmp %o3,%o1"); asm("bgu loop "); /* if (p > limit) goto loop */ asm("add %o3,-8,%o3"); /* p -= 8 (delay slot) */ asm("retl"); asm("mov %o2,%sp"); /* Restore sp., delay slot */#endif /* old SPARC */ /* First argument = %o0 = return value */# ifdef SVR4 asm(" .GC_clear_stack_inner_end:"); asm(" .size GC_clear_stack_inner,.GC_clear_stack_inner_end-GC_clear_stack_inner");# endif # ifdef LINT /*ARGSUSED*/ ptr_t GC_clear_stack_inner(arg, limit) ptr_t arg; word limit; { return(arg); }# endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -