[project @ 2000-04-14 15:18:05 by sewardj]
[ghc-hetmet.git] / ghc / rts / Assembler.c
index c959e3f..a382920 100644 (file)
@@ -5,8 +5,8 @@
  * Copyright (c) 1994-1998.
  *
  * $RCSfile: Assembler.c,v $
- * $Revision: 1.8 $
- * $Date: 1999/04/27 10:07:15 $
+ * $Revision: 1.26 $
+ * $Date: 2000/04/14 15:18:06 $
  *
  * This module provides functions to construct BCOs and other closures
  * required by the bytecode compiler.
 #include "Bytecodes.h"
 #include "Printer.h"
 #include "Disassembler.h"
-#include "Evaluator.h"
 #include "StgMiscClosures.h"
 #include "Storage.h"
+#include "Schedule.h"
+#include "Evaluator.h"
 
 #define INSIDE_ASSEMBLER_C
 #include "Assembler.h"
@@ -78,25 +79,33 @@ typedef struct {
 
 #define Queue Instrs
 #define Type  StgWord8
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue Ptrs
 #define Type  AsmObject
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue Refs
 #define Type  AsmRef
+#define MAKE_findIn 0
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
 #define Queue NonPtrs
 #define Type  StgWord
+#define MAKE_findIn 1
 #include "QueueTemplate.h"
+#undef MAKE_findIn
 #undef Type
 #undef Queue
 
@@ -145,8 +154,6 @@ struct AsmBCO_ {
     /* abstract machine ("executed" during compilation) */
     AsmSp    sp;          /* stack ptr */
     AsmSp    max_sp;
-    StgWord  hp;          /* heap ptr  */
-    StgWord  max_hp;
     Instr    lastOpc;
 };
 
@@ -171,8 +178,8 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
     case CONSTR:
         {
             StgClosure* con = stgCast(StgClosure*,obj->closure);
-            ASSERT(i < get_itbl(con)->layout.payload.nptrs && payloadCPtr(con,i) == NULL);
-            payloadCPtr(con,i) = reference;
+            ASSERT(i < get_itbl(con)->layout.payload.nptrs && con->payload[i] == NULL);
+            con->payload[i] = reference;
             break;
         }
     case AP_UPD:
@@ -183,8 +190,8 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
                 ASSERT(ap->fun == NULL);
                 ap->fun = reference;
             } else {
-                ASSERT(payloadCPtr(ap,i-1) == NULL);
-                payloadCPtr(ap,i-1) = reference;
+                ASSERT(ap->payload[i-1] == NULL);
+                ap->payload[i-1] = (StgPtr)reference;
             }
             break;
         }
@@ -261,30 +268,25 @@ static StgClosure* asmAlloc( nat size )
     return o;
 }
 
-static void grabHpUpd( AsmBCO bco, nat size )
-{
-    /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
-    ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
-    bco->hp += size;
-}
-
-static void grabHpNonUpd( AsmBCO bco, nat size )
+static void setSp( AsmBCO bco, AsmSp sp )
 {
-    /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
-    ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
-    bco->hp += size;
+    bco->max_sp = stg_max(bco->sp,bco->max_sp);
+    bco->sp     = sp;
+    bco->max_sp = stg_max(bco->sp,bco->max_sp);
 }
 
-static void resetHp( AsmBCO bco, nat hp )
+static void incSp ( AsmBCO bco, int sp_delta )
 {
-    bco->max_hp = stg_max(bco->hp,bco->max_hp);
-    bco->hp     = hp;
+    bco->max_sp  = stg_max(bco->sp,bco->max_sp);
+    bco->sp     += sp_delta;
+    bco->max_sp  = stg_max(bco->sp,bco->max_sp);
 }
 
-static void resetSp( AsmBCO bco, AsmSp sp )
+static void decSp ( AsmBCO bco, int sp_delta )
 {
-    bco->max_sp = stg_max(bco->sp,bco->max_sp);
-    bco->sp     = sp;
+    bco->max_sp  = stg_max(bco->sp,bco->max_sp);
+    bco->sp     -= sp_delta;
+    bco->max_sp  = stg_max(bco->sp,bco->max_sp);
 }
 
 /* --------------------------------------------------------------------------
@@ -321,8 +323,8 @@ void asmEndCon( AsmCon con )
     StgClosure* c = asmAlloc(CONSTR_sizeW(p,np));
     StgClosure* o = stgCast(StgClosure*,c);
     SET_HDR(o,con->info,??);
-    mapQueue(Ptrs,    AsmObject, con->object.ptrs, payloadCPtr(o,i) = NULL);
-    { nat i; for( i=0; i<np; ++i ) { payloadWord(o,p+i) = 0xdeadbeef; } }
+    mapQueue(Ptrs,    AsmObject, con->object.ptrs, o->payload[i] = NULL);
+    { nat i; for( i=0; i<np; ++i ) { o->payload[p+i] = (StgClosure *)0xdeadbeef; }}
     asmEndObject(&con->object,c);
 }
 
@@ -361,7 +363,6 @@ AsmBCO asmBeginBCO( int /*StgExpr*/ e )
 
     bco->stgexpr = e;
     bco->max_sp = bco->sp = 0;
-    bco->max_hp = bco->hp = 0;
     bco->lastOpc = i_INTERNAL_ERROR;
     return bco;
 }
@@ -370,7 +371,7 @@ void asmEndBCO( AsmBCO bco )
 {
     nat p  = bco->object.ptrs.len;
     nat np = bco->nps.len;
-    nat is = bco->is.len + 2;  /* 2 for stack check */
+    nat is = bco->is.len + (bco->max_sp <= 255 ? 2 : 3);  /* 2 or 3 for stack check */
 
     StgClosure* c = asmAlloc(BCO_sizeW(p,np,is));
     StgBCO*     o = stgCast(StgBCO*,c);
@@ -384,9 +385,17 @@ void asmEndBCO( AsmBCO bco )
     {
         nat j = 0;
         bco->max_sp = stg_max(bco->sp,bco->max_sp);
-        bco->max_hp = stg_max(bco->hp,bco->max_hp);
-        bcoInstr(o,j++) = i_STK_CHECK;
-        bcoInstr(o,j++) = bco->max_sp;
+
+        ASSERT(bco->max_sp <= 65535);
+        if (bco->max_sp <= 255) {
+           bcoInstr(o,j++) = i_STK_CHECK;
+           bcoInstr(o,j++) = bco->max_sp;
+        } else {
+           bcoInstr(o,j++) = i_STK_CHECK_big;
+           bcoInstr(o,j++) = bco->max_sp / 256;
+           bcoInstr(o,j++) = bco->max_sp % 256;
+        }
+
         mapQueue(Instrs,  StgWord8,   bco->is,   bcoInstr(o,j++) = x);
         ASSERT(j == is);
     }
@@ -442,6 +451,11 @@ static void asmWord( AsmBCO bco, StgWord i )
     insertNonPtrs( &bco->nps, i );
 }
 
+static int asmFindInNonPtrs ( AsmBCO bco, StgWord i )
+{
+   return findInNonPtrs ( &bco->nps, i );
+}
+
 #define asmWords(bco,ty,x)                               \
     {                                                    \
         union { ty a; AsmWord b[sizeofW(ty)]; } p;       \
@@ -459,14 +473,13 @@ static StgWord repSizeW( AsmRep rep )
     case CHAR_REP:    return sizeofW(StgWord) + sizeofW(StgChar);
 
     case BOOL_REP:
-    case INT_REP:     return sizeofW(StgWord) + sizeofW(StgInt);
-    case WORD_REP:    return sizeofW(StgWord) + sizeofW(StgWord);
-    case ADDR_REP:    return sizeofW(StgWord) + sizeofW(StgAddr);
-    case FLOAT_REP:   return sizeofW(StgWord) + sizeofW(StgFloat);
-    case DOUBLE_REP:  return sizeofW(StgWord) + sizeofW(StgDouble);
-#ifdef PROVIDE_STABLE
-    case STABLE_REP:  return sizeofW(StgWord) + sizeofW(StgWord);
-#endif
+    case INT_REP:      return sizeofW(StgWord) + sizeofW(StgInt);
+    case THREADID_REP:
+    case WORD_REP:     return sizeofW(StgWord) + sizeofW(StgWord);
+    case ADDR_REP:     return sizeofW(StgWord) + sizeofW(StgAddr);
+    case FLOAT_REP:    return sizeofW(StgWord) + sizeofW(StgFloat);
+    case DOUBLE_REP:   return sizeofW(StgWord) + sizeofW(StgDouble);
+    case STABLE_REP:   return sizeofW(StgWord) + sizeofW(StgWord);
 
     case INTEGER_REP: 
 #ifdef PROVIDE_WEAK
@@ -478,6 +491,7 @@ static StgWord repSizeW( AsmRep rep )
     case ALPHA_REP:    /* a                        */ 
     case BETA_REP:     /* b                       */ 
     case GAMMA_REP:    /* c                       */ 
+    case DELTA_REP:    /* d                       */ 
     case HANDLER_REP:  /* IOError -> IO a         */ 
     case ERROR_REP:    /* IOError                 */ 
     case ARR_REP    :  /* PrimArray              a */ 
@@ -485,10 +499,7 @@ static StgWord repSizeW( AsmRep rep )
     case REF_REP    :  /* Ref                  s a */ 
     case MUTARR_REP :  /* PrimMutableArray     s a */ 
     case MUTBARR_REP:  /* PrimMutableByteArray s a */ 
-#ifdef PROVIDE_CONCURRENT
-    case THREADID_REP: /* ThreadId                 */ 
     case MVAR_REP:     /* MVar a                   */ 
-#endif
     case PTR_REP:     return sizeofW(StgPtr);
 
     case VOID_REP:    return sizeofW(StgWord);
@@ -635,6 +646,14 @@ static void emit_i_VAR_DOUBLE ( AsmBCO bco, int arg1 )
       emiti_16(bco,i_VAR_DOUBLE_big,arg1);
 }
 
+static void emit_i_VAR_STABLE ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256)
+      emiti_8 (bco,i_VAR_STABLE,    arg1); else
+      emiti_16(bco,i_VAR_STABLE_big,arg1);
+}
+
 static void emit_i_VAR ( AsmBCO bco, int arg1 )
 {
    ASSERT(arg1 >= 0);
@@ -734,6 +753,14 @@ static void emit_i_RETADDR ( AsmBCO bco, int arg1 )
       emiti_16(bco,i_RETADDR_big,arg1);
 }
 
+static void emit_i_ALLOC_CONSTR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256)
+      emiti_8 (bco,i_ALLOC_CONSTR,    arg1); else
+      emiti_16(bco,i_ALLOC_CONSTR_big,arg1);
+}
+
 
 /* --------------------------------------------------------------------------
  * Arg checks.
@@ -750,8 +777,6 @@ void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg )
     nat args = bco->sp - last_arg;
     if (args != 0) { /* optimisation */
         emiti_8(bco,i_ARG_CHECK,args);
-        grabHpNonUpd(bco,PAP_sizeW(args-1));
-        resetHp(bco,0);
     }
 }
 
@@ -761,7 +786,7 @@ void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg )
 
 AsmVar asmBind          ( AsmBCO bco, AsmRep rep )
 {
-    bco->sp += repSizeW(rep);
+    incSp(bco,repSizeW(rep));
     return bco->sp;
 }
 
@@ -771,7 +796,7 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
 
     if (rep == VOID_REP) {
         emiti_(bco,i_VOID);
-        bco->sp += repSizeW(rep);
+        incSp(bco,repSizeW(rep));
         return;
     }
 
@@ -781,6 +806,7 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
     case INT_REP:
             emit_i_VAR_INT(bco,offset);
             break;
+    case THREADID_REP:
     case WORD_REP:
             emit_i_VAR_WORD(bco,offset);
             break;
@@ -796,11 +822,9 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
     case DOUBLE_REP:
             emit_i_VAR_DOUBLE(bco,offset);
             break;
-#ifdef PROVIDE_STABLE
     case STABLE_REP:
             emit_i_VAR_STABLE(bco,offset);
             break;
-#endif
 
     case INTEGER_REP:
 #ifdef PROVIDE_WEAK
@@ -812,6 +836,7 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
     case ALPHA_REP:    /* a                        */ 
     case BETA_REP:     /* b                       */
     case GAMMA_REP:    /* c                       */ 
+    case DELTA_REP:    /* d                       */ 
     case HANDLER_REP:  /* IOError -> IO a         */
     case ERROR_REP:    /* IOError                 */
     case ARR_REP    :  /* PrimArray              a */
@@ -819,17 +844,14 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
     case REF_REP    :  /* Ref                  s a */
     case MUTARR_REP :  /* PrimMutableArray     s a */
     case MUTBARR_REP:  /* PrimMutableByteArray s a */
-#ifdef PROVIDE_CONCURRENT
-    case THREADID_REP: /* ThreadId                */
     case MVAR_REP:     /* MVar a                  */
-#endif
     case PTR_REP:
             emit_i_VAR(bco,offset);
             break;
     default:
             barf("asmVar %d",rep);
     }
-    bco->sp += repSizeW(rep);
+    incSp(bco,repSizeW(rep));
 }
 
 /* --------------------------------------------------------------------------
@@ -848,9 +870,10 @@ void asmEndEnter( AsmBCO bco, AsmSp sp1, AsmSp sp2 )
     ASSERT(x >= 0 && y >= 0);
     if (y != 0) {
         emit_i_SLIDE(bco,x,y);
-        bco->sp -= sp1 - sp2;
+        decSp(bco,sp1 - sp2);
     }
     emiti_(bco,i_ENTER);
+    decSp(bco,sizeofW(StgPtr));
 }
 
 /* --------------------------------------------------------------------------
@@ -862,41 +885,33 @@ AsmVar asmBox( AsmBCO bco, AsmRep rep )
     switch (rep) {
     case CHAR_REP:
             emiti_(bco,i_PACK_CHAR);
-            grabHpNonUpd(bco,Czh_sizeW);
             break;
     case INT_REP:
             emiti_(bco,i_PACK_INT);
-            grabHpNonUpd(bco,Izh_sizeW);
             break;
+    case THREADID_REP:
     case WORD_REP:
             emiti_(bco,i_PACK_WORD);
-            grabHpNonUpd(bco,Wzh_sizeW);
             break;
     case ADDR_REP:
             emiti_(bco,i_PACK_ADDR);
-            grabHpNonUpd(bco,Azh_sizeW);
             break;
     case FLOAT_REP:
             emiti_(bco,i_PACK_FLOAT);
-            grabHpNonUpd(bco,Fzh_sizeW);
             break;
     case DOUBLE_REP:
             emiti_(bco,i_PACK_DOUBLE);
-            grabHpNonUpd(bco,Dzh_sizeW);
             break;
-#ifdef PROVIDE_STABLE
     case STABLE_REP:
             emiti_(bco,i_PACK_STABLE);
-            grabHpNonUpd(bco,Stablezh_sizeW);
             break;
-#endif
 
     default:
             barf("asmBox %d",rep);
     }
     /* NB: these operations DO pop their arg       */
-    bco->sp -= repSizeW(rep);   /* pop unboxed arg */
-    bco->sp += sizeofW(StgPtr); /* push box        */
+    decSp(bco, repSizeW(rep));   /* pop unboxed arg */
+    incSp(bco, sizeofW(StgPtr)); /* push box        */
     return bco->sp;
 }
 
@@ -910,6 +925,7 @@ AsmVar asmUnbox( AsmBCO bco, AsmRep rep )
     case INT_REP:
             emiti_(bco,i_UNPACK_INT);
             break;
+    case THREADID_REP:
     case WORD_REP:
             emiti_(bco,i_UNPACK_WORD);
             break;
@@ -925,16 +941,14 @@ AsmVar asmUnbox( AsmBCO bco, AsmRep rep )
     case DOUBLE_REP:
             emiti_(bco,i_UNPACK_DOUBLE);
             break;
-#ifdef PROVIDE_STABLE
     case STABLE_REP:
             emiti_(bco,i_UNPACK_STABLE);
             break;
-#endif
     default:
             barf("asmUnbox %d",rep);
     }
     /* NB: these operations DO NOT pop their arg  */
-    bco->sp += repSizeW(rep); /* push unboxed arg */
+    incSp(bco, repSizeW(rep)); /* push unboxed arg */
     return bco->sp;
 }
 
@@ -947,49 +961,49 @@ void asmConstInt( AsmBCO bco, AsmInt x )
 {
     emit_i_CONST_INT(bco,bco->nps.len);
     asmWords(bco,AsmInt,x);
-    bco->sp += repSizeW(INT_REP);
+    incSp(bco, repSizeW(INT_REP));
 }
 
 void asmConstInteger( AsmBCO bco, AsmString x )
 {
     emit_i_CONST_INTEGER(bco,bco->nps.len);
     asmWords(bco,AsmString,x);
-    bco->sp += repSizeW(INTEGER_REP);
+    incSp(bco, repSizeW(INTEGER_REP));
 }
 
 void asmConstAddr( AsmBCO bco, AsmAddr x )
 {
     emit_i_CONST_ADDR(bco,bco->nps.len);
     asmWords(bco,AsmAddr,x);
-    bco->sp += repSizeW(ADDR_REP);
+    incSp(bco, repSizeW(ADDR_REP));
 }
 
 void asmConstWord( AsmBCO bco, AsmWord x )
 {
     emit_i_CONST_INT(bco,bco->nps.len);
     asmWords(bco,AsmWord,(AsmInt)x);
-    bco->sp += repSizeW(WORD_REP);
+    incSp(bco, repSizeW(WORD_REP));
 }
 
 void asmConstChar( AsmBCO bco, AsmChar x )
 {
     emit_i_CONST_CHAR(bco,bco->nps.len);
     asmWords(bco,AsmChar,x);
-    bco->sp += repSizeW(CHAR_REP);
+    incSp(bco, repSizeW(CHAR_REP));
 }
 
 void asmConstFloat( AsmBCO bco, AsmFloat x )
 {
     emit_i_CONST_FLOAT(bco,bco->nps.len);
     asmWords(bco,AsmFloat,x);
-    bco->sp += repSizeW(FLOAT_REP);
+    incSp(bco, repSizeW(FLOAT_REP));
 }
 
 void asmConstDouble( AsmBCO bco, AsmDouble x )
 {
     emit_i_CONST_DOUBLE(bco,bco->nps.len);
     asmWords(bco,AsmDouble,x);
-    bco->sp += repSizeW(DOUBLE_REP);
+    incSp(bco, repSizeW(DOUBLE_REP));
 }
 
 /* --------------------------------------------------------------------------
@@ -1010,14 +1024,14 @@ AsmSp asmContinuation( AsmBCO bco, AsmBCO ret_addr )
 {
     emit_i_RETADDR(bco,bco->object.ptrs.len);
     asmPtr(bco,&(ret_addr->object));
-    bco->sp += 2 * sizeofW(StgPtr);
+    incSp(bco, 2 * sizeofW(StgPtr));
     return bco->sp;
 }
 
 AsmBCO asmBeginContinuation ( AsmSp sp, int /*List*/ alts )
 {
     AsmBCO bco = asmBeginBCO(alts);
-    bco->sp = sp;
+    setSp(bco, sp);
     return bco;
 }
 
@@ -1038,7 +1052,7 @@ AsmSp asmBeginAlt( AsmBCO bco )
 
 void asmEndAlt( AsmBCO bco, AsmSp  sp )
 {
-    resetSp(bco,sp);
+    setSp(bco,sp);
 }
 
 AsmPc asmTest( AsmBCO bco, AsmWord tag )
@@ -1052,7 +1066,7 @@ AsmPc asmTestInt( AsmBCO bco, AsmVar v, AsmInt x )
     asmVar(bco,v,INT_REP);
     asmConstInt(bco,x);
     emiti_16(bco,i_TEST_INT,0);
-    bco->sp -= 2*repSizeW(INT_REP);
+    decSp(bco, 2*repSizeW(INT_REP));
     return bco->is.len;
 }
 
@@ -1079,10 +1093,15 @@ AsmSp asmBeginPrim( AsmBCO bco )
     return bco->sp;
 }
 
-void   asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
+void asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
 {
     emiti_8(bco,prim->prefix,prim->opcode);
-    bco->sp = base;
+    setSp(bco, base);
+}
+
+char* asmGetPrimopName ( AsmPrim* p )
+{
+   return p->name;
 }
 
 /* Hugs used to let you add arbitrary primops with arbitrary types
@@ -1090,7 +1109,7 @@ void   asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
  * We deliberately avoided that approach because we wanted more
  * control over which primops are provided.
  */
-const AsmPrim asmPrimOps[] = {
+AsmPrim asmPrimOps[] = {
 
     /* Char# operations */
       { "primGtChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_gtChar }
@@ -1171,9 +1190,11 @@ const AsmPrim asmPrimOps[] = {
     , { "primIndexAddrOffAddr",      "AI", "A",  MONAD_Id, i_PRIMOP1, i_indexAddrOffAddr }
     , { "primIndexFloatOffAddr",     "AI", "F",  MONAD_Id, i_PRIMOP1, i_indexFloatOffAddr }
     , { "primIndexDoubleOffAddr",    "AI", "D",  MONAD_Id, i_PRIMOP1, i_indexDoubleOffAddr }
-#ifdef PROVIDE_STABLE
     , { "primIndexStableOffAddr",    "AI", "s",  MONAD_Id, i_PRIMOP1, i_indexStableOffAddr }
-#endif
+
+    /* Stable# operations */
+    , { "primIntToStablePtr",        "I",  "s",  MONAD_Id, i_PRIMOP1, i_intToStable }
+    , { "primStablePtrToInt",        "s",  "I",  MONAD_Id, i_PRIMOP1, i_stableToInt }
 
     /* These ops really ought to be in the IO monad */
     , { "primReadCharOffAddr",       "AI", "C",  MONAD_ST, i_PRIMOP1, i_readCharOffAddr }
@@ -1182,9 +1203,7 @@ const AsmPrim asmPrimOps[] = {
     , { "primReadAddrOffAddr",       "AI", "A",  MONAD_ST, i_PRIMOP1, i_readAddrOffAddr }
     , { "primReadFloatOffAddr",      "AI", "F",  MONAD_ST, i_PRIMOP1, i_readFloatOffAddr }
     , { "primReadDoubleOffAddr",     "AI", "D",  MONAD_ST, i_PRIMOP1, i_readDoubleOffAddr }
-#ifdef PROVIDE_STABLE                
     , { "primReadStableOffAddr",     "AI", "s",  MONAD_ST, i_PRIMOP1, i_readStableOffAddr }
-#endif
 
     /* These ops really ought to be in the IO monad */
     , { "primWriteCharOffAddr",      "AIC", "",  MONAD_ST, i_PRIMOP1, i_writeCharOffAddr }
@@ -1193,9 +1212,7 @@ const AsmPrim asmPrimOps[] = {
     , { "primWriteAddrOffAddr",      "AIA", "",  MONAD_ST, i_PRIMOP1, i_writeAddrOffAddr }
     , { "primWriteFloatOffAddr",     "AIF", "",  MONAD_ST, i_PRIMOP1, i_writeFloatOffAddr }
     , { "primWriteDoubleOffAddr",    "AID", "",  MONAD_ST, i_PRIMOP1, i_writeDoubleOffAddr }
-#ifdef PROVIDE_STABLE
     , { "primWriteStableOffAddr",    "AIs", "",  MONAD_ST, i_PRIMOP1, i_writeStableOffAddr }
-#endif
 
     /* Integer operations */
     , { "primCompareInteger",        "ZZ", "I",  MONAD_Id, i_PRIMOP1, i_compareInteger }
@@ -1343,30 +1360,37 @@ const AsmPrim asmPrimOps[] = {
     , { "primReadDoubleArray",       "mI",  "D", MONAD_ST, i_PRIMOP2, i_readDoubleArray }
     , { "primIndexDoubleArray",      "xI",  "D", MONAD_Id, i_PRIMOP2, i_indexDoubleArray }
 
-#ifdef PROVIDE_STABLE                
+#if 0
+#ifdef PROVIDE_STABLE
     , { "primWriteStableArray",      "mIs", "",  MONAD_ST, i_PRIMOP2, i_writeStableArray }
     , { "primReadStableArray",       "mI",  "s", MONAD_ST, i_PRIMOP2, i_readStableArray }
     , { "primIndexStableArray",      "xI",  "s", MONAD_Id, i_PRIMOP2, i_indexStableArray }
 #endif
-
+#endif
     /* {new,write,read,index}ForeignObjArray not provided */
 
 
 #ifdef PROVIDE_FOREIGN
     /* ForeignObj# operations */
-    , { "primMakeForeignObj",        "A",  "f",  MONAD_IO, i_PRIMOP2, i_makeForeignObj }
+    , { "primMkForeignObj",          "A",  "f",  MONAD_IO, i_PRIMOP2, i_mkForeignObj }
 #endif
 #ifdef PROVIDE_WEAK
     /* WeakPair# operations */
     , { "primMakeWeak",              "bac", "w",  MONAD_IO, i_PRIMOP2, i_makeWeak }
     , { "primDeRefWeak",             "w",   "Ia", MONAD_IO, i_PRIMOP2, i_deRefWeak }
 #endif
-#ifdef PROVIDE_STABLE
     /* StablePtr# operations */
     , { "primMakeStablePtr",         "a", "s",   MONAD_IO, i_PRIMOP2, i_makeStablePtr }
     , { "primDeRefStablePtr",        "s", "a",   MONAD_IO, i_PRIMOP2, i_deRefStablePtr }
     , { "primFreeStablePtr",         "s", "",    MONAD_IO, i_PRIMOP2, i_freeStablePtr }
-#endif
+
+    /* foreign export dynamic support */
+    , { "primCreateAdjThunkARCH",    "sAC","A",  MONAD_IO, i_PRIMOP2, i_createAdjThunkARCH }
+
+    /* misc handy hacks */
+    , { "primGetArgc",               "",   "I",  MONAD_IO, i_PRIMOP2, i_getArgc }
+    , { "primGetArgv",               "I",  "A",  MONAD_IO, i_PRIMOP2, i_getArgv }
+
 #ifdef PROVIDE_PTREQUALITY
     , { "primReallyUnsafePtrEquality", "aa", "B",MONAD_Id, i_PRIMOP2, i_reallyUnsafePtrEquality }
 #endif
@@ -1375,27 +1399,50 @@ const AsmPrim asmPrimOps[] = {
 #endif
 #ifdef PROVIDE_CONCURRENT
     /* Concurrency operations */
-    , { "primFork",                  "a", "T",   MONAD_IO, i_PRIMOP2, i_fork }
+    , { "primForkIO",                "a", "T",   MONAD_IO, i_PRIMOP2, i_forkIO }
     , { "primKillThread",            "T", "",    MONAD_IO, i_PRIMOP2, i_killThread }
-    , { "primSameMVar",              "rr", "B",  MONAD_Id, i_PRIMOP2, i_sameMVar }
-    , { "primNewMVar",               "",  "r",   MONAD_IO, i_PRIMOP2, i_newMVar }
-    , { "primTakeMVar",              "r", "a",   MONAD_IO, i_PRIMOP2, i_takeMVar }
-    , { "primPutMVar",               "ra", "",   MONAD_IO, i_PRIMOP2, i_putMVar } 
-    , { "primDelay",                 "I", "",    MONAD_IO, i_PRIMOP2, i_delay }
+    , { "primRaiseInThread",         "TE", "",   MONAD_IO, i_PRIMOP2, i_raiseInThread }
+
     , { "primWaitRead",              "I", "",    MONAD_IO, i_PRIMOP2, i_waitRead }
     , { "primWaitWrite",             "I", "",    MONAD_IO, i_PRIMOP2, i_waitWrite }
+    , { "primYield",                 "", "",     MONAD_IO, i_PRIMOP2, i_yield }    , { "primDelay",                 "I", "",    MONAD_IO, i_PRIMOP2, i_delay }
+    , { "primGetThreadId",           "",   "T",  MONAD_IO, i_PRIMOP2, i_getThreadId }
+    , { "primCmpThreadIds",          "TT", "I",  MONAD_Id, i_PRIMOP2, i_cmpThreadIds }
 #endif
+    , { "primNewEmptyMVar",          "",  "r",   MONAD_IO, i_PRIMOP2, i_newMVar }
+      /* primTakeMVar is handwritten bytecode */
+    , { "primPutMVar",               "ra", "",   MONAD_IO, i_PRIMOP2, i_putMVar } 
+    , { "primSameMVar",              "rr", "B",  MONAD_Id, i_PRIMOP2, i_sameMVar }
 
+  
     /* Ccall is polyadic - so it's excluded from this table */
 
-    , { 0,0,0,0 }
+    , { 0,0,0,0,0,0 }
 };
 
-const AsmPrim ccall_Id = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_Id };
-const AsmPrim ccall_IO = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_IO };
-
+AsmPrim ccall_ccall_Id
+   = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_ccall_Id };
+AsmPrim ccall_ccall_IO
+   = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_ccall_IO };
+AsmPrim ccall_stdcall_Id 
+   = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_stdcall_Id };
+AsmPrim ccall_stdcall_IO 
+   = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_stdcall_IO };
+
+#ifdef DEBUG
+void checkBytecodeCount( void );
+void checkBytecodeCount( void ) 
+{
+  if (MAX_Primop1 >= 255) {
+    printf("Too many Primop1 bytecodes (%d)\n",MAX_Primop1);
+  }
+  if (MAX_Primop2 >= 255) {
+    printf("Too many Primop2 bytecodes (%d)\n",MAX_Primop2);
+  }
+}
+#endif
 
-const AsmPrim* asmFindPrim( char* s )
+AsmPrim* asmFindPrim( char* s )
 {
     int i;
     for (i=0; asmPrimOps[i].name; ++i) {
@@ -1406,7 +1453,7 @@ const AsmPrim* asmFindPrim( char* s )
     return 0;
 }
 
-const AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
+AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
 {
     nat i;
     for (i=0; asmPrimOps[i].name; ++i) {
@@ -1426,8 +1473,9 @@ AsmBCO asm_BCO_catch ( void )
    AsmBCO bco = asmBeginBCO(0 /*NIL*/);
    emiti_8(bco,i_ARG_CHECK,2);
    emiti_8(bco,i_PRIMOP1,i_pushcatchframe);
-   bco->sp += (1-2)*sizeofW(StgPtr) + sizeofW(StgCatchFrame);
+   incSp(bco, (1-2)*sizeofW(StgPtr) + sizeofW(StgCatchFrame));
    emiti_(bco,i_ENTER);
+   decSp(bco, sizeofW(StgPtr));
    asmEndBCO(bco);
    return bco;
 }
@@ -1437,6 +1485,7 @@ AsmBCO asm_BCO_raise ( void )
    AsmBCO bco = asmBeginBCO(0 /*NIL*/);
    emiti_8(bco,i_ARG_CHECK,1);
    emiti_8(bco,i_PRIMOP2,i_raise);
+   decSp(bco,sizeofW(StgPtr));
    asmEndBCO(bco);
    return bco;
 }
@@ -1446,11 +1495,11 @@ AsmBCO asm_BCO_seq ( void )
    AsmBCO eval, cont;
 
    cont = asmBeginBCO(0 /*NIL*/);
-   emiti_8(cont,i_ARG_CHECK,2);
+   emiti_8(cont,i_ARG_CHECK,2);   /* should never fail */
    emit_i_VAR(cont,1);
    emit_i_SLIDE(cont,1,2);
    emiti_(cont,i_ENTER);
-   cont->sp += 3*sizeofW(StgPtr);
+   incSp(cont, 3*sizeofW(StgPtr));
    asmEndBCO(cont);
 
    eval = asmBeginBCO(0 /*NIL*/);
@@ -1461,23 +1510,73 @@ AsmBCO asm_BCO_seq ( void )
    emit_i_SLIDE(eval,3,1);
    emiti_8(eval,i_PRIMOP1,i_pushseqframe);
    emiti_(eval,i_ENTER);
-   eval->sp += sizeofW(StgSeqFrame) + 4*sizeofW(StgPtr);
+   incSp(eval, sizeofW(StgSeqFrame) + 4*sizeofW(StgPtr));
    asmEndBCO(eval);
 
    return eval;
 }
 
+AsmBCO asm_BCO_takeMVar ( void )
+{
+   AsmBCO kase, casecont, take;
+
+   take = asmBeginBCO(0 /*NIL*/);
+   emit_i_VAR(take,0);
+   emiti_8(take,i_PRIMOP2,i_takeMVar);
+   emit_i_VAR(take,3);
+   emit_i_VAR(take,1);
+   emit_i_VAR(take,4);
+   emit_i_SLIDE(take,3,4);
+   emiti_(take,i_ENTER);
+   incSp(take,20);
+   asmEndBCO(take);
+
+   casecont = asmBeginBCO(0 /*NIL*/);
+   emiti_(casecont,i_UNPACK);
+   emit_i_VAR(casecont,4);
+   emit_i_VAR(casecont,4);
+   emit_i_VAR(casecont,2);
+   emit_i_CONST(casecont,casecont->object.ptrs.len);
+   asmPtr(casecont,&(take->object));
+   emit_i_SLIDE(casecont,4,5);
+   emiti_(casecont,i_ENTER);
+   incSp(casecont,20);
+   asmEndBCO(casecont);
+
+   kase = asmBeginBCO(0 /*NIL*/);
+   emiti_8(kase,i_ARG_CHECK,3);
+   emit_i_RETADDR(kase,kase->object.ptrs.len);
+   asmPtr(kase,&(casecont->object));
+   emit_i_VAR(kase,2);
+   emiti_(kase,i_ENTER);
+   incSp(kase,20);
+   asmEndBCO(kase);
+
+   return kase;
+}
+
+
 /* --------------------------------------------------------------------------
  * Heap manipulation
  * ------------------------------------------------------------------------*/
 
 AsmVar asmAllocCONSTR   ( AsmBCO bco, AsmInfo info )
 {
+    int i;
     ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
-    emiti_8(bco,i_ALLOC_CONSTR,bco->nps.len);
-    asmWords(bco,AsmInfo,info);
-    bco->sp += sizeofW(StgClosurePtr);
-    grabHpNonUpd(bco,sizeW_fromITBL(info));
+
+    /* Look in this bco's collection of nonpointers (literals)
+       to see if the itbl pointer is already there.  If so, re-use it. */
+    i = asmFindInNonPtrs ( bco, (StgWord)info );
+
+    if (i == -1) {
+       emit_i_ALLOC_CONSTR(bco,bco->nps.len);
+       asmWords(bco,AsmInfo,info);
+    } else {
+       emit_i_ALLOC_CONSTR(bco,i);
+    }
+
+    incSp(bco, sizeofW(StgClosurePtr));
     return bco->sp;
 }
 
@@ -1494,7 +1593,7 @@ void asmEndPack( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info )
     /* only reason to include info is for this assertion */
     assert(info->layout.payload.ptrs == size);
     emit_i_PACK(bco, bco->sp - v);
-    bco->sp = start;
+    setSp(bco, start);
 }
 
 void asmBeginUnpack( AsmBCO bco )
@@ -1510,8 +1609,7 @@ void asmEndUnpack( AsmBCO bco )
 AsmVar asmAllocAP( AsmBCO bco, AsmNat words )
 {
     emiti_8(bco,i_ALLOC_AP,words);
-    bco->sp += sizeofW(StgPtr);
-    grabHpUpd(bco,AP_sizeW(words));
+    incSp(bco, sizeofW(StgPtr));
     return bco->sp;
 }
 
@@ -1524,13 +1622,13 @@ void asmEndMkAP( AsmBCO bco, AsmVar v, AsmSp start )
 {
     emit_i_MKAP(bco,bco->sp-v,bco->sp-start-1);
             /* -1 because fun isn't counted */
-    bco->sp = start;
+    setSp(bco, start);
 }
 
 AsmVar asmAllocPAP( AsmBCO bco, AsmNat size )
 {
     emiti_8(bco,i_ALLOC_PAP,size);
-    bco->sp += sizeofW(StgPtr);
+    incSp(bco, sizeofW(StgPtr));
     return bco->sp;
 }
 
@@ -1543,17 +1641,27 @@ void asmEndMkPAP( AsmBCO bco, AsmVar v, AsmSp start )
 {
     emiti_8_8(bco,i_MKPAP,bco->sp-v,bco->sp-start-1);
             /* -1 because fun isn't counted */
-    bco->sp = start;
+    setSp(bco, start);
 }
 
 AsmVar asmClosure( AsmBCO bco, AsmObject p )
 {
     emit_i_CONST(bco,bco->object.ptrs.len);
     asmPtr(bco,p);
-    bco->sp += sizeofW(StgPtr);
+    incSp(bco, sizeofW(StgPtr));
     return bco->sp;
 }
 
+AsmVar asmGHCClosure( AsmBCO bco, AsmObject p )
+{
+    // A complete hack.  Pushes the address as a tagged int
+    // and then uses SLIDE to get rid of the tag.  Appalling.
+    asmConstInt(bco, (AsmInt)p);
+    emit_i_SLIDE(bco,0,1); decSp(bco,1);
+    return bco->sp;
+}
+
+
 /* --------------------------------------------------------------------------
  * Building InfoTables
  * ------------------------------------------------------------------------*/