[project @ 2003-09-23 15:31:02 by simonmar]
[ghc-hetmet.git] / ghc / rts / StgCRun.c
index f88f28e..94ee2a5 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
- * $Id: StgCRun.c,v 1.37 2002/12/11 15:36:51 simonmar Exp $
+ * $Id: StgCRun.c,v 1.40 2003/08/29 16:13:48 simonmar Exp $
  *
- * (c) The GHC Team, 1998-2000
+ * (c) The GHC Team, 1998-2003
  *
  * STG-to-C glue.
  *
@@ -164,6 +164,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_TARGET_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
 
@@ -472,18 +537,18 @@ static void StgRunIsImplementedInAssembler(void)
                "_StgRun:\n"
                "\tmflr r0\n"
                "\tbl saveFP # f14\n"
-               "\tstmw r14,-216(r1)\n"
-               "\tstwu r1,-8480(r1)\n"
+               "\tstmw r13,-220(r1)\n"
+               "\tstwu r1,-%0(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"
+               "\tla r1,%0(r1)\n"
+               "\tlmw r13,-220(r1)\n"
                "\tb restFP # f14\n"
-       );      /* RESERVED_C_STACK_BYTES + stack frame size == 8192 + 288 == 8480 */
+       : : "i"(RESERVED_C_STACK_BYTES+288 /*stack frame size*/));
 }
 
 #endif
@@ -498,6 +563,7 @@ static void StgRunIsImplementedInAssembler(void)
    loc16 - loc28: STG registers
            loc29: saved ar.pfs
            loc30: saved b0
+           loc31: saved gp (gcc 3.3 uses this slot)
    -------------------------------------------------------------------------- */
 
 #ifdef ia64_TARGET_ARCH
@@ -506,12 +572,19 @@ static void StgRunIsImplementedInAssembler(void)
 #undef RESERVED_C_STACK_BYTES
 #define RESERVED_C_STACK_BYTES 1024
 
+#if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)
+/* gcc 3.3+: leave an extra slot for gp saves */
+#define LOCALS 32
+#else
+#define LOCALS 31
+#endif
+
 static void StgRunIsImplementedInAssembler(void)
 {
     __asm__ volatile(
                ".global StgRun\n"
                "StgRun:\n"
-               "\talloc loc29 = ar.pfs, 0, 31, 8, 0\n" /* setup register frame */
+               "\talloc loc29 = ar.pfs, 0, %1, 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 */
@@ -541,7 +614,7 @@ static void StgRunIsImplementedInAssembler(void)
                "\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));
+       : : "i"(RESERVED_C_STACK_BYTES + 6*16), "i"(LOCALS));
 }
 
 #endif