[project @ 1999-10-29 13:41:23 by sewardj]
[ghc-hetmet.git] / ghc / rts / Evaluator.c
index f7c8147..2c04e55 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (c) 1994-1998.
  *
  * $RCSfile: Evaluator.c,v $
- * $Revision: 1.17 $
- * $Date: 1999/07/06 16:40:24 $
+ * $Revision: 1.23 $
+ * $Date: 1999/10/29 13:41:29 $
  * ---------------------------------------------------------------------------*/
 
 #include "Rts.h"
 #include "Storage.h"
 #include "SchedAPI.h" /* for createGenThread */
 #include "Schedule.h" /* for context_switch  */
-
 #include "Bytecodes.h"
 #include "Assembler.h" /* for CFun stuff */
 #include "ForeignCall.h"
-#include "StablePriv.h"
 #include "PrimOps.h"   /* for __{encode,decode}{Float,Double} */
 #include "Evaluator.h"
 
 #ifdef DEBUG
 #include "Printer.h"
 #include "Disassembler.h"
-
 #include "Sanity.h"
 #include "StgRun.h"
 #endif
@@ -48,7 +45,6 @@
 #error Non-standalone integer not yet supported
 #endif
 
-
 /* An incredibly useful abbreviation.
  * Interestingly, there are some uses of END_TSO_QUEUE_closure that
  * can't use it because they use the closure at type StgClosure* or
 #define USE_GCC_LABELS 0
 #endif
 
+/* Make it possible for the evaluator to get hold of bytecode
+   for a given function by name.  Useful but a hack.  Sigh.
+ */
+extern void* getHugs_AsmObject_for ( char* s );
+
+
 /* --------------------------------------------------------------------------
  * Crude profiling stuff (mainly to assess effect of optimiser)
  * ------------------------------------------------------------------------*/
@@ -233,13 +235,24 @@ void cp_show ( void )
  * Hugs Hooks - a bit of a hack
  * ------------------------------------------------------------------------*/
 
-/* A total hack -- this code has an endian dependancy and only works
-   on little-endian archs.
-*/
 void setRtsFlags( int x );
 void setRtsFlags( int x )
 {
-    *(int*)(&(RtsFlags.DebugFlags)) = x;
+    unsigned int w    = 0x12345678;
+    unsigned char* pw = (unsigned char *)&w;
+    if (*pw == 0x78) {
+       /* little endian */
+       *(int*)(&(RtsFlags.DebugFlags)) = x;
+    } else {
+       /* big endian */
+       unsigned int w1 = x;
+       unsigned int w2 = 0;
+       w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
+       w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
+       w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
+       w2 |= (w1 && 0xFF); w2 <<= 8; w1 >>= 8;
+       *(int*)(&(RtsFlags.DebugFlags)) = (int)w2;
+    }
 }
 
 /* --------------------------------------------------------------------------
@@ -247,7 +260,7 @@ void setRtsFlags( int x )
  *
  * ToDo: figure out why these are being used and crush them!
  * ------------------------------------------------------------------------*/
-
+#if 0
 void OnExitHook (void)
 {
 }
@@ -270,7 +283,7 @@ void defaultsHook (void)
 {
     /* do nothing */
 }
-
+#endif
 
 /* --------------------------------------------------------------------------
  * Entering-objects and bytecode interpreter part of evaluator
@@ -300,7 +313,7 @@ void defaultsHook (void)
 
 /* Forward decls ... */
 static        void* enterBCO_primop1 ( int );
-static        void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */ );
+static        void* enterBCO_primop2 ( int , int* /*StgThreadReturnCode* */, StgBCO** );
 static inline void PopUpdateFrame ( StgClosure* obj );
 static inline void PopCatchFrame  ( void );
 static inline void PopSeqFrame    ( void );
@@ -337,7 +350,11 @@ void      SloppifyIntegerEnd ( StgPtr );
 #define LLL { xSp = Sp; xSu = Su; xSpLim = SpLim; }
 #endif
 
-#define RETURN(vvv) { StgThreadReturnCode retVal=(vvv); SSS; return retVal; }
+#define RETURN(vvv) {                                         \
+           StgThreadReturnCode retVal=(vvv); SSS;             \
+           /* SaveThreadState() is done by the scheduler. */  \
+           return retVal;                                     \
+        }
 
 
 /* Macros to operate directly on the pulled-out machine state.
@@ -385,6 +402,12 @@ void      SloppifyIntegerEnd ( StgPtr );
 #define xPopTaggedAddr()        ((xSp++,xSp+=sizeofW(StgAddr), \
                                  (StgAddr)(*(xSp-sizeofW(StgAddr)))))
 
+#define xPushTaggedStable(xxx)  { xSp -= sizeofW(StgStablePtr); \
+                                  *xSp = (StgWord)(xxx); xPushTag(STABLE_TAG); }
+#define xTaggedStackStable(iii) ((StgStablePtr)(*(xSp+1+(iii))))
+#define xPopTaggedStable()      ((xSp++,xSp+=sizeofW(StgStablePtr), \
+                                 (StgStablePtr)(*(xSp-sizeofW(StgStablePtr)))))
+
 #define xPushTaggedChar(xxx)    { xSp -= sizeofW(StgChar); \
                                   *xSp = (StgWord)(xxx); xPushTag(CHAR_TAG); }
 #define xTaggedStackChar(iii)   ((StgChar)(*(xSp+1+(iii))))
@@ -440,7 +463,11 @@ StgThreadReturnCode enter( StgClosure* obj0 )
 
 #ifdef DEBUG
     /* use the t values to check that Su/Sp/SpLim do not change unexpectedly */
-    StgPtr tSp = Sp; StgUpdateFrame* tSu = Su; StgPtr tSpLim = SpLim;
+    StgPtr tSp; StgUpdateFrame* tSu; StgPtr tSpLim;
+#endif
+    /* LoadThreadState() is done by the scheduler. */
+#ifdef DEBUG
+    tSp = Sp; tSu = Su; tSpLim = SpLim;
 #endif
 
     obj    = obj0;
@@ -975,7 +1002,7 @@ StgThreadReturnCode enter( StgClosure* obj0 )
                 }
             Case(i_UNPACK_ADDR):
                 {
-                    StgClosure* con = stgCast(StgClosure*,xStackPtr(0));
+                    StgClosure* con = (StgClosure*)xStackPtr(0);
                     /* ASSERT(isAddrLike(con)); */
                     xPushTaggedAddr(payloadPtr(con,0));
                     Continue;
@@ -1085,38 +1112,30 @@ StgThreadReturnCode enter( StgClosure* obj0 )
                 }
             Case(i_VAR_STABLE):
                 {   
-                    fprintf(stderr, "unimp: i_VAR_STABLE\n" ); exit(0);
-                    /*fix side effects here ...*/
-                    /*
-                    xPushTaggedStablePtr(xTaggedStackStable(BCO_INSTR_8));
-                    */
+                    StgStablePtr s = xTaggedStackStable(BCO_INSTR_8);
+                    xPushTaggedStable(s);
                     Continue;
                 }
             Case(i_PACK_STABLE):
                 {
-                   //StgClosure* o;
-                    fprintf(stderr, "unimp: i_PACK_STABLE\n" ); exit(0);
-                    /*
+                    StgClosure* o;
                     SSS; o = (StgClosure*)grabHpNonUpd(Stablezh_sizeW); LLL;
                     SET_HDR(o,&StablePtr_con_info,??);
-                    payloadWord(o,0) = xPopTaggedStablePtr();
+                    payloadWord(o,0) = xPopTaggedStable();
                     IF_DEBUG(evaluator,
                              fprintf(stderr,"\tBuilt "); 
+                             SSS;
                              printObj(stgCast(StgClosure*,o));
+                             LLL;
                              );
                     xPushPtr(stgCast(StgPtr,o));
-                    */
                     Continue;
                 }
             Case(i_UNPACK_STABLE):
                 {
-                   //StgClosure* con;
-                    fprintf(stderr, "unimp: i_UNPACK_STABLE\n" ); exit(0);
-                    /*
-                    con = stgCast(StgClosure*,xStackPtr(0));
-                    ASSERT(isStableLike(con));
-                    xPushTaggedStablePtr(payloadWord(con,0));
-                    */
+                    StgClosure* con = (StgClosure*)xStackPtr(0);
+                    /* ASSERT(isStableLike(con)); */
+                    xPushTaggedStable(payloadWord(con,0));
                     Continue;
                 }
             Case(i_PRIMOP1):
@@ -1130,11 +1149,19 @@ StgThreadReturnCode enter( StgClosure* obj0 )
                 }
             Case(i_PRIMOP2):
                 {
-                    int   i, trc;
-                    void* p;
-                    trc = 12345678;  /* Hope that no StgThreadReturnCode has this value */
-                    i   = BCO_INSTR_8;
-                    SSS; p = enterBCO_primop2 ( i, &trc ); LLL;
+                 /* Remember to save  */
+                    int      i, trc, pc_saved;
+                    void*    p;
+                    StgBCO*  bco_tmp;
+                    trc      = 12345678; /* Assume != any StgThreadReturnCode */
+                    i        = BCO_INSTR_8;
+                    pc_saved = PC; 
+                    bco_tmp  = bco;
+                    SSS;
+                    p        = enterBCO_primop2 ( i, &trc, &bco_tmp ); 
+                    LLL;
+                    bco      = bco_tmp;
+                    bciPtr   = &(bcoInstr(bco,pc_saved));
                     if (p) {
                        if (trc == 12345678) {
                           /* we want to enter p */
@@ -1315,13 +1342,16 @@ StgThreadReturnCode enter( StgClosure* obj0 )
             }
             obj = ap->fun;
 #ifdef EAGER_BLACKHOLING
+#warn  LAZY_BLACKHOLING is default for StgHugs
+#error Dont know if EAGER_BLACKHOLING works in StgHugs
             {
-                /* superfluous - but makes debugging easier */
-                StgBlackHole* bh = stgCast(StgBlackHole*,ap);
-                SET_INFO(bh,&BLACKHOLE_info);
-                bh->blocking_queue = EndTSOQueue;
-                IF_DEBUG(gccafs,fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
-                /*printObj(bh); */
+            /* superfluous - but makes debugging easier */
+            StgBlackHole* bh = stgCast(StgBlackHole*,ap);
+            SET_INFO(bh,&BLACKHOLE_info);
+            bh->blocking_queue = EndTSOQueue;
+            IF_DEBUG(gccafs,
+                     fprintf(stderr,"Eagerly blackholed AP_UPD %p in evaluator\n",bh));
+            /* printObj(bh); */
             }
 #endif /* EAGER_BLACKHOLING */
             goto enterLoop;
@@ -1376,9 +1406,10 @@ StgThreadReturnCode enter( StgClosure* obj0 )
                         ASSERT(xSp==(P_)xSu);
                         IF_DEBUG(evaluator,
                                  SSS;
+                                 fprintf(stderr, "hit a STOP_FRAME\n");
                                  printObj(obj);
-                                 /*fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);*/
-                                 /*printStack(xSp,CurrentTSO->stack+CurrentTSO->stack_size,xSu);*/
+                                 fprintf(stderr,"xSp = %p\txSu = %p\n", xSp, xSu);
+                                 printStack(xSp,CurrentTSO->stack+CurrentTSO->stack_size,xSu);
                                  LLL;
                                  );
                         SSS; PopStopFrame(obj); LLL;
@@ -1400,7 +1431,7 @@ StgThreadReturnCode enter( StgClosure* obj0 )
                 case RET_VEC_SMALL:
                 case RET_BIG:
                 case RET_VEC_BIG:
-                        barf("todo: RET_[VEC_]{BIG,SMALL}");
+                 //       barf("todo: RET_[VEC_]{BIG,SMALL}");
                 default:
                         belch("entered CONSTR with invalid continuation on stack");
                         IF_DEBUG(evaluator,
@@ -1453,6 +1484,9 @@ StgThreadReturnCode enter( StgClosure* obj0 )
 #undef xPushTaggedAddr
 #undef xTaggedStackAddr
 #undef xPopTaggedAddr
+#undef xPushTaggedStable
+#undef xTaggedStackStable
+#undef xPopTaggedStable
 #undef xPushTaggedChar
 #undef xTaggedStackChar
 #undef xPopTaggedChar
@@ -1471,7 +1505,7 @@ StgThreadReturnCode enter( StgClosure* obj0 )
 
 static inline void            PushTag            ( StackTag    t ) 
    { *(--Sp) = t; }
-static inline void            PushPtr            ( StgPtr      x ) 
+       inline void            PushPtr            ( StgPtr      x ) 
    { *(--stgCast(StgPtr*,Sp))  = x; }
 static inline void            PushCPtr           ( StgClosure* x ) 
    { *(--stgCast(StgClosure**,Sp)) = x; }
@@ -1485,7 +1519,7 @@ static inline void            checkTag           ( StackTag t1, StackTag t2 )
    { ASSERT(t1 == t2);}
 static inline void            PopTag             ( StackTag t ) 
    { checkTag(t,*(Sp++));    }
-static inline StgPtr          PopPtr             ( void )       
+       inline StgPtr          PopPtr             ( void )       
    { return *stgCast(StgPtr*,Sp)++; }
 static inline StgClosure*     PopCPtr            ( void )       
    { return *stgCast(StgClosure**,Sp)++; }
@@ -1508,17 +1542,17 @@ static inline void            PushTaggedRealWorld( void            )
    { PushTag(REALWORLD_TAG);  }
        inline void            PushTaggedInt      ( StgInt        x ) 
    { Sp -= sizeofW(StgInt);        *Sp = x;          PushTag(INT_TAG);    }
-static inline void            PushTaggedWord     ( StgWord       x ) 
+       inline void            PushTaggedWord     ( StgWord       x ) 
    { Sp -= sizeofW(StgWord);       *Sp = x;          PushTag(WORD_TAG);   }
-static inline void            PushTaggedAddr     ( StgAddr       x ) 
+       inline void            PushTaggedAddr     ( StgAddr       x ) 
    { Sp -= sizeofW(StgAddr);       *Sp = (W_)x;      PushTag(ADDR_TAG);   }
-static inline void            PushTaggedChar     ( StgChar       x ) 
+       inline void            PushTaggedChar     ( StgChar       x ) 
    { Sp -= sizeofW(StgChar);         *Sp = stgCast(StgWord,x); PushTag(CHAR_TAG); }
-static inline void            PushTaggedFloat    ( StgFloat      x ) 
+       inline void            PushTaggedFloat    ( StgFloat      x ) 
    { Sp -= sizeofW(StgFloat);      ASSIGN_FLT(Sp,x); PushTag(FLOAT_TAG);  }
-static inline void            PushTaggedDouble   ( StgDouble     x ) 
+       inline void            PushTaggedDouble   ( StgDouble     x ) 
    { Sp -= sizeofW(StgDouble);     ASSIGN_DBL(Sp,x); PushTag(DOUBLE_TAG); }
-static inline void            PushTaggedStablePtr   ( StgStablePtr  x ) 
+       inline void            PushTaggedStablePtr   ( StgStablePtr  x ) 
    { Sp -= sizeofW(StgStablePtr);  *Sp = x;          PushTag(STABLE_TAG); }
 static inline void            PushTaggedBool     ( int           x ) 
    { PushTaggedInt(x); }
@@ -1530,22 +1564,22 @@ static inline void            PopTaggedRealWorld ( void )
        inline StgInt          PopTaggedInt       ( void ) 
    { StgInt    r; PopTag(INT_TAG);     r = *stgCast(StgInt*,  Sp);      
      Sp += sizeofW(StgInt);        return r;}
-static inline StgWord         PopTaggedWord      ( void ) 
+       inline StgWord         PopTaggedWord      ( void ) 
    { StgWord   r; PopTag(WORD_TAG);    r = *stgCast(StgWord*, Sp);      
      Sp += sizeofW(StgWord);       return r;}
-static inline StgAddr         PopTaggedAddr      ( void ) 
+       inline StgAddr         PopTaggedAddr      ( void ) 
    { StgAddr   r; PopTag(ADDR_TAG);    r = *stgCast(StgAddr*, Sp);      
      Sp += sizeofW(StgAddr);       return r;}
-static inline StgChar         PopTaggedChar      ( void ) 
+       inline StgChar         PopTaggedChar      ( void ) 
    { StgChar   r; PopTag(CHAR_TAG);    r = stgCast(StgChar, *Sp);       
      Sp += sizeofW(StgChar);       return r;}
-static inline StgFloat        PopTaggedFloat     ( void ) 
+       inline StgFloat        PopTaggedFloat     ( void ) 
    { StgFloat  r; PopTag(FLOAT_TAG);   r = PK_FLT(Sp);                  
      Sp += sizeofW(StgFloat);      return r;}
-static inline StgDouble       PopTaggedDouble    ( void ) 
+       inline StgDouble       PopTaggedDouble    ( void ) 
    { StgDouble r; PopTag(DOUBLE_TAG);  r = PK_DBL(Sp);                  
      Sp += sizeofW(StgDouble);     return r;}
-static inline StgStablePtr    PopTaggedStablePtr    ( void ) 
+       inline StgStablePtr    PopTaggedStablePtr    ( void ) 
    { StgInt    r; PopTag(STABLE_TAG);  r = *stgCast(StgStablePtr*, Sp); 
      Sp += sizeofW(StgStablePtr);  return r;}
 
@@ -1616,6 +1650,8 @@ static inline void PopUpdateFrame( StgClosure* obj )
              fprintf(stderr,"Sp = %p\tSu = %p\n\n", Sp, Su);
              );
 #ifdef EAGER_BLACKHOLING
+#warn  LAZY_BLACKHOLING is default for StgHugs
+#error Dont know if EAGER_BLACKHOLING works in StgHugs
     ASSERT(get_itbl(Su->updatee)->type == BLACKHOLE
            || get_itbl(Su->updatee)->type == SE_BLACKHOLE
            || get_itbl(Su->updatee)->type == CAF_BLACKHOLE
@@ -1642,7 +1678,7 @@ static inline void PushCatchFrame( StgClosure* handler )
     /* ToDo: stack check! */
     Sp -= sizeofW(StgCatchFrame);
     fp = stgCast(StgCatchFrame*,Sp);
-    SET_HDR(fp,&catch_frame_info,CCCS);
+    SET_HDR(fp,(StgInfoTable*)&catch_frame_info,CCCS);
     fp->handler         = handler;
     fp->link            = Su;
     Su = stgCast(StgUpdateFrame*,fp);
@@ -1662,7 +1698,7 @@ static inline void PushSeqFrame( void )
     /* ToDo: stack check! */
     Sp -= sizeofW(StgSeqFrame);
     fp = stgCast(StgSeqFrame*,Sp);
-    SET_HDR(fp,&seq_frame_info,CCCS);
+    SET_HDR(fp,(StgInfoTable*)&seq_frame_info,CCCS);
     fp->link = Su;
     Su = stgCast(StgUpdateFrame*,fp);
 }
@@ -1713,32 +1749,29 @@ static inline StgClosure* raiseAnError( StgClosure* errObj )
     }
 }
 
-static StgClosure* raisePrim(char* msg)
+
+static StgClosure* makeErrorCall ( const char* msg )
 {
-    /* ToDo: figure out some way to turn the msg into a Haskell Exception
-     * Hack: we don't know how to build an Exception but we do know how
-     * to build a (recursive!) error object.
-     * The result isn't pretty but it's (slightly) better than nothing.
-     */
-    nat size = sizeof(StgClosure) + 1;
-    StgClosure* errObj = stgCast(StgClosure*,grabHpNonUpd(size));
-    SET_INFO(errObj,&raise_info);
-    errObj->payload[0] = errObj;
-fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
-#if 0
-    belch(msg);
-#else
-    /* At the moment, I prefer to put it on stdout to make things as
-     * close to Hugs' old behaviour as possible.
-     */
-    fprintf(stdout, "Program error: %s", msg);
-    fflush(stdout);
-#endif
-    return raiseAnError(stgCast(StgClosure*,errObj));
+   /* Note!  the msg string should be allocated in a 
+      place which will not get freed -- preferably 
+      read-only data of the program.  That's because
+      the thunk we build here may linger indefinitely.
+      (thinks: probably not so, but anyway ...)
+   */
+   HaskellObj error 
+      = asmClosureOfObject(getHugs_AsmObject_for("error"));
+   HaskellObj unpack
+      = asmClosureOfObject(getHugs_AsmObject_for("primUnpackString"));
+   HaskellObj thunk
+      = rts_apply ( unpack, rts_mkAddr ( (void*)msg ) );
+   thunk
+      = rts_apply ( error, thunk );
+   return 
+      (StgClosure*) thunk;
 }
 
-#define raiseIndex(where) raisePrim("Array index out of range in " where)
-#define raiseDiv0(where)  raisePrim("Division by 0 in " where)
+#define raiseIndex(where) makeErrorCall("Array index out of range in " where)
+#define raiseDiv0(where)  makeErrorCall("Division by zero in " where)
 
 /* --------------------------------------------------------------------------
  * Evaluator
@@ -1822,6 +1855,12 @@ fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
     PushTaggedWord(e);       \
 }
 
+#define OP_I_s(e)            \
+{                            \
+    StgInt x = PopTaggedInt();  \
+    PushTaggedStablePtr(e);  \
+}
+
 #define OP__F(e)             \
 {                            \
     PushTaggedFloat(e);      \
@@ -1864,6 +1903,12 @@ fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
     PushTaggedInt(e);         \
 }
 
+#define OP_s_I(e)             \
+{                             \
+    StgStablePtr x = PopTaggedStablePtr(); \
+    PushTaggedInt(e);         \
+}
+
 #define OP_W_W(e)             \
 {                             \
     StgWord x = PopTaggedWord(); \
@@ -1927,7 +1972,7 @@ fprintf(stderr, "\n\n\nRAISE PRIM %s\n", msg);
     int  y = PopTaggedInt();  \
     StgStablePtr r;           \
     s;                        \
-    PushTaggedStablePtr(r);      \
+    PushTaggedStablePtr(r);   \
 }
 #define OP_AIC_(s)            \
 {                             \
@@ -2092,7 +2137,7 @@ void SloppifyIntegerEnd ( StgPtr arr0 )
       do_renormalise(b);
       ASSERT(is_sane(b));
       arr->words -= nwunused;
-      slop = &(arr->payload[arr->words]);
+      slop = (StgArrWords*)&(arr->payload[arr->words]);
       SET_HDR(slop,&ARR_WORDS_info,CCCS);
       slop->words = nwunused - sizeofW(StgArrWords);
       ASSERT( &(slop->payload[slop->words]) == 
@@ -2236,8 +2281,7 @@ static void* enterBCO_primop1 ( int primop1code )
                     return (raiseDiv0("quotInt"));
                 }
                 /* ToDo: protect against minInt / -1 errors
-                 * (repeat for all other division primops)
-                                */
+                 * (repeat for all other division primops) */
                 PushTaggedInt(x/y);
             }
             break;
@@ -2334,6 +2378,9 @@ static void* enterBCO_primop1 ( int primop1code )
         case i_intToAddr:       OP_I_A((StgAddr)x);  break;  /*  ToDo */
         case i_addrToInt:       OP_A_I((StgInt)x);   break;  /* ToDo */
 
+        case i_intToStable:     OP_I_s(x);           break;
+        case i_stableToInt:     OP_s_I(x);           break;
+
         case i_indexCharOffAddr:   OP_AI_C(indexCharOffAddrzh(r,x,y));      break;
         case i_readCharOffAddr:    OP_AI_C(indexCharOffAddrzh(r,x,y));      break;
         case i_writeCharOffAddr:   OP_AIC_(writeCharOffAddrzh(x,y,z));      break;
@@ -2354,11 +2401,9 @@ static void* enterBCO_primop1 ( int primop1code )
         case i_readDoubleOffAddr:  OP_AI_D(indexDoubleOffAddrzh(r,x,y));    break;
         case i_writeDoubleOffAddr: OP_AID_(writeDoubleOffAddrzh(x,y,z));    break;
 
-#ifdef PROVIDE_STABLE
         case i_indexStableOffAddr: OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
         case i_readStableOffAddr:  OP_AI_s(indexStablePtrOffAddrzh(r,x,y)); break;
         case i_writeStableOffAddr: OP_AIs_(writeStablePtrOffAddrzh(x,y,z)); break;
-#endif
 
 #ifdef STANDALONE_INTEGER
         case i_compareInteger:     
@@ -2448,11 +2493,6 @@ static void* enterBCO_primop1 ( int primop1code )
             {
                 StgFloat x = PopTaggedFloat();
                 StgFloat y = PopTaggedFloat();
-#if 0
-                if (y == 0) {
-                    return (raiseDiv0("divideFloat"));
-                }
-#endif
                 PushTaggedFloat(x/y);
             }
             break;
@@ -2519,11 +2559,6 @@ static void* enterBCO_primop1 ( int primop1code )
             {
                 StgDouble x = PopTaggedDouble();
                 StgDouble y = PopTaggedDouble();
-#if 0
-                if (y == 0) {
-                    return (raiseDiv0("divideDouble"));
-                }
-#endif
                 PushTaggedDouble(x/y);
             }
             break;
@@ -2593,7 +2628,8 @@ static void* enterBCO_primop1 ( int primop1code )
       set *return2 to it and return a non-NULL value.
 */
 static void* enterBCO_primop2 ( int primop2code, 
-                                int* /*StgThreadReturnCode* */ return2 )
+                                int* /*StgThreadReturnCode* */ return2,
+                                StgBCO** bco )
 {
         switch (primop2code) {
         case i_raise:  /* raise#{err} */
@@ -2713,8 +2749,8 @@ static void* enterBCO_primop2 ( int primop2code,
             }
 
         /* Most of these generate alignment warnings on Sparcs and similar architectures.
-                        * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
-                        */
+         * These are harmless and are caused by the cast to C* in BYTE_ARR_CTS.
+         */
         case i_indexCharArray:   
             OP_mI_ty(Char,"indexCharArray",    indexCharArrayzh(r,x,i)); break;
         case i_readCharArray:    
@@ -2750,6 +2786,7 @@ static void* enterBCO_primop2 ( int primop2code,
         case i_writeDoubleArray: 
             OP_mIty_(Double,"writeDoubleArray", writeDoubleArrayzh(x,i,z)); break;
 
+#if 0
 #ifdef PROVIDE_STABLE
         case i_indexStableArray: 
             OP_mI_ty(StablePtr,"indexStableArray", indexStablePtrArrayzh(r,x,i)); break;
@@ -2758,7 +2795,7 @@ static void* enterBCO_primop2 ( int primop2code,
         case i_writeStableArray: 
             OP_mIty_(StablePtr,"writeStableArray", writeStablePtrArrayzh(x,i,z)); break;
 #endif
-
+#endif
 
 
 
@@ -2812,54 +2849,60 @@ static void* enterBCO_primop2 ( int primop2code,
                     PushCPtr(w->value); /* last result  */
                     PushTaggedInt(1);   /* first result */
                 } else {
-                    PushPtr(stgCast(StgPtr,w)); /* ToDo: error thunk would be better */
+                    PushPtr(stgCast(StgPtr,w)); 
+                           /* ToDo: error thunk would be better */
                     PushTaggedInt(0);
                 }
                 break;
             }
 #endif /* PROVIDE_WEAK */
-#ifdef PROVIDE_STABLE
-                /* StablePtr# operations */
-        case i_makeStablePtr: 
-        case i_deRefStablePtr: 
-        case i_freeStablePtr: 
-           { fprintf(stderr,"Evaluator.c:stablePtrOp unimp\n" );
-                          exit(1); };
 
-#if 0
-                       ToDo: reinstate
         case i_makeStablePtr:
             {
-                StgStablePtr stable_ptr;
-                if (stable_ptr_free == NULL) {
-                    enlargeStablePtrTable();
-                }
-        
-                stable_ptr = stable_ptr_free - stable_ptr_table;
-                stable_ptr_free  = (P_*)*stable_ptr_free;
-                stable_ptr_table[stable_ptr] = PopPtr();
-
-                PushTaggedStablePtr(stable_ptr);
+                StgPtr       p  = PopPtr();                
+                StgStablePtr sp = getStablePtr ( p );
+                PushTaggedStablePtr(sp);
                 break;
             }
         case i_deRefStablePtr:
             {
-                StgStablePtr stable_ptr = PopTaggedStablePtr();
-                PushPtr(stable_ptr_table[stable_ptr]);
+                StgPtr p;
+                StgStablePtr sp = PopTaggedStablePtr();
+                p = deRefStablePtr(sp);
+                PushPtr(p);
                 break;
             }     
-
         case i_freeStablePtr:
             {
-                StgStablePtr stable_ptr = PopTaggedStablePtr();
-                stable_ptr_table[stable_ptr] = (P_)stable_ptr_free;
-                stable_ptr_free = stable_ptr_table + stable_ptr;
+                StgStablePtr sp = PopTaggedStablePtr();
+                freeStablePtr(sp);
+                break;
+            }     
+
+        case i_createAdjThunkARCH:
+            {
+                StgStablePtr stableptr = PopTaggedStablePtr();
+                StgAddr      typestr   = PopTaggedAddr();
+                StgChar      callconv  = PopTaggedChar();
+                StgAddr      adj_thunk = createAdjThunk(stableptr,typestr,callconv);
+                PushTaggedAddr(adj_thunk);
                 break;
             }     
-#endif /* 0 */
 
+        case i_getArgc:
+            {
+                StgInt n = prog_argc;
+                PushTaggedInt(n);
+                break;
+            }
+        case i_getArgv:
+            {
+                StgInt  n = PopTaggedInt();
+                StgAddr a = (StgAddr)prog_argv[n];
+                PushTaggedAddr(a);
+                break;
+            }
 
-#endif /* PROVIDE_STABLE */
 #ifdef PROVIDE_CONCURRENT
         case i_fork:
             {
@@ -3008,13 +3051,25 @@ off the stack.
                 ASSERT(0);
                 break;
 #endif /* PROVIDE_CONCURRENT */
-        case i_ccall_Id:
-        case i_ccall_IO:
+        case i_ccall_ccall_Id:
+        case i_ccall_ccall_IO:
+        case i_ccall_stdcall_Id:
+        case i_ccall_stdcall_IO:
             {
+                int r;
                 CFunDescriptor* descriptor = PopTaggedAddr();
-                StgAddr funPtr = PopTaggedAddr();
-                ccall(descriptor,funPtr);
-                break;
+                void (*funPtr)(void)       = PopTaggedAddr();
+                char cc = (primop2code == i_ccall_stdcall_Id ||
+                           primop2code == i_ccall_stdcall_IO)
+                          ? 's' : 'c';
+                r = ccall(descriptor,funPtr,bco,cc);
+                if (r == 0) break;
+                if (r == 1) 
+                   return makeErrorCall(
+                      "unhandled type or too many args/results in ccall");
+                if (r == 2)
+                   barf("ccall not configured correctly for this platform");
+                barf("unknown return code from ccall");
             }
         default:
                 barf("Unrecognised primop2");
@@ -3060,11 +3115,9 @@ nat marshall(char arg_ty, void* arg)
     case ADDR_REP:
             PushTaggedAddr(*((void**)arg));
             return ARG_SIZE(ADDR_TAG);
-#ifdef PROVIDE_STABLE
     case STABLE_REP:
             PushTaggedStablePtr(*((StgStablePtr*)arg));
             return ARG_SIZE(STABLE_TAG);
-#endif
 #ifdef PROVIDE_FOREIGN
     case FOREIGN_REP:
             /* Not allowed in this direction - you have to
@@ -3114,11 +3167,9 @@ nat unmarshall(char res_ty, void* res)
     case ADDR_REP:
             *((void**)res) = PopTaggedAddr();
             return ARG_SIZE(ADDR_TAG);
-#ifdef PROVIDE_STABLE
     case STABLE_REP:
             *((StgStablePtr*)res) = PopTaggedStablePtr();
             return ARG_SIZE(STABLE_TAG);
-#endif
 #ifdef PROVIDE_FOREIGN
     case FOREIGN_REP:
         {
@@ -3167,11 +3218,9 @@ nat argSize( const char* ks )
         case ADDR_REP:
                 sz += sizeof(StgWord) * ARG_SIZE(ADDR_TAG);
                 break;
-#ifdef PROVIDE_STABLE
         case STABLE_REP:
                 sz += sizeof(StgWord) * ARG_SIZE(STABLE_TAG);
                 break;
-#endif
 #ifdef PROVIDE_FOREIGN
         case FOREIGN_REP:
 #endif
@@ -3369,6 +3418,4 @@ void B__decodeFloat (B* man, I_* exp, StgFloat flt)
 
 #endif /* STANDALONE_INTEGER */
 
-
-
 #endif /* INTERPRETER */