[project @ 1999-03-20 17:33:07 by sof]
[ghc-hetmet.git] / ghc / rts / Assembler.c
index f1e71a1..a9c5fa1 100644 (file)
@@ -1,10 +1,12 @@
-/* -*- mode: hugs-c; -*- */
+
 /* --------------------------------------------------------------------------
- * $Id: Assembler.c,v 1.4 1999/02/05 16:02:34 simonm Exp $
+ * Bytecode assembler
  *
- * Copyright (c) The GHC Team 1994-1998.
+ * Copyright (c) 1994-1998.
  *
- * Bytecode assembler
+ * $RCSfile: Assembler.c,v $
+ * $Revision: 1.7 $
+ * $Date: 1999/03/09 14:51:19 $
  *
  * This module provides functions to construct BCOs and other closures
  * required by the bytecode compiler.
@@ -84,7 +86,7 @@ typedef struct {
 #define NonPtrsChunkSize 10
 
 #define Queue Instrs
-#define Type  StgNat8
+#define Type  StgWord8
 #include "QueueTemplate.h"
 #undef Type
 #undef Queue
@@ -143,7 +145,8 @@ struct AsmCAF_ {
 
 struct AsmBCO_ {
     struct AsmObject_ object;  /* must be first in struct */
-    
+
+    int /*StgExpr*/  stgexpr;    
     Instrs   is;          
     NonPtrs  nps;
 
@@ -201,7 +204,7 @@ static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
         /* todo: free the queues */
 
         /* we don't print until all ptrs are resolved */
-        IF_DEBUG(codegen,printObj(obj->closure));
+        IF_DEBUG(codegen,printObj(obj->closure);printf("\n\n"));
     }
 }
 
@@ -234,11 +237,19 @@ static void asmEndObject( AsmObject obj, StgClosure* c )
     obj->closure = c;
     mapQueue(Ptrs,    AsmObject, obj->ptrs, asmAddRef(x,obj,i));
     mapQueue(Refs,    AsmRef,    obj->refs, asmResolveRef(x.ref,x.i,c));
+#if 0
     if (obj->num_unresolved == 0) {
         /* todo: free the queues */
         /* we don't print until all ptrs are resolved */
+        IF_DEBUG(codegen,
+                 if (obj->num_unresolved > 0) 
+                    fprintf(stderr, "{{%d unresolved}} ", obj->num_unresolved);
+                )
         IF_DEBUG(codegen,printObj(obj->closure));
     }
+    //printf( "unresolved %d\n", obj->num_unresolved);
+    //printObj(obj->closure);
+#endif
 }
 
 int asmObjectHasClosure ( AsmObject obj )
@@ -357,7 +368,7 @@ void asmEndCAF( AsmCAF caf, AsmBCO body )
     asmEndObject(&caf->object,c);
 }
 
-AsmBCO asmBeginBCO( void )
+AsmBCO asmBeginBCO( int /*StgExpr*/ e )
 {
     AsmBCO bco = malloc(sizeof(struct AsmBCO_));
     if (bco == NULL) {
@@ -367,6 +378,7 @@ AsmBCO asmBeginBCO( void )
     initInstrs(&bco->is);
     initNonPtrs(&bco->nps);
 
+    bco->stgexpr = e;
     bco->max_sp = bco->sp = 0;
     bco->max_hp = bco->hp = 0;
     return bco;
@@ -388,6 +400,7 @@ void asmEndBCO( AsmBCO bco )
     o->n_ptrs   = p;
     o->n_words  = np;
     o->n_instrs = is;
+    o->stgexpr  = bco->stgexpr;
     mapQueue(Ptrs,    AsmObject, bco->object.ptrs, bcoConstCPtr(o,i) = NULL);
     mapQueue(NonPtrs, StgWord,   bco->nps,  bcoConstWord(o,i) = x);
     {
@@ -400,7 +413,7 @@ void asmEndBCO( AsmBCO bco )
         bcoInstr(o,j++) = i_HP_CHECK;
         bcoInstr(o,j++) = bco->max_hp;
 #endif
-        mapQueue(Instrs,  StgNat8,   bco->is,   bcoInstr(o,j++) = x);
+        mapQueue(Instrs,  StgWord8,   bco->is,   bcoInstr(o,j++) = x);
         ASSERT(j == is);
     }
     asmEndObject(&bco->object,c);
@@ -410,12 +423,25 @@ void asmEndBCO( AsmBCO bco )
  * 
  * ------------------------------------------------------------------------*/
 
-static void asmInstr( AsmBCO bco, StgWord i )
+static void asmInstr8 ( AsmBCO bco, StgWord i )
 {
+    if (i >= 256) {
+       fprintf(stderr, "too big (256)\n");
+    }
     ASSERT(i < 256); /* must be a byte */
     insertInstrs(&(bco->is),i);
 }
 
+static void asmInstr16 ( AsmBCO bco, StgWord i )
+{
+    if (i >= 65536) {
+       fprintf(stderr, "too big (65536)\n");
+    }
+    ASSERT(i < 65536); /* must be a byte */
+    insertInstrs(&(bco->is),i / 256);
+    insertInstrs(&(bco->is),i % 256);
+}
+
 static void asmPtr( AsmBCO bco, AsmObject x )
 {
     insertPtrs( &bco->object.ptrs, x );
@@ -430,6 +456,7 @@ static void asmWord( AsmBCO bco, StgWord i )
     {                                                    \
         union { ty a; AsmWord b[sizeofW(ty)]; } p;       \
         nat i;                                           \
+        if (sizeof(ty) < sizeof(AsmWord)) p.b[0]=0;      \
         p.a = x;                                         \
         for( i = 0; i < sizeofW(ty); i++ ) {             \
             asmWord(bco,p.b[i]);                         \
@@ -491,6 +518,231 @@ static StgWord repSizeW( AsmRep rep )
 }
 
 /* --------------------------------------------------------------------------
+ * Instruction emission
+ * ------------------------------------------------------------------------*/
+
+static void emit_i0 ( AsmBCO bco, Instr opcode )
+{
+   asmInstr8(bco,opcode);
+}
+
+static void emit_i1 ( AsmBCO bco, Instr opcode, int arg1 )
+{
+   asmInstr8(bco,opcode);
+   asmInstr8(bco,arg1);
+}
+
+static void emit_i2 ( AsmBCO bco, Instr opcode, int arg1, int arg2 )
+{
+   asmInstr8(bco,opcode);
+   asmInstr8(bco,arg1);
+   asmInstr8(bco,arg2);
+}
+
+static void emit_i_VAR_INT ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR_INT);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_INT_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+#ifdef PROVIDE_ADDR
+static void emit_i_VAR_ADDR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR_ADDR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_ADDR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+#endif
+
+static void emit_i_VAR_CHAR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR_CHAR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_CHAR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_VAR_FLOAT ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR_FLOAT);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_FLOAT_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_VAR_DOUBLE ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR_DOUBLE);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_DOUBLE_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_VAR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_VAR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_VAR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_SLIDE ( AsmBCO bco, int arg1, int arg2 )
+{
+   ASSERT(arg1 >= 0);
+   ASSERT(arg2 >= 0);
+   if (arg1 < 256 && arg2 < 256) {
+      asmInstr8(bco,i_SLIDE);
+      asmInstr8(bco,arg1);
+      asmInstr8(bco,arg2);
+   } else {
+      asmInstr8(bco,i_SLIDE_big);
+      asmInstr16(bco,arg1);
+      asmInstr16(bco,arg2);
+   }
+}
+
+static void emit_i_MKAP ( AsmBCO bco, int arg1, int arg2 )
+{
+   ASSERT(arg1 >= 0);
+   ASSERT(arg2 >= 0);
+   if (arg1 < 256 && arg2 < 256) {
+      asmInstr8(bco,i_MKAP);
+      asmInstr8(bco,arg1);
+      asmInstr8(bco,arg2);
+   } else {
+      asmInstr8(bco,i_MKAP_big);
+      asmInstr16(bco,arg1);
+      asmInstr16(bco,arg2);
+   }
+}
+
+static void emit_i_CONST_INT ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_INT);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_INT_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+#ifdef PROVIDE_INTEGER
+static void emit_i_CONST_INTEGER ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_INTEGER);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_INTEGER_big);
+      asmInstr16(bco,arg1);
+   }
+}
+#endif
+
+static void emit_i_CONST_ADDR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_ADDR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_ADDR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_CONST_CHAR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_CHAR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_CHAR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_CONST_FLOAT ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_FLOAT);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_FLOAT_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_CONST_DOUBLE ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST_DOUBLE);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_DOUBLE_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_RETADDR ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_RETADDR);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_RETADDR_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+static void emit_i_CONST ( AsmBCO bco, int arg1 )
+{
+   ASSERT(arg1 >= 0);
+   if (arg1 < 256) {
+      asmInstr8(bco,i_CONST);
+      asmInstr8(bco,arg1);
+   } else {
+      asmInstr8(bco,i_CONST_big);
+      asmInstr16(bco,arg1);
+   }
+}
+
+
+/* --------------------------------------------------------------------------
  * Arg checks.
  * ------------------------------------------------------------------------*/
 
@@ -504,8 +756,7 @@ void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg )
 {
     nat args = bco->sp - last_arg;
     if (args != 0) { /* optimisation */
-        asmInstr(bco,i_ARG_CHECK);
-        asmInstr(bco,args);
+        emit_i1(bco,i_ARG_CHECK,args);
         grabHpNonUpd(bco,PAP_sizeW(args-1));
         resetHp(bco,0);
     }
@@ -523,38 +774,47 @@ AsmVar asmBind          ( AsmBCO bco, AsmRep rep )
 
 void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
 {
+    int offset;
+
+    if (rep == VOID_REP) {
+        emit_i0(bco,i_VOID);
+        bco->sp += repSizeW(rep);
+        return;
+    }
+
+    offset = bco->sp - v;
     switch (rep) {
     case BOOL_REP:
     case INT_REP:
-            asmInstr(bco,i_VAR_INT);
+            emit_i_VAR_INT(bco,offset);
             break;
 #ifdef PROVIDE_INT64
     case INT64_REP:
-            asmInstr(bco,i_VAR_INT64);
+            emit_i_VAR_INT64(bco,offset);
             break;
 #endif
 #ifdef PROVIDE_WORD
     case WORD_REP:
-            asmInstr(bco,i_VAR_WORD);
+            emit_i_VAR_WORD(bco,offset);
             break;
 #endif
 #ifdef PROVIDE_ADDR
     case ADDR_REP:
-            asmInstr(bco,i_VAR_ADDR);
+            emit_i_VAR_ADDR(bco,offset);
             break;
 #endif
     case CHAR_REP:
-            asmInstr(bco,i_VAR_CHAR);
+            emit_i_VAR_CHAR(bco,offset);
             break;
     case FLOAT_REP:
-            asmInstr(bco,i_VAR_FLOAT);
+            emit_i_VAR_FLOAT(bco,offset);
             break;
     case DOUBLE_REP:
-            asmInstr(bco,i_VAR_DOUBLE);
+            emit_i_VAR_DOUBLE(bco,offset);
             break;
 #ifdef PROVIDE_STABLE
     case STABLE_REP:
-            asmInstr(bco,i_VAR_STABLE);
+            emit_i_VAR_STABLE(bco,offset);
             break;
 #endif
 
@@ -584,17 +844,11 @@ void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
     case MVAR_REP:     /* MVar a                  */
 #endif
     case PTR_REP:
-            asmInstr(bco,i_VAR);
+            emit_i_VAR(bco,offset);
             break;
-
-    case VOID_REP:
-            asmInstr(bco,i_VOID);
-            bco->sp += repSizeW(rep);
-            return; /* NB we don't break! */
     default:
             barf("asmVar %d",rep);
     }
-    asmInstr(bco,bco->sp - v);
     bco->sp += repSizeW(rep);
 }
 
@@ -613,12 +867,10 @@ void asmEndEnter( AsmBCO bco, AsmSp sp1, AsmSp sp2 )
     int y = sp1 - sp2;
     ASSERT(x >= 0 && y >= 0);
     if (y != 0) {
-        asmInstr(bco,i_SLIDE);
-        asmInstr(bco,x);
-        asmInstr(bco,y);
+        emit_i_SLIDE(bco,x,y);
         bco->sp -= sp1 - sp2;
     }
-    asmInstr(bco,i_ENTER);
+    emit_i0(bco,i_ENTER);
 }
 
 /* --------------------------------------------------------------------------
@@ -629,42 +881,42 @@ AsmVar asmBox( AsmBCO bco, AsmRep rep )
 {
     switch (rep) {
     case CHAR_REP:
-            asmInstr(bco,i_PACK_CHAR);
+            emit_i0(bco,i_PACK_CHAR);
             grabHpNonUpd(bco,Czh_sizeW);
             break;
     case INT_REP:
-            asmInstr(bco,i_PACK_INT);
+            emit_i0(bco,i_PACK_INT);
             grabHpNonUpd(bco,Izh_sizeW);
             break;
 #ifdef PROVIDE_INT64
     case INT64_REP:
-            asmInstr(bco,i_PACK_INT64);
+            emit_i0(bco,i_PACK_INT64);
             grabHpNonUpd(bco,I64zh_sizeW);
             break;
 #endif
 #ifdef PROVIDE_WORD
     case WORD_REP:
-            asmInstr(bco,i_PACK_WORD);
+            emit_i0(bco,i_PACK_WORD);
             grabHpNonUpd(bco,Wzh_sizeW);
             break;
 #endif
 #ifdef PROVIDE_ADDR
     case ADDR_REP:
-            asmInstr(bco,i_PACK_ADDR);
+            emit_i0(bco,i_PACK_ADDR);
             grabHpNonUpd(bco,Azh_sizeW);
             break;
 #endif
     case FLOAT_REP:
-            asmInstr(bco,i_PACK_FLOAT);
+            emit_i0(bco,i_PACK_FLOAT);
             grabHpNonUpd(bco,Fzh_sizeW);
             break;
     case DOUBLE_REP:
-            asmInstr(bco,i_PACK_DOUBLE);
+            emit_i0(bco,i_PACK_DOUBLE);
             grabHpNonUpd(bco,Dzh_sizeW);
             break;
 #ifdef PROVIDE_STABLE
     case STABLE_REP:
-            asmInstr(bco,i_PACK_STABLE);
+            emit_i0(bco,i_PACK_STABLE);
             grabHpNonUpd(bco,Stablezh_sizeW);
             break;
 #endif
@@ -686,36 +938,37 @@ AsmVar asmUnbox( AsmBCO bco, AsmRep rep )
 {
     switch (rep) {
     case INT_REP:
-            asmInstr(bco,i_UNPACK_INT);
+            emit_i0(bco,i_UNPACK_INT);
             break;
 #ifdef PROVIDE_INT64
     case INT64_REP:
-            asmInstr(bco,i_UNPACK_INT64);
+            emit_i0(bco,i_UNPACK_INT64);
             break;
 #endif
 #ifdef PROVIDE_WORD
     case WORD_REP:
-            asmInstr(bco,i_UNPACK_WORD);
+            emit_i0(bco,i_UNPACK_WORD);
             break;
 #endif
 #ifdef PROVIDE_ADDR
     case ADDR_REP:
-            asmInstr(bco,i_UNPACK_ADDR);
+            emit_i0(bco,i_UNPACK_ADDR);
             break;
 #endif
     case CHAR_REP:
-            asmInstr(bco,i_UNPACK_CHAR);
+            emit_i0(bco,i_UNPACK_CHAR);
             break;
     case FLOAT_REP:
-            asmInstr(bco,i_UNPACK_FLOAT);
+            emit_i0(bco,i_UNPACK_FLOAT);
             break;
     case DOUBLE_REP:
-            asmInstr(bco,i_UNPACK_DOUBLE);
+            emit_i0(bco,i_UNPACK_DOUBLE);
             break;
+#ifdef PROVIDE_STABLE
     case STABLE_REP:
-            asmInstr(bco,i_UNPACK_STABLE);
+            emit_i0(bco,i_UNPACK_STABLE);
             break;
-
+#endif
     default:
             barf("asmUnbox %d",rep);
     }
@@ -732,35 +985,35 @@ void asmReturnUnboxed( AsmBCO bco, AsmRep rep )
 {
     switch (rep) {
     case CHAR_REP:
-            asmInstr(bco,i_RETURN_CHAR);
+            emit_i0(bco,i_RETURN_CHAR);
             break;
     case INT_REP:
-            asmInstr(bco,i_RETURN_INT);
+            emit_i0(bco,i_RETURN_INT);
             break;
 #ifdef PROVIDE_INT64
     case INT64_REP:
-            asmInstr(bco,i_RETURN_INT64);
+            emit_i0(bco,i_RETURN_INT64);
             break;
 #endif
 #ifdef PROVIDE_WORD
     case WORD_REP:
-            asmInstr(bco,i_RETURN_WORD);
+            emit_i0(bco,i_RETURN_WORD);
             break;
 #endif
 #ifdef PROVIDE_ADDR
     case ADDR_REP:
-            asmInstr(bco,i_RETURN_ADDR);
+            emit_i0(bco,i_RETURN_ADDR);
             break;
 #endif
     case FLOAT_REP:
-            asmInstr(bco,i_RETURN_FLOAT);
+            emit_i0(bco,i_RETURN_FLOAT);
             break;
     case DOUBLE_REP:
-            asmInstr(bco,i_RETURN_DOUBLE);
+            emit_i0(bco,i_RETURN_DOUBLE);
             break;
 #ifdef PROVIDE_STABLE
     case STABLE_REP:
-            asmInstr(bco,i_RETURN_STABLE);
+            emit_i0(bco,i_RETURN_STABLE);
             break;
 #endif
 #ifdef PROVIDE_INTEGER
@@ -783,7 +1036,7 @@ void asmReturnUnboxed( AsmBCO bco, AsmRep rep )
     case THREADID_REP: /* ThreadId                 */ 
     case MVAR_REP:     /* MVar a                   */ 
 #endif
-            asmInstr(bco,i_RETURN_GENERIC);
+            emit_i0(bco,i_RETURN_GENERIC);
             break;
     default:
             barf("asmReturnUnboxed %d",rep);
@@ -796,8 +1049,7 @@ void asmReturnUnboxed( AsmBCO bco, AsmRep rep )
 
 void asmConstInt( AsmBCO bco, AsmInt x )
 {
-    asmInstr(bco,i_CONST_INT);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_INT(bco,bco->nps.len);
     asmWords(bco,AsmInt,x);
     bco->sp += repSizeW(INT_REP);
 }
@@ -805,8 +1057,7 @@ void asmConstInt( AsmBCO bco, AsmInt x )
 #ifdef PROVIDE_INT64
 void asmConstInt64( AsmBCO bco, AsmInt64 x )
 {
-    asmInstr(bco,i_CONST_INT64);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_INT64(bco,bco->nps.len);
     asmWords(bco,AsmInt64,x);
     bco->sp += repSizeW(INT64_REP);
 }
@@ -815,8 +1066,7 @@ void asmConstInt64( AsmBCO bco, AsmInt64 x )
 #ifdef PROVIDE_INTEGER
 void asmConstInteger( AsmBCO bco, AsmString x )
 {
-    asmInstr(bco,i_CONST_INTEGER);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_INTEGER(bco,bco->nps.len);
     asmWords(bco,AsmString,x);
     bco->sp += repSizeW(INTEGER_REP);
 }
@@ -825,8 +1075,7 @@ void asmConstInteger( AsmBCO bco, AsmString x )
 #ifdef PROVIDE_ADDR
 void asmConstAddr( AsmBCO bco, AsmAddr x )
 {
-    asmInstr(bco,i_CONST_ADDR);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_ADDR(bco,bco->nps.len);
     asmWords(bco,AsmAddr,x);
     bco->sp += repSizeW(ADDR_REP);
 }
@@ -835,8 +1084,7 @@ void asmConstAddr( AsmBCO bco, AsmAddr x )
 #ifdef PROVIDE_WORD
 void asmConstWord( AsmBCO bco, AsmWord x )
 {
-    asmInstr(bco,i_CONST_INT);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_INT(bco->nps.len);
     asmWords(bco,AsmWord,x);
     bco->sp += repSizeW(WORD_REP);
 }
@@ -844,30 +1092,27 @@ void asmConstWord( AsmBCO bco, AsmWord x )
 
 void asmConstChar( AsmBCO bco, AsmChar x )
 {
-    asmInstr(bco,i_CONST_CHAR);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_CHAR(bco,bco->nps.len);
     asmWords(bco,AsmChar,x);
     bco->sp += repSizeW(CHAR_REP);
 }
 
 void asmConstFloat( AsmBCO bco, AsmFloat x )
 {
-    asmInstr(bco,i_CONST_FLOAT);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_FLOAT(bco,bco->nps.len);
     asmWords(bco,AsmFloat,x);
     bco->sp += repSizeW(FLOAT_REP);
 }
 
 void asmConstDouble( AsmBCO bco, AsmDouble x )
 {
-    asmInstr(bco,i_CONST_DOUBLE);
-    asmInstr(bco,bco->nps.len);
+    emit_i_CONST_DOUBLE(bco,bco->nps.len);
     asmWords(bco,AsmDouble,x);
     bco->sp += repSizeW(DOUBLE_REP);
 }
 
 /* --------------------------------------------------------------------------
- *
+ * Algebraic case helpers
  * ------------------------------------------------------------------------*/
 
 /* a mildly bogus pair of functions... */
@@ -882,16 +1127,15 @@ void asmEndCase( AsmBCO bco )
 
 AsmSp asmContinuation( AsmBCO bco, AsmBCO ret_addr )
 {
-    asmInstr(bco,i_RETADDR);
-    asmInstr(bco,bco->object.ptrs.len);
+    emit_i_RETADDR(bco,bco->object.ptrs.len);
     asmPtr(bco,&(ret_addr->object));
     bco->sp += 2 * sizeofW(StgPtr);
     return bco->sp;
 }
 
-AsmBCO asmBeginContinuation ( AsmSp sp )
+AsmBCO asmBeginContinuation ( AsmSp sp, int /*List*/ alts )
 {
-    AsmBCO bco = asmBeginBCO();
+    AsmBCO bco = asmBeginBCO(alts);
     bco->sp = sp;
     return bco;
 }
@@ -901,6 +1145,7 @@ void asmEndContinuation ( AsmBCO bco )
     asmEndBCO(bco);
 }
 
+
 /* --------------------------------------------------------------------------
  * Branches
  * ------------------------------------------------------------------------*/
@@ -923,9 +1168,9 @@ void asmEndAlt( AsmBCO bco, AsmSp  sp )
 
 AsmPc asmTest( AsmBCO bco, AsmWord tag )
 {
-    asmInstr(bco,i_TEST);
-    asmInstr(bco,tag);
-    asmInstr(bco,0);
+    asmInstr8(bco,i_TEST);
+    asmInstr8(bco,tag);
+    asmInstr16(bco,0);
     return bco->is.len;
 }
 
@@ -933,8 +1178,8 @@ AsmPc asmTestInt( AsmBCO bco, AsmVar v, AsmInt x )
 {
     asmVar(bco,v,INT_REP);
     asmConstInt(bco,x);
-    asmInstr(bco,i_TEST_INT);
-    asmInstr(bco,0);
+    asmInstr8(bco,i_TEST_INT);
+    asmInstr16(bco,0);
     bco->sp -= 2*repSizeW(INT_REP);
     return bco->is.len;
 }
@@ -943,12 +1188,14 @@ void asmFixBranch( AsmBCO bco, AsmPc from )
 {
     int distance = bco->is.len - from;
     ASSERT(distance >= 0);
-    setInstrs(&(bco->is),from-1,distance);
+    ASSERT(distance < 65536);
+    setInstrs(&(bco->is),from-2,distance/256);
+    setInstrs(&(bco->is),from-1,distance%256);
 }
 
 void asmPanic( AsmBCO bco )
 {
-    asmInstr(bco,i_PANIC); /* "irrefutable" pattern failed - oops! */
+    emit_i0(bco,i_PANIC); /* "irrefutable" pattern failed - oops! */
 }
 
 /* --------------------------------------------------------------------------
@@ -962,8 +1209,7 @@ AsmSp asmBeginPrim( AsmBCO bco )
 
 void   asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
 {
-    asmInstr(bco,prim->prefix);
-    asmInstr(bco,prim->opcode);
+    emit_i1(bco,prim->prefix,prim->opcode);
     bco->sp = base;
 }
 
@@ -1005,9 +1251,9 @@ const AsmPrim asmPrimOps[] = {
     , { "primOrInt",                 "II", "I",  MONAD_Id, i_PRIMOP1, i_orInt }
     , { "primXorInt",                "II", "I",  MONAD_Id, i_PRIMOP1, i_xorInt }
     , { "primNotInt",                "I",  "I",  MONAD_Id, i_PRIMOP1, i_notInt }
-    , { "primShiftLInt",             "IW", "I",  MONAD_Id, i_PRIMOP1, i_shiftLInt }
-    , { "primShiftRAInt",            "IW", "I",  MONAD_Id, i_PRIMOP1, i_shiftRAInt }
-    , { "primShiftRLInt",            "IW", "I",  MONAD_Id, i_PRIMOP1, i_shiftRLInt }
+    , { "primShiftLInt",             "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftLInt }
+    , { "primShiftRAInt",            "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftRAInt }
+    , { "primShiftRLInt",            "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftRLInt }
 
 #ifdef PROVIDE_INT64
     /* Int64# operations */
@@ -1093,7 +1339,9 @@ const AsmPrim asmPrimOps[] = {
 #ifdef PROVIDE_INT64
     , { "primIndexInt64OffAddr",     "AI", "z",  MONAD_Id, i_PRIMOP1, i_indexInt64OffAddr }
 #endif
+#ifdef PROVIDE_WORD
     , { "primIndexWordOffAddr",      "AI", "W",  MONAD_Id, i_PRIMOP1, i_indexWordOffAddr }
+#endif
     , { "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 }
@@ -1107,7 +1355,9 @@ const AsmPrim asmPrimOps[] = {
 #ifdef PROVIDE_INT64                 
     , { "primReadInt64OffAddr",      "AI", "z",  MONAD_ST, i_PRIMOP1, i_readInt64OffAddr }
 #endif                               
+#ifdef PROVIDE_WORD
     , { "primReadWordOffAddr",       "AI", "W",  MONAD_ST, i_PRIMOP1, i_readWordOffAddr }
+#endif
     , { "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 }
@@ -1121,7 +1371,9 @@ const AsmPrim asmPrimOps[] = {
 #ifdef PROVIDE_INT64
     , { "primWriteInt64OffAddr",     "AIz", "",  MONAD_ST, i_PRIMOP1, i_writeInt64OffAddr }
 #endif
+#ifdef PROVIDE_WORD
     , { "primWriteWordOffAddr",      "AIW", "",  MONAD_ST, i_PRIMOP1, i_writeWordOffAddr }
+#endif
     , { "primWriteAddrOffAddr",      "AIA", "",  MONAD_ST, i_PRIMOP1, i_writeAddrOffAddr }
     , { "primWriteFloatOffAddr",     "AIF", "",  MONAD_ST, i_PRIMOP1, i_writeFloatOffAddr }
     , { "primWriteDoubleOffAddr",    "AID", "",  MONAD_ST, i_PRIMOP1, i_writeDoubleOffAddr }
@@ -1142,8 +1394,10 @@ const AsmPrim asmPrimOps[] = {
     , { "primDivModInteger",         "ZZ", "ZZ", MONAD_Id, i_PRIMOP1, i_divModInteger }
     , { "primIntegerToInt",          "Z",  "I",  MONAD_Id, i_PRIMOP1, i_integerToInt }
     , { "primIntToInteger",          "I",  "Z",  MONAD_Id, i_PRIMOP1, i_intToInteger }
+#ifdef PROVIDE_INT64
     , { "primIntegerToInt64",        "Z",  "z",  MONAD_Id, i_PRIMOP1, i_integerToInt64 }
     , { "primInt64ToInteger",        "z",  "Z",  MONAD_Id, i_PRIMOP1, i_int64ToInteger }
+#endif
 #ifdef PROVIDE_WORD
     , { "primIntegerToWord",         "Z",  "W",  MONAD_Id, i_PRIMOP1, i_integerToWord }
     , { "primWordToInteger",         "W",  "Z",  MONAD_Id, i_PRIMOP1, i_wordToInteger }
@@ -1252,11 +1506,11 @@ const AsmPrim asmPrimOps[] = {
 
 
     /* Polymorphic force :: a -> (# #) */
-    , { "primForce",                 "a",  "",   MONAD_Id, i_PRIMOP2, i_force }
+      /* , { "primForce",                 "a",  "",   MONAD_Id, i_PRIMOP2, i_force } */
 
     /* Error operations - not in IO monad! */
-    , { "primRaise",                 "E",  "a",  MONAD_Id, i_PRIMOP2, i_raise }
-    , { "primCatch'",                "aH", "a",  MONAD_Id, i_PRIMOP2, i_catch }
+      //, { "primRaise",                 "E",  "a",  MONAD_Id, i_PRIMOP2, i_raise }
+      //, { "primCatch'",                "aH", "a",  MONAD_Id, i_PRIMOP2, i_catch }
 
 #ifdef PROVIDE_ARRAY
     /* Ref operations */
@@ -1367,6 +1621,7 @@ const AsmPrim asmPrimOps[] = {
 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 };
 
+
 const AsmPrim* asmFindPrim( char* s )
 {
     int i;
@@ -1390,14 +1645,63 @@ const AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
 }
 
 /* --------------------------------------------------------------------------
+ * Handwritten primops
+ * ------------------------------------------------------------------------*/
+
+AsmBCO asm_BCO_catch ( void )
+{
+   AsmBCO bco = asmBeginBCO(0 /*NIL*/);
+   emit_i1(bco,i_ARG_CHECK,2);
+   emit_i1(bco,i_PRIMOP1,i_pushcatchframe);
+   bco->sp += (1-2)*sizeofW(StgPtr) + sizeofW(StgCatchFrame);
+   emit_i0(bco,i_ENTER);
+   asmEndBCO(bco);
+   return bco;
+}
+
+AsmBCO asm_BCO_raise ( void )
+{
+   AsmBCO bco = asmBeginBCO(0 /*NIL*/);
+   emit_i1(bco,i_ARG_CHECK,1);
+   emit_i1(bco,i_PRIMOP2,i_raise);
+   asmEndBCO(bco);
+   return bco;
+}
+
+AsmBCO asm_BCO_seq ( void )
+{
+   AsmBCO eval, cont;
+
+   cont = asmBeginBCO(0 /*NIL*/);
+   emit_i1(cont,i_ARG_CHECK,2);
+   emit_i_VAR(cont,1);
+   emit_i_SLIDE(cont,1,2);
+   emit_i0(cont,i_ENTER);
+   cont->sp += 3*sizeofW(StgPtr);
+   asmEndBCO(cont);
+
+   eval = asmBeginBCO(0 /*NIL*/);
+   emit_i1(eval,i_ARG_CHECK,2);
+   emit_i_RETADDR(eval,eval->object.ptrs.len);
+   asmPtr(eval,&(cont->object));
+   emit_i_VAR(eval,2);
+   emit_i_SLIDE(eval,3,1);
+   emit_i1(eval,i_PRIMOP1,i_pushseqframe);
+   emit_i0(eval,i_ENTER);
+   eval->sp += sizeofW(StgSeqFrame) + 4*sizeofW(StgPtr);
+   asmEndBCO(eval);
+
+   return eval;
+}
+
+/* --------------------------------------------------------------------------
  * Heap manipulation
  * ------------------------------------------------------------------------*/
 
 AsmVar asmAllocCONSTR   ( AsmBCO bco, AsmInfo info )
 {
     ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
-    asmInstr(bco,i_ALLOC_CONSTR);
-    asmInstr(bco,bco->nps.len);
+    emit_i1(bco,i_ALLOC_CONSTR,bco->nps.len);
     asmWords(bco,AsmInfo,info);
     bco->sp += sizeofW(StgClosurePtr);
     grabHpNonUpd(bco,sizeW_fromITBL(info));
@@ -1412,12 +1716,11 @@ AsmSp asmBeginPack( AsmBCO bco )
 void asmEndPack( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info )
 {
     nat size = bco->sp - start;
-    ASSERT(bco->sp >= start);
-    ASSERT(start >= v);
+    assert(bco->sp >= start);
+    assert(start >= v);
     /* only reason to include info is for this assertion */
-    ASSERT(info->layout.payload.ptrs == size);
-    asmInstr(bco,i_PACK);
-    asmInstr(bco,bco->sp - v);
+    assert(info->layout.payload.ptrs == size);
+    emit_i1(bco,i_PACK,bco->sp - v);
     bco->sp = start;
 }
 
@@ -1428,13 +1731,12 @@ void asmBeginUnpack( AsmBCO bco )
 
 void asmEndUnpack( AsmBCO bco )
 {
-    asmInstr(bco,i_UNPACK);
+    emit_i0(bco,i_UNPACK);
 }
 
 AsmVar asmAllocAP( AsmBCO bco, AsmNat words )
 {
-    asmInstr(bco,i_ALLOC_AP);
-    asmInstr(bco,words);
+    emit_i1(bco,i_ALLOC_AP,words);
     bco->sp += sizeofW(StgPtr);
     grabHpUpd(bco,AP_sizeW(words));
     return bco->sp;
@@ -1447,16 +1749,14 @@ AsmSp asmBeginMkAP( AsmBCO bco )
 
 void asmEndMkAP( AsmBCO bco, AsmVar v, AsmSp start )
 {
-    asmInstr(bco,i_MKAP);
-    asmInstr(bco,bco->sp-v);
-    asmInstr(bco,bco->sp-start-1);  /* -1 because fun isn't counted */
+    emit_i_MKAP(bco,bco->sp-v,bco->sp-start-1);
+            /* -1 because fun isn't counted */
     bco->sp = start;
 }
 
 AsmVar asmAllocPAP( AsmBCO bco, AsmNat size )
 {
-    asmInstr(bco,i_ALLOC_PAP);
-    asmInstr(bco,size);
+    emit_i1(bco,i_ALLOC_PAP,size);
     bco->sp += sizeofW(StgPtr);
     return bco->sp;
 }
@@ -1468,25 +1768,15 @@ AsmSp asmBeginMkPAP( AsmBCO bco )
 
 void asmEndMkPAP( AsmBCO bco, AsmVar v, AsmSp start )
 {
-    asmInstr(bco,i_MKPAP);
-    asmInstr(bco,bco->sp-v);
-    asmInstr(bco,bco->sp-start-1);  /* -1 because fun isn't counted */
+    emit_i2(bco,i_MKPAP,bco->sp-v,bco->sp-start-1);
+            /* -1 because fun isn't counted */
     bco->sp = start;
 }
 
 AsmVar asmClosure( AsmBCO bco, AsmObject p )
 {
-    StgWord o = bco->object.ptrs.len;
-    if (o < 256) {
-        asmInstr(bco,i_CONST);
-        asmInstr(bco,o);
-        asmPtr(bco,p);
-    } else {
-        asmInstr(bco,i_CONST2);
-        asmInstr(bco,o / 256);
-        asmInstr(bco,o % 256);
-        asmPtr(bco,p);
-    }
+    emit_i_CONST(bco,bco->object.ptrs.len);
+    asmPtr(bco,p);
     bco->sp += sizeofW(StgPtr);
     return bco->sp;
 }