X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FStgCRun.c;h=cf210d204fdb04fb74834142d0713038d8394856;hb=153b9cb9b11e05c4edb1b6bc0a7b972660e41f70;hp=fb7179f75eff1e43d2f239c5c5bee0c5f3081b54;hpb=1da969c52be2e56893625957162cf56dd1168ec9;p=ghc-hetmet.git diff --git a/ghc/rts/StgCRun.c b/ghc/rts/StgCRun.c index fb7179f..cf210d2 100644 --- a/ghc/rts/StgCRun.c +++ b/ghc/rts/StgCRun.c @@ -1,7 +1,6 @@ /* ----------------------------------------------------------------------------- - * $Id: StgCRun.c,v 1.39 2003/06/09 13:17:41 matthewc Exp $ * - * (c) The GHC Team, 1998-2000 + * (c) The GHC Team, 1998-2003 * * STG-to-C glue. * @@ -50,8 +49,8 @@ * 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 +#include "ghcconfig.h" +#ifdef alpha_HOST_ARCH #define alpha_EXTRA_CAREFUL register long fake_ra __asm__("$26"); register long fake_gp __asm__("$29"); @@ -68,9 +67,11 @@ register double fake_f9 __asm__("$f9"); #include "Stg.h" #include "Rts.h" #include "StgRun.h" +#include "RtsFlags.h" +#include "OSThreads.h" +#include "Capability.h" #ifdef DEBUG -#include "RtsFlags.h" #include "RtsUtils.h" #include "Printer.h" #endif @@ -81,22 +82,22 @@ register double fake_f9 __asm__("$f9"); any architecture (using miniinterpreter) -------------------------------------------------------------------------- */ -extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED) +StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg STG_UNUSED) { - while (f) { - IF_DEBUG(interpreter, - fprintf(stderr,"Jumping to "); - printPtr((P_)f); fflush(stdout); - fprintf(stderr,"\n"); - ); - f = (StgFunPtr) (f)(); - } - return (StgThreadReturnCode)R1.i; + while (f) { + if (RtsFlags[0].DebugFlags.interpreter) { + debugBelch("Jumping to "); + printPtr((P_)f); fflush(stdout); + debugBelch("\n"); + } + f = (StgFunPtr) (f)(); + } + return (StgThreadReturnCode)R1.i; } -EXTFUN(StgReturn) +StgFunPtr StgReturn(void) { - return 0; + return 0; } #else /* !USE_MINIINTERPRETER */ @@ -111,7 +112,7 @@ EXTFUN(StgReturn) x86 architecture -------------------------------------------------------------------------- */ -#ifdef i386_TARGET_ARCH +#ifdef i386_HOST_ARCH StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) { @@ -164,6 +165,71 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { #endif +/* ---------------------------------------------------------------------------- + x86-64 is almost the same as plain x86. + + I've done it using entirely inline assembler, because I couldn't + get gcc to generate the correct subtraction from %rsp by using + the local array variable trick. It didn't seem to reserve + enough space. Oh well, it's not much harder this way. + + ------------------------------------------------------------------------- */ + +#ifdef x86_64_HOST_ARCH + +extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); + +static void StgRunIsImplementedInAssembler(void) +{ + __asm__ volatile ( + /* + * save callee-saves registers on behalf of the STG code. + */ + ".globl StgRun\n" + "StgRun:\n\t" + "subq %0, %%rsp\n\t" + "movq %%rsp, %%rax\n\t" + "addq %0-48, %%rax\n\t" + "movq %%rbx,0(%%rax)\n\t" + "movq %%rbp,8(%%rax)\n\t" + "movq %%r12,16(%%rax)\n\t" + "movq %%r13,24(%%rax)\n\t" + "movq %%r14,32(%%rax)\n\t" + "movq %%r15,40(%%rax)\n\t" + /* + * Set BaseReg + */ + "movq %%rsi,%%rbx\n\t" + /* + * grab the function argument from the stack, and jump to it. + */ + "movq %%rdi,%%rax\n\t" + "jmp *%%rax\n\t" + + ".global " STG_RETURN "\n" + STG_RETURN ":\n\t" + + "movq %%r13, %%rax\n\t" /* Return value in R1 */ + + /* + * restore callee-saves registers. (Don't stomp on %%rax!) + */ + "movq %%rsp, %%rdx\n\t" + "addq %0-48, %%rdx\n\t" + "movq 0(%%rdx),%%rbx\n\t" /* restore the registers saved above */ + "movq 8(%%rdx),%%rbp\n\t" + "movq 16(%%rdx),%%r12\n\t" + "movq 24(%%rdx),%%r13\n\t" + "movq 32(%%rdx),%%r14\n\t" + "movq 40(%%rdx),%%r15\n\t" + "addq %0, %%rsp\n\t" + "retq" + + : : "i"(RESERVED_C_STACK_BYTES+48 /*stack frame size*/)); +} + +#endif /* x86-64 */ + /* ----------------------------------------------------------------------------- Sparc architecture @@ -195,7 +261,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { Updated info (GHC 4.08.2): not saving %i7 any more (see below). -------------------------------------------------------------------------- */ -#ifdef sparc_TARGET_ARCH +#ifdef sparc_HOST_ARCH StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) { @@ -263,7 +329,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) { tru64unix.compaq.com/docs/base_doc/DOCUMENTATION/V51_PDF/ARH9MBTE.PDF -------------------------------------------------------------------------- */ -#ifdef alpha_TARGET_ARCH +#ifdef alpha_HOST_ARCH StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) @@ -359,13 +425,13 @@ StgRun(StgFunPtr f, StgRegTable *basereg) return ret; } -#endif /* alpha_TARGET_ARCH */ +#endif /* alpha_HOST_ARCH */ /* ----------------------------------------------------------------------------- HP-PA architecture -------------------------------------------------------------------------- */ -#ifdef hppa1_1_TARGET_ARCH +#ifdef hppa1_1_HOST_ARCH StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg) @@ -452,7 +518,7 @@ StgRun(StgFunPtr f, StgRegTable *basereg) return ret; } -#endif /* hppa1_1_TARGET_ARCH */ +#endif /* hppa1_1_HOST_ARCH */ /* ----------------------------------------------------------------------------- PowerPC architecture @@ -461,12 +527,18 @@ StgRun(StgFunPtr f, StgRegTable *basereg) -------------------------------------------------------------------------- */ -#ifdef powerpc_TARGET_ARCH +#ifdef powerpc_HOST_ARCH extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); +#ifdef darwin_HOST_OS static void StgRunIsImplementedInAssembler(void) { +#if HAVE_SUBSECTIONS_VIA_SYMBOLS + // if the toolchain supports deadstripping, we have to + // prevent it here (it tends to get confused here). + __asm__ volatile (".no_dead_strip _StgRunIsImplementedInAssembler"); +#endif __asm__ volatile ( "\n.globl _StgRun\n" "_StgRun:\n" @@ -474,6 +546,7 @@ static void StgRunIsImplementedInAssembler(void) "\tbl saveFP # f14\n" "\tstmw r13,-220(r1)\n" "\tstwu r1,-%0(r1)\n" + "\tmr r27,r4\n" // BaseReg == r27 "\tmtctr r3\n" "\tmr r12,r3\n" "\tbctr\n" @@ -483,8 +556,220 @@ static void StgRunIsImplementedInAssembler(void) "\tla r1,%0(r1)\n" "\tlmw r13,-220(r1)\n" "\tb restFP # f14\n" - : : "i"(RESERVED_C_STACK_BYTES+288 /*stack frame size*/)); + : : "i"(RESERVED_C_STACK_BYTES+224 /*stack frame size*/)); } +#else + +// This version is for PowerPC Linux. + +// Differences from the Darwin/Mac OS X version: +// *) Different Assembler Syntax +// *) Doesn't use Register Saving Helper Functions (although they exist somewhere) +// *) We may not access positive stack offsets +// (no "Red Zone" as in the Darwin ABI) +// *) The Link Register is saved to a different offset in the caller's stack frame +// (Linux: 4(r1), Darwin 8(r1)) + +static void StgRunIsImplementedInAssembler(void) +{ + __asm__ volatile ( + "\t.globl StgRun\n" + "\t.type StgRun,@function\n" + "StgRun:\n" + "\tmflr 0\n" + "\tstw 0,4(1)\n" + "\tmr 5,1\n" + "\tstwu 1,-%0(1)\n" + "\tstmw 13,-220(5)\n" + "\tstfd 14,-144(5)\n" + "\tstfd 15,-136(5)\n" + "\tstfd 16,-128(5)\n" + "\tstfd 17,-120(5)\n" + "\tstfd 18,-112(5)\n" + "\tstfd 19,-104(5)\n" + "\tstfd 20,-96(5)\n" + "\tstfd 21,-88(5)\n" + "\tstfd 22,-80(5)\n" + "\tstfd 23,-72(5)\n" + "\tstfd 24,-64(5)\n" + "\tstfd 25,-56(5)\n" + "\tstfd 26,-48(5)\n" + "\tstfd 27,-40(5)\n" + "\tstfd 28,-32(5)\n" + "\tstfd 29,-24(5)\n" + "\tstfd 30,-16(5)\n" + "\tstfd 31,-8(5)\n" + "\tmr 27,4\n" // BaseReg == r27 + "\tmtctr 3\n" + "\tmr 12,3\n" + "\tbctr\n" + ".globl StgReturn\n" + "\t.type StgReturn,@function\n" + "StgReturn:\n" + "\tmr 3,14\n" + "\tla 5,%0(1)\n" + "\tlmw 13,-220(5)\n" + "\tlfd 14,-144(5)\n" + "\tlfd 15,-136(5)\n" + "\tlfd 16,-128(5)\n" + "\tlfd 17,-120(5)\n" + "\tlfd 18,-112(5)\n" + "\tlfd 19,-104(5)\n" + "\tlfd 20,-96(5)\n" + "\tlfd 21,-88(5)\n" + "\tlfd 22,-80(5)\n" + "\tlfd 23,-72(5)\n" + "\tlfd 24,-64(5)\n" + "\tlfd 25,-56(5)\n" + "\tlfd 26,-48(5)\n" + "\tlfd 27,-40(5)\n" + "\tlfd 28,-32(5)\n" + "\tlfd 29,-24(5)\n" + "\tlfd 30,-16(5)\n" + "\tlfd 31,-8(5)\n" + "\tmr 1,5\n" + "\tlwz 0,4(1)\n" + "\tmtlr 0\n" + "\tblr\n" + : : "i"(RESERVED_C_STACK_BYTES+224 /*stack frame size*/)); +} +#endif + +#endif + +/* ----------------------------------------------------------------------------- + PowerPC 64 architecture + + Everything is in assembler, so we don't have to deal with GCC... + + -------------------------------------------------------------------------- */ + +#ifdef powerpc64_HOST_ARCH + +#ifdef linux_HOST_OS +extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg); + +static void StgRunIsImplementedInAssembler(void) +{ + // r0 volatile + // r1 stack pointer + // r2 toc - needs to be saved + // r3-r10 argument passing, volatile + // r11, r12 very volatile (not saved across cross-module calls) + // r13 thread local state (never modified, don't need to save) + // r14-r31 callee-save + __asm__ volatile ( + ".section \".opd\",\"aw\"\n" + ".align 3\n" + ".globl StgRun\n" + "StgRun:\n" + "\t.quad\t.StgRun,.TOC.@tocbase,0\n" + "\t.size StgRun,24\n" + ".globl StgReturn\n" + "StgReturn:\n" + "\t.quad\t.StgReturn,.TOC.@tocbase,0\n" + "\t.size StgReturn,24\n" + ".previous\n" + ".globl .StgRun\n" + ".type .StgRun,@function\n" + ".StgRun:\n" + "\tmflr 0\n" + "\tmr 5, 1\n" + "\tstd 0, 16(1)\n" + "\tstdu 1, -%0(1)\n" + "\tstd 2, -296(5)\n" + "\tstd 14, -288(5)\n" + "\tstd 15, -280(5)\n" + "\tstd 16, -272(5)\n" + "\tstd 17, -264(5)\n" + "\tstd 18, -256(5)\n" + "\tstd 19, -248(5)\n" + "\tstd 20, -240(5)\n" + "\tstd 21, -232(5)\n" + "\tstd 22, -224(5)\n" + "\tstd 23, -216(5)\n" + "\tstd 24, -208(5)\n" + "\tstd 25, -200(5)\n" + "\tstd 26, -192(5)\n" + "\tstd 27, -184(5)\n" + "\tstd 28, -176(5)\n" + "\tstd 29, -168(5)\n" + "\tstd 30, -160(5)\n" + "\tstd 31, -152(5)\n" + "\tstfd 14, -144(5)\n" + "\tstfd 15, -136(5)\n" + "\tstfd 16, -128(5)\n" + "\tstfd 17, -120(5)\n" + "\tstfd 18, -112(5)\n" + "\tstfd 19, -104(5)\n" + "\tstfd 20, -96(5)\n" + "\tstfd 21, -88(5)\n" + "\tstfd 22, -80(5)\n" + "\tstfd 23, -72(5)\n" + "\tstfd 24, -64(5)\n" + "\tstfd 25, -56(5)\n" + "\tstfd 26, -48(5)\n" + "\tstfd 27, -40(5)\n" + "\tstfd 28, -32(5)\n" + "\tstfd 29, -24(5)\n" + "\tstfd 30, -16(5)\n" + "\tstfd 31, -8(5)\n" + "\tmr 27, 4\n" // BaseReg == r27 + "\tld 2, 8(3)\n" + "\tld 3, 0(3)\n" + "\tmtctr 3\n" + "\tbctr\n" + ".globl .StgReturn\n" + ".type .StgReturn,@function\n" + ".StgReturn:\n" + "\tmr 3,14\n" + "\tla 5, %0(1)\n" // load address == addi r5, r1, %0 + "\tld 2, -296(5)\n" + "\tld 14, -288(5)\n" + "\tld 15, -280(5)\n" + "\tld 16, -272(5)\n" + "\tld 17, -264(5)\n" + "\tld 18, -256(5)\n" + "\tld 19, -248(5)\n" + "\tld 20, -240(5)\n" + "\tld 21, -232(5)\n" + "\tld 22, -224(5)\n" + "\tld 23, -216(5)\n" + "\tld 24, -208(5)\n" + "\tld 25, -200(5)\n" + "\tld 26, -192(5)\n" + "\tld 27, -184(5)\n" + "\tld 28, -176(5)\n" + "\tld 29, -168(5)\n" + "\tld 30, -160(5)\n" + "\tld 31, -152(5)\n" + "\tlfd 14, -144(5)\n" + "\tlfd 15, -136(5)\n" + "\tlfd 16, -128(5)\n" + "\tlfd 17, -120(5)\n" + "\tlfd 18, -112(5)\n" + "\tlfd 19, -104(5)\n" + "\tlfd 20, -96(5)\n" + "\tlfd 21, -88(5)\n" + "\tlfd 22, -80(5)\n" + "\tlfd 23, -72(5)\n" + "\tlfd 24, -64(5)\n" + "\tlfd 25, -56(5)\n" + "\tlfd 26, -48(5)\n" + "\tlfd 27, -40(5)\n" + "\tlfd 28, -32(5)\n" + "\tlfd 29, -24(5)\n" + "\tlfd 30, -16(5)\n" + "\tlfd 31, -8(5)\n" + "\tmr 1, 5\n" + "\tld 0, 16(1)\n" + "\tmtlr 0\n" + "\tblr\n" + : : "i"(RESERVED_C_STACK_BYTES+304 /*stack frame size*/)); +} +#else // linux_HOST_OS +#error Only linux support for power64 right now. +#endif #endif @@ -501,7 +786,7 @@ static void StgRunIsImplementedInAssembler(void) loc31: saved gp (gcc 3.3 uses this slot) -------------------------------------------------------------------------- */ -#ifdef ia64_TARGET_ARCH +#ifdef ia64_HOST_ARCH /* the memory stack is rarely used, so 16K is excessive */ #undef RESERVED_C_STACK_BYTES @@ -555,4 +840,3 @@ static void StgRunIsImplementedInAssembler(void) #endif #endif /* !USE_MINIINTERPRETER */ -