X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStgCRun.c;h=d200cffa756320ca22ea535528b2b54626c780d7;hb=0316a9e603115e6d3f04bd03824a1ca9430b0f0f;hp=fc4ca662cedff0fa00dfd990fecec9cdbebc5f02;hpb=9bab7a0eda6230f7844b9c10b259331229ca6985;p=ghc-hetmet.git diff --git a/ghc/rts/StgCRun.c b/ghc/rts/StgCRun.c index fc4ca66..d200cff 100644 --- a/ghc/rts/StgCRun.c +++ b/ghc/rts/StgCRun.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: StgCRun.c,v 1.25 2001/08/07 20:06:41 ken Exp $ + * $Id: StgCRun.c,v 1.36 2002/06/13 21:14:51 wolfgang Exp $ * * (c) The GHC Team, 1998-2000 * @@ -19,20 +19,22 @@ * the whatever way C returns a value. * * NOTE: StgRun/StgReturn do *NOT* load or store Hp or any - * other registers (other than saving the C callee-saves + * other registers (other than saving the C callee-saves * registers). Instead, the called function "f" must do that * in STG land. - * + * * GCC will have assumed that pushing/popping of C-stack frames is * going on when it generated its code, and used stack space * accordingly. However, we actually {\em post-process away} all * such stack-framery (see \tr{ghc/driver/ghc-asm.lprl}). Things will * be OK however, if we initially make sure there are * @RESERVED_C_STACK_BYTES@ on the C-stack to begin with, for local - * variables. + * variables. * * -------------------------------------------------------------------------- */ +#include "PosixSource.h" + /* * We define the following (unused) global register variables, because for @@ -44,14 +46,15 @@ * definition has been read. Any point after #include "Stg.h" would be too * late. * - * You can define alpha_EXTRA_CAREFUL here to save $s6, $f8 and $f9 -- registers - * that we don't use but which are callee-save registers. It shouldn't be - * necessary. + * We define alpha_EXTRA_CAREFUL here to save $s6, $f8 and $f9 -- registers + * that we don't use but which are callee-save registers. The __divq() routine + * in libc.a clobbers $s6. */ #include "config.h" #ifdef alpha_TARGET_ARCH -#undef alpha_EXTRA_CAREFUL +#define alpha_EXTRA_CAREFUL register long fake_ra __asm__("$26"); +register long fake_gp __asm__("$29"); #ifdef alpha_EXTRA_CAREFUL register long fake_s6 __asm__("$15"); register double fake_f8 __asm__("$f8"); @@ -77,26 +80,13 @@ register double fake_f9 __asm__("$f9"); /* ----------------------------------------------------------------------------- any architecture (using miniinterpreter) -------------------------------------------------------------------------- */ - -/* The static @jmp_environment@ variable allows @miniInterpret@ to - * communicate with @StgReturn@. - * - * Because @StgRun@ may be used recursively, we carefully - * save and restore the whole of @jmp_environment@. - */ -#include -#include /* for memcpy */ - -static jmp_buf jmp_environment; - -#if 1 -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) +extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED) { while (f) { IF_DEBUG(evaluator, fprintf(stderr,"Jumping to "); - printPtr((P_)f); + printPtr((P_)f); fflush(stdout); fprintf(stderr,"\n"); ); f = (StgFunPtr) (f)(); @@ -109,144 +99,6 @@ EXTFUN(StgReturn) return 0; } -#else - -#define CHECK_STACK 0 -#define STACK_DETAILS 0 - -static int enters = 0; - -static void scanStackSeg ( W_* ptr, int nwords ) -{ - W_ w; -#if CHECK_STACK - int nwords0 = nwords; -#if STACK_DETAILS - while (nwords > 0) { - w = *ptr; - if (IS_ARG_TAG(w)) { - fprintf ( stderr, "%d",w ); nwords--; ptr++; - while (w) { fprintf(stderr, "_"); w--; nwords--; ptr++; } - } - else { - fprintf(stderr, "p"); - nwords--; ptr++; - } - } - if (nwords < 0) fprintf(stderr, "erk: nwords < 0\n"); -#endif - checkStackChunk ( ptr, ptr-nwords0 ); -#endif -} - -extern StgFunPtr stg_enterStackTop; -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) -{ - char* nm; - while (1) { - -#if CHECK_STACK - { - int i; - StgTSO* tso = basereg->rCurrentTSO; - StgWord* sb = tso->stack + tso->stack_size; - StgWord* sp; - StgWord* su; - int ws; - - if (f == &stg_enterStackTop) { - sp = tso->sp; - su = tso->su; - } else { - sp = basereg->rSp; - su = basereg->rSu; - } - -#if STACK_DETAILS - fprintf(stderr, - "== SB = %p SP = %p(%p) SU = %p SpLim = %p(%p)\n", - sb, sp, tso->sp, su, basereg->rSpLim, tso->stack + RESERVED_STACK_WORDS); -#endif - - if (su >= sb) goto postloop; - if (!sp || !su) goto postloop; - - printStack ( sp, sb, su); - - while (1) { - ws = su - sp; - switch (get_itbl((StgClosure*)su)->type) { - case STOP_FRAME: - scanStackSeg(sp,ws); -#if STACK_DETAILS - fprintf(stderr, "S%d ",ws); - fprintf(stderr, "\n"); -#endif - goto postloop; - case UPDATE_FRAME: - scanStackSeg(sp,ws); -#if STACK_DETAILS - fprintf(stderr,"U%d ",ws); -#endif - sp = su + sizeofW(StgUpdateFrame); - su = ((StgUpdateFrame*)su)->link; - break; - case SEQ_FRAME: - scanStackSeg(sp,ws); -#if STACK_DETAILS - fprintf(stderr,"Q%d ",ws); -#endif - sp = su + sizeofW(StgSeqFrame); - su = ((StgSeqFrame*)su)->link; - break; - case CATCH_FRAME: - scanStackSeg(sp,ws); -#if STACK_DETAILS - fprintf(stderr,"C%d ",ws); -#endif - sp = su + sizeofW(StgCatchFrame); - su = ((StgCatchFrame*)su)->link; - break; - default: - fprintf(stderr, "?\nweird record on stack\n"); - assert(0); - goto postloop; - } - } - postloop: - } -#endif -#if STACK_DETAILS - fprintf(stderr,"\n"); -#endif -#if 1 - fprintf(stderr,"-- enter %p ", f); - nm = nameFromOPtr ( f ); - if (nm) fprintf(stderr, "%s", nm); else - printPtr((P_)f); - fprintf ( stderr, "\n"); -#endif -#if STACK_DETAILS - fprintf(stderr,"\n"); -#endif - zzz: - if (enters % 1000 == 0) fprintf(stderr, "%d enters\n",enters); - enters++; - f = (StgFunPtr) (f)(); - if (!f) break; - } - fprintf (stderr, "miniInterpreter: bye!\n\n" ); - return (StgThreadReturnCode)R1.i; -} - -EXTFUN(StgReturn) -{ - return 0; -} -#endif - - - #else /* !USE_MINIINTERPRETER */ #ifdef LEADING_UNDERSCORE @@ -258,7 +110,7 @@ EXTFUN(StgReturn) /* ----------------------------------------------------------------------------- x86 architecture -------------------------------------------------------------------------- */ - + #ifdef i386_TARGET_ARCH StgThreadReturnCode @@ -268,7 +120,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { StgThreadReturnCode r; __asm__ volatile ( - /* + /* * save callee-saves registers on behalf of the STG code. */ "movl %%esp, %%eax\n\t" @@ -315,7 +167,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { /* ----------------------------------------------------------------------------- Sparc architecture - -- + -- OLD COMMENT from GHC-3.02: We want tailjumps to be calls, because `call xxx' is the only Sparc @@ -342,7 +194,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { Updated info (GHC 4.08.2): not saving %i7 any more (see below). -------------------------------------------------------------------------- */ - + #ifdef sparc_TARGET_ARCH StgThreadReturnCode @@ -355,9 +207,9 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { #endif f(); __asm__ volatile ( - ".align 4\n" + ".align 4\n" ".global " STG_RETURN "\n" - STG_RETURN ":" + STG_RETURN ":" : : : "l0","l1","l2","l3","l4","l5","l6","l7"); /* we tell the C compiler that l0-l7 are clobbered on return to * StgReturn, otherwise it tries to use these to save eg. the @@ -375,7 +227,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { * call to f(), this gets clobbered in STG land and we end up * dereferencing a bogus pointer in StgReturn. */ - __asm__ volatile ("ld %1,%0" + __asm__ volatile ("ld %1,%0" : "=r" (i7) : "m" (((void **)(space))[100])); #endif return (StgThreadReturnCode)R1.i; @@ -406,7 +258,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { Architecture Reference Manual_, and as a result of asynchronous software actions." - -- Compaq Computer Corporation, Houston. Tru64 UNIX Calling Standard for + -- Compaq Computer Corporation, Houston. Tru64 UNIX Calling Standard for Alpha Systems, 5.1 edition, August 2000, section 3.2.1. http://www. tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_PDF/ARH9MBTE.PDF -------------------------------------------------------------------------- */ @@ -414,9 +266,10 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { #ifdef alpha_TARGET_ARCH StgThreadReturnCode -StgRun(StgFunPtr f, StgRegTable *basereg) +StgRun(StgFunPtr f, StgRegTable *basereg) { register long real_ra __asm__("$26"); volatile long save_ra; + register long real_gp __asm__("$29"); volatile long save_gp; register long real_s0 __asm__("$9" ); volatile long save_s0; register long real_s1 __asm__("$10"); volatile long save_s1; @@ -427,7 +280,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #ifdef alpha_EXTRA_CAREFUL register long real_s6 __asm__("$15"); volatile long save_s6; #endif - + register double real_f2 __asm__("$f2"); volatile double save_f2; register double real_f3 __asm__("$f3"); volatile double save_f3; register double real_f4 __asm__("$f4"); volatile double save_f4; @@ -444,6 +297,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) StgThreadReturnCode ret; save_ra = real_ra; + save_gp = real_gp; save_s0 = real_s0; save_s1 = real_s1; @@ -500,6 +354,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #endif real_ra = save_ra; + real_gp = save_gp; return ret; } @@ -513,7 +368,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #ifdef hppa1_1_TARGET_ARCH StgThreadReturnCode -StgRun(StgFunPtr f, StgRegTable *basereg) +StgRun(StgFunPtr f, StgRegTable *basereg) { StgChar space[RESERVED_C_STACK_BYTES+16*sizeof(long)+10*sizeof(double)]; StgThreadReturnCode ret; @@ -588,7 +443,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) "\tfldds 8(0,%%r19),%%fr19\n" "\tldo 32(%%r19),%%r19\n" "\tfldds -16(0,%%r19),%%fr20\n" - "\tfldds -8(0,%%r19),%%fr21\n" + "\tfldds -8(0,%%r19),%%fr21\n" : "=r" (ret) : "n" (-(116 * sizeof(long) + 10 * sizeof(double))) : "%r19" @@ -599,4 +454,97 @@ StgRun(StgFunPtr f, StgRegTable *basereg) #endif /* hppa1_1_TARGET_ARCH */ +/* ----------------------------------------------------------------------------- + PowerPC architecture + + Everything is in assembler, so we don't have to deal with GCC... + + -------------------------------------------------------------------------- */ + +#ifdef powerpc_TARGET_ARCH + +extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); + +static void StgRunIsImplementedInAssembler(void) +{ + __asm__ volatile ( + "\n.globl _StgRun\n" + "_StgRun:\n" + "\tmflr r0\n" + "\tbl saveFP # f14\n" + "\tstmw r14,-216(r1)\n" + "\tstwu r1,-8480(r1)\n" + "\tmtctr r3\n" + "\tmr r12,r3\n" + "\tbctr\n" + ".globl _StgReturn\n" + "_StgReturn:\n" + "\tmr r3,r14\n" + "\tla r1,8480(r1)\n" + "\tlmw r14,-216(r1)\n" + "\tb restFP # f14\n" + ); /* RESERVED_C_STACK_BYTES + stack frame size == 8192 + 288 == 8480 */ +} + +#endif + +/* ----------------------------------------------------------------------------- + IA64 architecture + + Again, in assembler - so we can fiddle with the register stack, and because + gcc doesn't handle asm-clobbered callee-saves correctly. + + loc0 - loc15: preserved locals + loc16 - loc28: STG registers + loc29: saved ar.pfs + loc30: saved b0 + -------------------------------------------------------------------------- */ + +#ifdef ia64_TARGET_ARCH + +/* the memory stack is rarely used, so 16K is excessive */ +#undef RESERVED_C_STACK_BYTES +#define RESERVED_C_STACK_BYTES 1024 + +static void StgRunIsImplementedInAssembler(void) +{ + __asm__ volatile( + ".global StgRun\n" + "StgRun:\n" + "\talloc loc29 = ar.pfs, 0, 31, 8, 0\n" /* setup register frame */ + "\tld8 r18 = [r32],8\n" /* get procedure address */ + "\tadds sp = -%0, sp ;;\n" /* setup stack */ + "\tld8 gp = [r32]\n" /* get procedure GP */ + "\tadds r16 = %0-(6*16), sp\n" + "\tadds r17 = %0-(5*16), sp ;;\n" + "\tstf.spill [r16] = f16,32\n" /* spill callee-saved fp regs */ + "\tstf.spill [r17] = f17,32\n" + "\tmov b6 = r18 ;;\n" /* set target address */ + "\tstf.spill [r16] = f18,32\n" + "\tstf.spill [r17] = f19,32\n" + "\tmov loc30 = b0 ;;\n" /* save return address */ + "\tstf.spill [r16] = f20,32\n" + "\tstf.spill [r17] = f21,32\n" + "\tbr.few b6 ;;\n" /* branch to function */ + ".global StgReturn\n" + "StgReturn:\n" + "\tmov r8 = loc16\n" /* return value in r8 */ + "\tadds r16 = %0-(6*16), sp\n" + "\tadds r17 = %0-(5*16), sp ;;\n" + "\tldf.fill f16 = [r16],32\n" /* start restoring fp regs */ + "\tldf.fill f17 = [r17],32\n" + "\tmov ar.pfs = loc29 ;;\n" /* restore register frame */ + "\tldf.fill f18 = [r16],32\n" + "\tldf.fill f19 = [r17],32\n" + "\tmov b0 = loc30 ;;\n" /* restore return address */ + "\tldf.fill f20 = [r16],32\n" + "\tldf.fill f21 = [r17],32\n" + "\tadds sp = %0, sp\n" /* restore stack */ + "\tbr.ret.sptk.many b0 ;;\n" /* return */ + : : "i"(RESERVED_C_STACK_BYTES + 6*16)); +} + +#endif + #endif /* !USE_MINIINTERPRETER */ +