[project @ 2001-11-22 15:15:27 by simonmar]
[ghc-hetmet.git] / ghc / rts / StgCRun.c
index d5abf20..46c47fe 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: StgCRun.c,v 1.24 2001/07/24 06:02:21 ken Exp $
+ * $Id: StgCRun.c,v 1.26 2001/08/14 13:40:09 sewardj Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
  *
  * -------------------------------------------------------------------------- */
 
+#include "PosixSource.h"
+
+
+/*
+ * We define the following (unused) global register variables, because for
+ * some reason gcc generates sub-optimal code for StgRun() on the Alpha
+ * (unnecessarily saving extra registers on the stack) if we don't.
+ *
+ * Why do it at the top of this file, rather than near StgRun() below?  Because
+ * gcc doesn't let us define global register variables after any function
+ * 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.
+ */
+#include "config.h"
+#ifdef alpha_TARGET_ARCH
+#undef alpha_EXTRA_CAREFUL
+register long   fake_ra __asm__("$26");
+#ifdef alpha_EXTRA_CAREFUL
+register long   fake_s6 __asm__("$15");
+register double fake_f8 __asm__("$f8");
+register double fake_f9 __asm__("$f9");
+#endif
+#endif
+
 /* include Stg.h first because we want real machine regs in here: we
  * have to get the value of R1 back from Stg land to C land intact.
  */
    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 <setjmp.h>
-#include <string.h> /* for memcpy */
-
-static jmp_buf jmp_environment;
-
-#if 1
-
 extern StgThreadReturnCode StgRun(StgFunPtr f, StgRegTable *basereg)
 {
    while (f) {
@@ -83,144 +98,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
@@ -359,6 +236,30 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
 
 /* -----------------------------------------------------------------------------
    alpha architecture
+
+   "The stack pointer (SP) must at all times denote an address that has octaword
+    alignment. (This restriction has the side effect that the in-memory portion
+    of the argument list, if any, will start on an octaword boundary.) Note that
+    the stack grows toward lower addresses. During a procedure invocation, SP
+    can never be set to a value that is higher than the value of SP at entry to
+    that procedure invocation.
+
+   "The contents of the stack, located above the portion of the argument list
+    (if any) that is passed in memory, belong to the calling procedure. Because
+    they are part of the calling procedure, they should not be read or written
+    by the called procedure, except as specified by indirect arguments or
+    language-controlled up-level references.
+
+   "The SP value might be used by the hardware when raising exceptions and
+    asynchronous interrupts. It must be assumed that the contents of the stack
+    below the current SP value and within the stack for the current thread are
+    continually and unpredictably modified, as specified in the _Alpha
+    Architecture Reference Manual_, and as a result of asynchronous software
+    actions."
+
+   -- 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
    -------------------------------------------------------------------------- */
 
 #ifdef alpha_TARGET_ARCH
@@ -366,52 +267,90 @@ StgRun(StgFunPtr f, StgRegTable *basereg) {
 StgThreadReturnCode
 StgRun(StgFunPtr f, StgRegTable *basereg) 
 {
+    register long   real_ra __asm__("$26"); volatile long   save_ra;
+
+    register long   real_s0 __asm__("$9" ); volatile long   save_s0;
+    register long   real_s1 __asm__("$10"); volatile long   save_s1;
+    register long   real_s2 __asm__("$11"); volatile long   save_s2;
+    register long   real_s3 __asm__("$12"); volatile long   save_s3;
+    register long   real_s4 __asm__("$13"); volatile long   save_s4;
+    register long   real_s5 __asm__("$14"); volatile long   save_s5;
+#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;
+    register double real_f5 __asm__("$f5"); volatile double save_f5;
+    register double real_f6 __asm__("$f6"); volatile double save_f6;
+    register double real_f7 __asm__("$f7"); volatile double save_f7;
+#ifdef alpha_EXTRA_CAREFUL
+    register double real_f8 __asm__("$f8"); volatile double save_f8;
+    register double real_f9 __asm__("$f9"); volatile double save_f9;
+#endif
+
+    register StgFunPtr real_pv __asm__("$27");
+
     StgThreadReturnCode ret;
 
-    __asm__ volatile ("stq $9,-8($30)\n\t"
-                      "stq $10,-16($30)\n\t"
-                      "stq $11,-24($30)\n\t"
-                      "stq $12,-32($30)\n\t"
-                      "stq $13,-40($30)\n\t"
-                      "stq $14,-48($30)\n\t"
-                      "stq $15,-56($30)\n\t"
-                      "stt $f2,-64($30)\n\t"
-                      "stt $f3,-72($30)\n\t"
-                      "stt $f4,-80($30)\n\t"
-                      "stt $f5,-88($30)\n\t"
-                      "stt $f6,-96($30)\n\t"
-                      "stt $f7,-104($30)\n\t"
-                      "stt $f8,-112($30)\n\t"
-                      "stt $f9,-120($30)\n\t"
-                     "lda $30,-%0($30)" : :
-                      "K" (RESERVED_C_STACK_BYTES+
-                          8*sizeof(double)+8*sizeof(long)));
+    save_ra = real_ra;
 
-    f();
+    save_s0 = real_s0;
+    save_s1 = real_s1;
+    save_s2 = real_s2;
+    save_s3 = real_s3;
+    save_s4 = real_s4;
+    save_s5 = real_s5;
+#ifdef alpha_EXTRA_CAREFUL
+    save_s6 = real_s6;
+#endif
+
+    save_f2 = real_f2;
+    save_f3 = real_f3;
+    save_f4 = real_f4;
+    save_f5 = real_f5;
+    save_f6 = real_f6;
+    save_f7 = real_f7;
+#ifdef alpha_EXTRA_CAREFUL
+    save_f8 = real_f8;
+    save_f9 = real_f9;
+#endif
+
+    real_pv = f;
+
+    __asm__ volatile(  "lda $30,-%0($30)"      "\n"
+               "\t"    "jmp ($27)"             "\n"
+               "\t"    ".align 3"              "\n"
+               ".globl " STG_RETURN            "\n"
+               STG_RETURN ":"                  "\n"
+               "\t"    "lda $30,%0($30)"       "\n"
+               : : "K" (RESERVED_C_STACK_BYTES));
+
+    ret = real_s5;
+
+    real_s0 = save_s0;
+    real_s1 = save_s1;
+    real_s2 = save_s2;
+    real_s3 = save_s3;
+    real_s4 = save_s4;
+    real_s5 = save_s5;
+#ifdef alpha_EXTRA_CAREFUL
+    real_s6 = save_s6;
+#endif
+
+    real_f2 = save_f2;
+    real_f3 = save_f3;
+    real_f4 = save_f4;
+    real_f5 = save_f5;
+    real_f6 = save_f6;
+    real_f7 = save_f7;
+#ifdef alpha_EXTRA_CAREFUL
+    real_f8 = save_f8;
+    real_f9 = save_f9;
+#endif
 
-    __asm__ volatile (".align 3\n"
-                             ".globl " STG_RETURN "\n"
-                      STG_RETURN ":\n\t"
-                     "lda %0,($14)\n\t"  /* save R1 */
-                             "lda $30,%1($30)\n\t"
-                             "ldq $9,-8($30)\n\t"
-                             "ldq $10,-16($30)\n\t"
-                             "ldq $11,-24($30)\n\t"
-                             "ldq $12,-32($30)\n\t"
-                             "ldq $13,-40($30)\n\t"
-                             "ldq $14,-48($30)\n\t"
-                             "ldq $15,-56($30)\n\t"
-                             "ldt $f2,-64($30)\n\t"
-                             "ldt $f3,-72($30)\n\t"
-                             "ldt $f4,-80($30)\n\t"
-                             "ldt $f5,-88($30)\n\t"
-                             "ldt $f6,-96($30)\n\t"
-                     "ldt $f7,-104($30)\n\t"
-                     "ldt $f8,-112($30)\n\t" 
-                     "ldt $f9,-120($30)" 
-                     : "=r" (ret)
-                     : "K" (RESERVED_C_STACK_BYTES+
-                          8*sizeof(double)+8*sizeof(long)));
+    real_ra = save_ra;
 
     return ret;
 }