X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fincludes%2FCOptWraps.lh;h=baf217b6635f342110b82151eb35f469425e52a5;hb=5eb1c77c795f92ed0f4c8023847e9d4be1a4fd0d;hp=c444df76beb6f00f0e2cbc62bd17676f1edb0b70;hpb=e7d21ee4f8ac907665a7e170c71d59e13a01da09;p=ghc-hetmet.git diff --git a/ghc/includes/COptWraps.lh b/ghc/includes/COptWraps.lh index c444df7..baf217b 100644 --- a/ghc/includes/COptWraps.lh +++ b/ghc/includes/COptWraps.lh @@ -69,9 +69,23 @@ but unfortunately, we have to cater to ANSI C as well.) do {SaveAllStgRegs(); PerformGC(args); RestoreAllStgRegs();} while(0) #define DO_STACKOVERFLOW(headroom,args) \ do {SaveAllStgRegs(); StackOverflow(headroom,args); RestoreAllStgRegs();} while(0) + +#if defined(GRAN) + +#define DO_YIELD(args) DO_GRAN_YIELD(args) +#define DO_GRAN_YIELD(liveness) \ + do {SaveAllStgRegs(); Yield(liveness); RestoreAllStgRegs();} while(0) + +#define DO_PERFORM_RESCHEDULE(liveness_mask,reenter) \ + do {SaveAllStgRegs(); PerformReschedule(liveness_mask,reenter); RestoreAllStgRegs();} while(0) + +#else + #define DO_YIELD(args) \ do {SaveAllStgRegs(); Yield(args); RestoreAllStgRegs();} while(0) +#endif /* GRAN */ + \end{code} %************************************************************************ @@ -168,12 +182,35 @@ extern void callWrapper_safe(STG_NO_ARGS); void PerformGC_wrapper PROTO((W_)); void StackOverflow_wrapper PROTO((W_, W_)); void Yield_wrapper PROTO((W_)); +# ifdef GRAN +void PerformReschedule_wrapper PROTO((W_, W_)); +void GranSimAllocate_wrapper PROTO((I_, P_, W_)); +void GranSimUnallocate_wrapper PROTO((I_, P_, W_)); +void GranSimFetch_wrapper PROTO((P_)); +void GranSimExec_wrapper PROTO((W_, W_, W_, W_, W_)); +# endif #endif #define DO_GC(args) PerformGC_wrapper(args) #define DO_STACKOVERFLOW(headroom,args) StackOverflow_wrapper(headroom,args) + +# ifdef GRAN + +#define DO_YIELD(args) DO_GRAN_YIELD(args) +#define DO_GRAN_YIELD(liveness) Yield_wrapper(liveness) + +#define DO_PERFORMRESCHEDULE(liveness, always_reenter_node) PerformReschedule_wrapper(liveness, always_reenter_node) +#define DO_GRANSIMALLOCATE(n, node, liveness) GranSimAllocate_wrapper(n, node, liveness) +#define DO_GRANSIMUNALLOCATE(n, node, liveness) GranSimUnallocate_wrapper(n, node, liveness) +#define DO_GRANSIMFETCH(node) GranSimFetch_wrapper(node) +#define DO_GRANSIMEXEC(arith,branch,load,store,floats) GranSimExec_wrapper(arith,branch,load,store,floats) + +# else + #define DO_YIELD(args) Yield_wrapper(args) +# endif + #endif /* __GNUC__ && __STG_GCC_REGS__ */ \end{code} @@ -185,7 +222,7 @@ void Yield_wrapper PROTO((W_)); Call wrappers need to be able to call arbitrary functions, regardless of their arguments and return types. (Okay, we actually only allow up to -five arguments, because on the sparc it gets more complicated to handle +five arguments, because on the SPARC it gets more complicated to handle any more.) The nasty bit is that the return value can be in either an integer register or a floating point register, and we don't know which. (We {\em don't} handle structure returns, and we don't want to.) @@ -200,7 +237,7 @@ chock full of assembly gook for the current platform. These are results, and @MAGIC_RETURN@, which collects all possible results back up again. -For example, in the sparc version, the @SETUP@ guarantees that we +For example, in the SPARC version, the @SETUP@ guarantees that we have enough space to store all of our argument registers for a wee bit, and it gives a `C' name to the register that we're going to use for the call. (It helps to do the call in actual `C' fashion, so that @@ -223,8 +260,7 @@ gets whatever it's after. #if defined(__GNUC__) && defined(__STG_GCC_REGS__) -#if alpha_dec_osf1_TARGET - /* Is this too specific */ +#if alpha_TARGET_ARCH #define MAGIC_CALL_SETUP \ long WeNeedThisSpace[7]; \ @@ -277,7 +313,7 @@ gets whatever it's after. #define SET_RETADDR(loc) { register StgFunPtrFunPtr ra __asm__ ("$26"); loc = ra; } -#define WRAPPER_SETUP(f) SaveAllStgContext(); +#define WRAPPER_SETUP(f,ignore1,ignore2) SaveAllStgContext(); #define WRAPPER_RETURN(x) \ do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); @@ -296,8 +332,7 @@ gets whatever it's after. \begin{code} -#if hppa1_1_hp_hpux_TARGET - /* Is this too specific */ +#if hppa1_1_TARGET_ARCH #define MAGIC_CALL_SETUP \ long SavedIntArgRegs[4]; \ @@ -353,7 +388,7 @@ gets whatever it's after. #define SET_RETADDR(loc) __asm__ volatile ("stw %%r2, %0" : "=m" ((void *)(loc))); -#define WRAPPER_SETUP(f) SaveAllStgContext(); +#define WRAPPER_SETUP(f,ignore1,ignore2) SaveAllStgContext(); #define WRAPPER_RETURN(x) \ do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); @@ -371,64 +406,57 @@ gets whatever it's after. %************************************************************************ \begin{code} - -#if i386_TARGET_ARCH || i486_TARGET_ARCH +#if i386_TARGET_ARCH /* modelled loosely on SPARC stuff */ /* NB: no MAGIC_CALL_SETUP, MAGIC_CALL, or MAGIC_RETURN! */ -#define WRAPPER_NAME(f) __asm__("L" #f "_wrapper") +#define WRAPPER_NAME(f) /*nothing*/ +#if defined(solaris2_TARGET_OS) || defined(linux_TARGET_OS) +#define REAL_NAME(f) #f +#else #define REAL_NAME(f) "_" #f +#endif -/* when we come into PerformGC_wrapper: +/* + Threaded code needs to be able to grab the return address, in case we have + an intervening context switch. + */ - - %esp holds Hp (!); get it into 80(%ebx) -- quick! +#define SET_RETADDR(loc,val) loc = val; - - %esp needs to be bumped by (at least) 4, because - C thinks an argument was passed on the stack - (use 64 just for fun) +/* the grab-%eax-quickly HACK is here because we use a VERY SPECIAL + calling convention on iX86 just for calling PerformGC_wrapper. + (WDP 95/09) - - %eax holds the argument for PerformGC + NB: mangler makes sure that __temp_{eax,esp} get loaded. + (This is about as ugly as it can get.) +*/ - - 104(%ebx) hold the return address -- address we want to - go back to +#define WRAPPER_SETUP(f,ret_addr,args) \ + __asm__ volatile ( \ + "movl " REAL_NAME(__temp_esp) ",%%edx\n" \ + "\tmovl (%%edx),%0\n" \ + "\tmovl " REAL_NAME(__temp_eax) ",%1" \ + : "=r" (ret_addr), "=r" (args) ); \ + SaveAllStgContext(ret_addr); - - 100(%ebx) holds a %esp value that we can re-load with - if need be +/* Note re WRAPPER_SETUP: we have special code just for PerformGC_wrapper; + pls see its definition. WDP 95/09 + Also note the EXTREMELY UGLY slamming in of an "sp_offset"; the + return address *is* on the stack, but it is hard to get there + before GCC has moved the sp pointer... WDP 95/11 */ -#define WRAPPER_SETUP(f) \ - __asm__ volatile ( \ - ".globl " REAL_NAME(f) "_wrapper\n" \ - REAL_NAME(f) "_wrapper:\n" \ - "\tmovl %%esp,80(%%ebx)\n" \ - "\tmovl 100(%%ebx),%%esp\n" \ - "\tmovl %%eax,%0" : "=r" (args)); \ - __asm__ volatile ( \ - "movl %%esp,%0\n" \ - "\tsubl $64,%%esp" \ - : "=r" (SP_stack[++SP_stack_ptr])); \ - SaveAllStgContext(); - -#define WRAPPER_RETURN(x) \ - do {P_ foo; \ - RestoreAllStgRegs(); \ - if(x) JMP_(EnterNodeCode); /* never used? */ \ - __asm__ volatile ( \ - "movl %1,%0\n" \ - "\tmovl %0,_MainRegTable+100" \ - : "=r" (foo) : "m" (SP_stack[SP_stack_ptr--]) ); \ - __asm__ volatile ( \ - "movl 80(%ebx),%esp\n" \ - "\tjmp *104(%ebx)" ); \ - } while(0); + +#define WRAPPER_RETURN(x) \ + do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); #define SEPARATE_WRAPPER_RESTORE /* none */ #endif /* iX86 */ - \end{code} %************************************************************************ @@ -465,7 +493,7 @@ gets whatever it's after. #define WRAPPER_NAME(f) /* nothing */ -#define WRAPPER_SETUP(f) SaveAllStgContext(); +#define WRAPPER_SETUP(f,ignore1,ignore2) SaveAllStgContext(); #define WRAPPER_RETURN(x) \ do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); @@ -512,7 +540,7 @@ gets whatever it's after. #define WRAPPER_NAME(f) /* nothing */ -#define WRAPPER_SETUP(f) SaveAllStgContext(); +#define WRAPPER_SETUP(f,ignore1,ignore2) SaveAllStgContext(); #define WRAPPER_RETURN(x) \ do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); @@ -524,12 +552,57 @@ gets whatever it's after. %************************************************************************ %* * -\subsubsection[sparc-magic]{Call-wrapper MAGIC for SPARC} +\subsubsection[powerpc-magic]{Call-wrapper MAGIC for PowerPC} %* * %************************************************************************ \begin{code} +#if powerpc_TARGET_ARCH + +/* shift 4 arg registers down one */ + +#define MAGIC_CALL_SETUP \ + register void (*f)() __asm__("$2"); \ + __asm__ volatile ( \ + "move $2,$4\n" \ + "\tmove $4,$5\n" \ + "\tmove $5,$6\n" \ + "\tmove $6,$7\n" \ + "\tlw $7,16($sp)\n" \ + "\taddu $sp,$sp,4\n" \ + : : : "$2" ); +#define MAGIC_CALL \ + (*f)(); \ + __asm__ volatile ( \ + "subu $sp,$sp,4\n" \ + "\ts.d $f0, -8($sp)\n" \ + "\tsw $2, -12($sp)"); + +#define MAGIC_RETURN \ + __asm__ volatile ( \ + "l.d $f0, -8($sp)\n" \ + "\tlw $2, -12($sp)"); + +#define WRAPPER_NAME(f) /* nothing */ + +#define WRAPPER_SETUP(f,ignore1,ignore2) SaveAllStgContext(); + +#define WRAPPER_RETURN(x) \ + do {RestoreAllStgRegs(); if(x) JMP_(EnterNodeCode);} while(0); + +#define SEPARATE_WRAPPER_RESTORE /* none */ + +#endif /* powerpc */ +\end{code} + +%************************************************************************ +%* * +\subsubsection[sparc-magic]{Call-wrapper MAGIC for SPARC} +%* * +%************************************************************************ + +\begin{code} #if sparc_TARGET_ARCH #define MAGIC_CALL_SETUP \ @@ -540,6 +613,10 @@ gets whatever it's after. "\tstd %i2,[%fp-32]\n" \ "\tstd %i4,[%fp-24]"); +/* Lest GCC attempt to stick something in + the delay slot: with compile with + -fno-delayed-branch. A weak solution. WDP 96/07 +*/ #define MAGIC_CALL \ __asm__ volatile ( \ "ld [%%fp-40],%%o5\n" \ @@ -553,6 +630,30 @@ gets whatever it's after. __asm__ volatile ( \ "std %f0,[%fp-40]\n" \ "\tstd %o0,[%fp-32]"); +#if 0 +/* We leave nothing to chance here; we have seen + GCC stick "unwanted" code in the branch delay + slot, causing mischief (WDP 96/05) +*/ +/* the problem with this one: GCC has no way of + knowing there is a "call" in there, so it + does not do any calling-convention stuff + (e.g., saving used regs). WDP 96/07 +*/ +#define MAGIC_CALL \ + __asm__ volatile ( \ + "ld [%%fp-40],%%o5\n" \ + "\tld [%%fp-36],%%o0\n" \ + "\tld [%%fp-32],%%o1\n" \ + "\tld [%%fp-28],%%o2\n" \ + "\tld [%%fp-24],%%o3\n" \ + "\tld [%%fp-20],%%o4\n" \ + "\tcall %%o5\n" \ + "\tnop\n" \ + "\tstd %%f0,[%%fp-40]\n"\ + "\tstd %%o0,[%%fp-32]" \ + : : : "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o7", "%f0", "memory"); +#endif /* 0 */ #define MAGIC_RETURN \ __asm__ volatile ( \ @@ -560,10 +661,10 @@ gets whatever it's after. "\tldd [%fp-32],%i0"); /* - We rename the entry points for wrappers so that we can - introduce a new entry point after the prologue. We want to ensure - that the register window does not slide! However, we insert a - call to abort() to make gcc _believe_ that the window slid. + We rename the entry points for wrappers so that we can introduce a + new entry point after the prologue. We want to ensure that the + register window does not slide! However, we insert a call to + abort() to make gcc _believe_ that the window slid. */ #define WRAPPER_NAME(f) __asm__("L" #f "_wrapper") @@ -574,7 +675,7 @@ gets whatever it's after. #define REAL_NAME(f) "_" #f #endif -#define WRAPPER_SETUP(f) \ +#define WRAPPER_SETUP(f,ignore1,ignore2) \ __asm__ volatile ( \ ".global " REAL_NAME(f) "_wrapper\n"\ REAL_NAME(f) "_wrapper:\n" \ @@ -586,15 +687,17 @@ gets whatever it's after. "\tmov %i0,%o0\n" \ "\tmov %i1,%o1"); /* - * In the above, we want to ensure that the arguments are both in the %i registers - * and the %o registers, with the assumption that gcc will expect them now to be in - * one or the other. This is a terrible hack. + * In the above, we want to ensure that the arguments are both in the + * %i registers and the %o registers, with the assumption that gcc + * will expect them now to be in one or the other. This is a terrible + * hack. */ /* - Threaded code needs to be able to grab the return address, in case we have - an intervening context switch. Note that we want the address of the next - instruction to be executed, so we add 8 to the link address. + Threaded code needs to be able to grab the return address, in case + we have an intervening context switch. Note that we want the + address of the next instruction to be executed, so we add 8 to the + link address. */ #define SET_RETADDR(loc) \