[project @ 1999-03-01 14:46:42 by sewardj]
[ghc-hetmet.git] / ghc / rts / Assembler.c
1
2 /* --------------------------------------------------------------------------
3  * Bytecode assembler
4  *
5  * Copyright (c) 1994-1998.
6  *
7  * $RCSfile: Assembler.c,v $
8  * $Revision: 1.5 $
9  * $Date: 1999/03/01 14:47:02 $
10  *
11  * This module provides functions to construct BCOs and other closures
12  * required by the bytecode compiler.
13  *
14  * It is supposed to shield the compiler from platform dependent information
15  * such as:
16  *
17  * o sizeof(StgFloat)
18  * o sizeof(I#)
19  *
20  * and from details of how the abstract machine is implemented such as:
21  *
22  * o what does a BCO look like?
23  * o how many bytes does the "Push InfoTable" instruction require?
24  *
25  * Details of design:
26  * o (To handle letrecs) We allocate Aps, Paps and Cons using number of
27  *   heap allocated args to determine size.
28  *   We can't handle unboxed args :-(
29  * o All stack offsets are relative to position of Sp at start of
30  *   function or thunk (not BCO - consider continuations)
31  * o Active thunks must be roots during GC - how to achieve this?
32  * o Each BCO contains its own stack and heap check
33  *   We don't try to exploit the Hp check optimisation - easier to make
34  *   each thunk stand on its own.
35  * o asBind returns a "varid" (which is, in fact, a stack offset)
36  *   asVar acts on a "varid" - combining it with the current stack size to
37  *   determine actual position
38  * o Assembler.h uses totally neutral types: strings, floats, ints, etc
39  *   to minimise conflicts with other parts of the system.
40  * Simulated Stack
41  * ------------------------------------------------------------------------*/
42
43 #include "Rts.h"
44
45 #ifdef INTERPRETER
46
47 #include "RtsFlags.h"
48 #include "RtsUtils.h"
49 #include "Bytecodes.h"
50 #include "Printer.h"
51 #include "Disassembler.h"
52 #include "Evaluator.h"
53 #include "StgMiscClosures.h"
54 #include "Storage.h"
55
56 #define INSIDE_ASSEMBLER_C
57 #include "Assembler.h"
58 #undef INSIDE_ASSEMBLER_C
59
60 /* --------------------------------------------------------------------------
61  * References between BCOs
62  *
63  * These are necessary because there can be circular references between 
64  * BCOs so we have to keep track of all the references to each object
65  * and fill in all the references once we're done.
66  *
67  * ToDo: generalise to allow references between any objects
68  * ------------------------------------------------------------------------*/
69
70 typedef struct {
71     AsmObject ref;  /* who refers to it                       */
72     AsmNat i;       /* index into some table held by referer  */
73 } AsmRef;
74
75 /* --------------------------------------------------------------------------
76  * Queues (of instructions, ptrs, nonptrs)
77  * ------------------------------------------------------------------------*/
78
79 /* ToDo: while debugging, we use a chunk size of 1 to stress-test the code
80  * this should be fine-tuned using statistics on common sizes
81  */
82
83 #define InstrsChunkSize  40
84 #define PtrsChunkSize    10
85 #define RefsChunkSize    10
86 #define NonPtrsChunkSize 10
87
88 #define Queue Instrs
89 #define Type  StgNat8
90 #include "QueueTemplate.h"
91 #undef Type
92 #undef Queue
93
94 #define Queue Ptrs
95 #define Type  AsmObject
96 #include "QueueTemplate.h"
97 #undef Type
98 #undef Queue
99
100 #define Queue Refs
101 #define Type  AsmRef
102 #include "QueueTemplate.h"
103 #undef Type
104 #undef Queue
105
106 #define Queue NonPtrs
107 #define Type  StgWord
108 #include "QueueTemplate.h"
109 #undef Type
110 #undef Queue
111
112 /* --------------------------------------------------------------------------
113  * AsmObjects are used to build heap objects.
114  *
115  * AsmObjects can contain circular references to each other
116  * so we have to keep track of all the references which can't be filled
117  * in yet.
118  *
119  * When we finish building an AsmObject, we allocate an actual heap object and
120  * fill in all the references to the asmObject with pointers to the heap object.
121  *
122  * We obtain a limited form of polymorphism through inheritance by putting 
123  * the AsmObject first in every structure (as in C++ implementations).
124  * We use the closure type of the allocated object to figure out
125  * where the payload lives in the closure.
126  * ------------------------------------------------------------------------*/
127 /* ToDo: clean up terminology: is Closure right or should it be object or ... */
128
129 struct AsmObject_ {
130     Refs           refs;
131     Ptrs           ptrs;
132     AsmNat         num_unresolved; /* number of unfilled references */
133     StgClosure*    closure;        /* where object was allocated    */
134 };
135     
136 struct AsmCon_ {
137     struct AsmObject_ object;  /* must be first in struct */
138
139     AsmInfo info;
140 };
141   
142 struct AsmCAF_ {
143     struct AsmObject_ object;  /* must be first in struct */
144 };
145
146 struct AsmBCO_ {
147     struct AsmObject_ object;  /* must be first in struct */
148
149     int /*StgExpr*/  stgexpr;    
150     Instrs   is;          
151     NonPtrs  nps;
152
153     /* abstract machine ("executed" during compilation) */
154     AsmSp    sp;          /* stack ptr */
155     AsmSp    max_sp;
156     StgWord  hp;          /* heap ptr  */
157     StgWord  max_hp;
158 };
159
160 static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
161 {
162     ASSERT(obj->closure);
163     switch (get_itbl(obj->closure)->type) {
164     case BCO:
165         {
166             StgBCO* bco = stgCast(StgBCO*,obj->closure);
167             ASSERT(i < bco->n_ptrs && bcoConstPtr(bco,i) == NULL);
168             bcoConstCPtr(bco,i) = reference;
169             break;
170         }
171     case CAF_UNENTERED:
172         {
173             StgCAF* caf = stgCast(StgCAF*,obj->closure);
174             ASSERT(i == 0 && caf->body == NULL);
175             caf->body = reference;
176             break;
177         }
178     case CONSTR:
179         {
180             StgClosure* con = stgCast(StgClosure*,obj->closure);
181             ASSERT(i < get_itbl(con)->layout.payload.nptrs && payloadCPtr(con,i) == NULL);
182             payloadCPtr(con,i) = reference;
183             break;
184         }
185     case AP_UPD:
186         {
187             StgAP_UPD* ap = stgCast(StgAP_UPD*,obj->closure);
188             ASSERT(i < 1+ap->n_args);
189             if (i==0) {
190                 ASSERT(ap->fun == NULL);
191                 ap->fun = reference;
192             } else {
193                 ASSERT(payloadCPtr(ap,i-1) == NULL);
194                 payloadCPtr(ap,i-1) = reference;
195             }
196             break;
197         }
198     default:
199             barf("asmResolveRef");
200     }
201     obj->num_unresolved -= 1;
202
203     if (obj->num_unresolved == 0) {
204         /* todo: free the queues */
205
206         /* we don't print until all ptrs are resolved */
207         IF_DEBUG(codegen,printObj(obj->closure);printf("\n\n"));
208     }
209 }
210
211 static void asmAddRef( AsmObject referent, AsmObject referer, AsmNat i )
212 {
213     if (referent->closure) {
214         asmResolveRef(referer,i,(AsmClosure)referent->closure);
215     } else {
216         insertRefs(&(referent->refs),(AsmRef){referer,i});
217     }
218 }
219
220 void asmAddPtr( AsmObject obj, AsmObject arg )
221 {
222     ASSERT(obj->closure == 0); /* can't extend an object once it's allocated */
223     insertPtrs( &obj->ptrs, arg );
224 }
225
226 static void asmBeginObject( AsmObject obj )
227 {
228     obj->closure = NULL;
229     obj->num_unresolved = 0;
230     initRefs(&obj->refs);
231     initPtrs(&obj->ptrs);
232 }
233
234 static void asmEndObject( AsmObject obj, StgClosure* c )
235 {
236     obj->num_unresolved = obj->ptrs.len;
237     obj->closure = c;
238     mapQueue(Ptrs,    AsmObject, obj->ptrs, asmAddRef(x,obj,i));
239     mapQueue(Refs,    AsmRef,    obj->refs, asmResolveRef(x.ref,x.i,c));
240 #if 0
241     if (obj->num_unresolved == 0) {
242         /* todo: free the queues */
243         /* we don't print until all ptrs are resolved */
244         IF_DEBUG(codegen,
245                  if (obj->num_unresolved > 0) 
246                     fprintf(stderr, "{{%d unresolved}} ", obj->num_unresolved);
247                 )
248         IF_DEBUG(codegen,printObj(obj->closure));
249     }
250     //printf( "unresolved %d\n", obj->num_unresolved);
251     //printObj(obj->closure);
252 #endif
253 }
254
255 int asmObjectHasClosure ( AsmObject obj )
256 {
257     return (obj->num_unresolved == 0 && obj->closure);
258 }
259
260 AsmClosure asmClosureOfObject ( AsmObject obj )
261 {
262     ASSERT(asmObjectHasClosure(obj));
263     return obj->closure;
264 }
265
266 void asmMarkObject ( AsmObject obj )
267 {
268     ASSERT(obj->num_unresolved == 0 && obj->closure);
269     obj->closure = MarkRoot(obj->closure);
270 }
271
272 /* --------------------------------------------------------------------------
273  * Heap allocation
274  * ------------------------------------------------------------------------*/
275
276 static StgClosure* asmAlloc( nat size )
277 {
278     StgClosure* o = stgCast(StgClosure*,allocate(size));
279     ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
280     /* printf("Allocated %p .. %p\n", o, o+size-1); */
281     return o;
282 }
283
284 static void grabHpUpd( AsmBCO bco, nat size )
285 {
286     /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
287     ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
288     bco->hp += size;
289 }
290
291 static void grabHpNonUpd( AsmBCO bco, nat size )
292 {
293     /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
294     ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
295     bco->hp += size;
296 }
297
298 static void resetHp( AsmBCO bco, nat hp )
299 {
300     bco->max_hp = stg_max(bco->hp,bco->max_hp);
301     bco->hp     = hp;
302 }
303
304 static void resetSp( AsmBCO bco, AsmSp sp )
305 {
306     bco->max_sp = stg_max(bco->sp,bco->max_sp);
307     bco->sp     = sp;
308 }
309
310 /* --------------------------------------------------------------------------
311  * 
312  * ------------------------------------------------------------------------*/
313
314 AsmObject asmMkObject( AsmClosure c )
315 {
316     AsmObject obj = malloc(sizeof(struct AsmObject_));
317     if (obj == NULL) {
318         barf("Can't allocate AsmObject");
319     }
320     asmBeginObject(obj);
321     asmEndObject(obj,c);
322     return obj;
323 }
324
325 AsmCon asmBeginCon( AsmInfo info )
326 {
327     AsmCon con = malloc(sizeof(struct AsmCon_));
328     if (con == NULL) {
329         barf("Can't allocate AsmCon");
330     }
331     asmBeginObject(&con->object);
332     con->info = info;
333     return con;
334 }
335
336 void asmEndCon( AsmCon con )
337 {
338     nat p  = con->object.ptrs.len;
339     nat np = stg_max(0,MIN_NONUPD_SIZE-p);
340
341     StgClosure* c = asmAlloc(CONSTR_sizeW(p,np));
342     StgClosure* o = stgCast(StgClosure*,c);
343     SET_HDR(o,con->info,??);
344     mapQueue(Ptrs,    AsmObject, con->object.ptrs, payloadCPtr(o,i) = NULL);
345     { nat i; for( i=0; i<np; ++i ) { payloadWord(o,p+i) = 0xdeadbeef; } }
346     asmEndObject(&con->object,c);
347 }
348
349 AsmCAF asmBeginCAF( void )
350 {
351     AsmCAF caf = malloc(sizeof(struct AsmCAF_));
352     if (caf == NULL) {
353         barf("Can't allocate AsmCAF");
354     }
355     asmBeginObject(&caf->object);
356     return caf;
357 }
358
359 void asmEndCAF( AsmCAF caf, AsmBCO body )
360 {
361     StgClosure* c = asmAlloc(CAF_sizeW());
362     StgCAF*     o = stgCast(StgCAF*,c);
363     SET_HDR(o,&CAF_UNENTERED_info,??);
364     o->body  = NULL;
365     o->value = stgCast(StgClosure*,0xdeadbeef);
366     o->link  = stgCast(StgCAF*,0xdeadbeef);
367     asmAddPtr(&caf->object,&body->object);
368     asmEndObject(&caf->object,c);
369 }
370
371 AsmBCO asmBeginBCO( int /*StgExpr*/ e )
372 {
373     AsmBCO bco = malloc(sizeof(struct AsmBCO_));
374     if (bco == NULL) {
375         barf("Can't allocate AsmBCO");
376     }
377     asmBeginObject(&bco->object);
378     initInstrs(&bco->is);
379     initNonPtrs(&bco->nps);
380
381     bco->stgexpr = e;
382     bco->max_sp = bco->sp = 0;
383     bco->max_hp = bco->hp = 0;
384     return bco;
385 }
386
387 void asmEndBCO( AsmBCO bco )
388 {
389     nat p  = bco->object.ptrs.len;
390     nat np = bco->nps.len;
391 #if 0
392     nat is = bco->is.len + 4;  /* 4 for stack and heap checks */
393 #else
394     nat is = bco->is.len + 2;  /* 4 for stack check */
395 #endif
396
397     StgClosure* c = asmAlloc(BCO_sizeW(p,np,is));
398     StgBCO*     o = stgCast(StgBCO*,c);
399     SET_HDR(o,&BCO_info,??);
400     o->n_ptrs   = p;
401     o->n_words  = np;
402     o->n_instrs = is;
403     o->stgexpr  = bco->stgexpr;
404     mapQueue(Ptrs,    AsmObject, bco->object.ptrs, bcoConstCPtr(o,i) = NULL);
405     mapQueue(NonPtrs, StgWord,   bco->nps,  bcoConstWord(o,i) = x);
406     {
407         nat j = 0;
408         bco->max_sp = stg_max(bco->sp,bco->max_sp);
409         bco->max_hp = stg_max(bco->hp,bco->max_hp);
410         bcoInstr(o,j++) = i_STK_CHECK;
411         bcoInstr(o,j++) = bco->max_sp;
412 #if 0
413         bcoInstr(o,j++) = i_HP_CHECK;
414         bcoInstr(o,j++) = bco->max_hp;
415 #endif
416         mapQueue(Instrs,  StgNat8,   bco->is,   bcoInstr(o,j++) = x);
417         ASSERT(j == is);
418     }
419     asmEndObject(&bco->object,c);
420 }
421
422 /* --------------------------------------------------------------------------
423  * 
424  * ------------------------------------------------------------------------*/
425
426 static void asmInstr( AsmBCO bco, StgWord i )
427 {
428     ASSERT(i < 256); /* must be a byte */
429     insertInstrs(&(bco->is),i);
430 }
431
432 static void asmPtr( AsmBCO bco, AsmObject x )
433 {
434     insertPtrs( &bco->object.ptrs, x );
435 }
436
437 static void asmWord( AsmBCO bco, StgWord i )
438 {
439     insertNonPtrs( &bco->nps, i );
440 }
441
442 #define asmWords(bco,ty,x)                               \
443     {                                                    \
444         union { ty a; AsmWord b[sizeofW(ty)]; } p;       \
445         nat i;                                           \
446         if (sizeof(ty) < sizeof(AsmWord)) p.b[0]=0;      \
447         p.a = x;                                         \
448         for( i = 0; i < sizeofW(ty); i++ ) {             \
449             asmWord(bco,p.b[i]);                         \
450         }                                                \
451     }
452
453 static StgWord repSizeW( AsmRep rep )
454 {
455     switch (rep) {
456     case CHAR_REP:    return sizeofW(StgWord) + sizeofW(StgChar);
457
458     case BOOL_REP:
459     case INT_REP:     return sizeofW(StgWord) + sizeofW(StgInt);
460 #ifdef PROVIDE_INT64
461     case INT64_REP:   return sizeofW(StgWord) + sizeofW(StgInt64);
462 #endif
463 #ifdef PROVIDE_WORD
464     case WORD_REP:    return sizeofW(StgWord) + sizeofW(StgWord);
465 #endif
466 #ifdef PROVIDE_ADDR
467     case ADDR_REP:    return sizeofW(StgWord) + sizeofW(StgAddr);
468 #endif
469     case FLOAT_REP:   return sizeofW(StgWord) + sizeofW(StgFloat);
470     case DOUBLE_REP:  return sizeofW(StgWord) + sizeofW(StgDouble);
471 #ifdef PROVIDE_STABLE
472     case STABLE_REP:  return sizeofW(StgWord) + sizeofW(StgWord);
473 #endif
474
475 #ifdef PROVIDE_INTEGER
476     case INTEGER_REP: 
477 #endif
478 #ifdef PROVIDE_WEAK
479     case WEAK_REP: 
480 #endif
481 #ifdef PROVIDE_FOREIGN
482     case FOREIGN_REP: 
483 #endif
484     case ALPHA_REP:    /* a                        */ 
485     case BETA_REP:     /* b                        */ 
486     case GAMMA_REP:    /* c                        */ 
487     case HANDLER_REP:  /* IOError -> IO a          */ 
488     case ERROR_REP:    /* IOError                  */ 
489 #ifdef PROVIDE_ARRAY            
490     case ARR_REP    :  /* PrimArray              a */ 
491     case BARR_REP   :  /* PrimByteArray          a */ 
492     case REF_REP    :  /* Ref                  s a */ 
493     case MUTARR_REP :  /* PrimMutableArray     s a */ 
494     case MUTBARR_REP:  /* PrimMutableByteArray s a */ 
495 #endif
496 #ifdef PROVIDE_CONCURRENT
497     case THREADID_REP: /* ThreadId                 */ 
498     case MVAR_REP:     /* MVar a                   */ 
499 #endif
500     case PTR_REP:     return sizeofW(StgPtr);
501
502     case VOID_REP:    return sizeofW(StgWord);
503     default:          barf("repSizeW %d",rep);
504     }
505 }
506
507 /* --------------------------------------------------------------------------
508  * Arg checks.
509  * ------------------------------------------------------------------------*/
510
511 AsmSp  asmBeginArgCheck ( AsmBCO bco )
512 {
513     ASSERT(bco->sp == 0);
514     return bco->sp;
515 }
516
517 void   asmEndArgCheck   ( AsmBCO bco, AsmSp last_arg )
518 {
519     nat args = bco->sp - last_arg;
520     if (args != 0) { /* optimisation */
521         asmInstr(bco,i_ARG_CHECK);
522         asmInstr(bco,args);
523         grabHpNonUpd(bco,PAP_sizeW(args-1));
524         resetHp(bco,0);
525     }
526 }
527
528 /* --------------------------------------------------------------------------
529  * Creating and using "variables"
530  * ------------------------------------------------------------------------*/
531
532 AsmVar asmBind          ( AsmBCO bco, AsmRep rep )
533 {
534     bco->sp += repSizeW(rep);
535     return bco->sp;
536 }
537
538 void   asmVar           ( AsmBCO bco, AsmVar v, AsmRep rep )
539 {
540     switch (rep) {
541     case BOOL_REP:
542     case INT_REP:
543             asmInstr(bco,i_VAR_INT);
544             break;
545 #ifdef PROVIDE_INT64
546     case INT64_REP:
547             asmInstr(bco,i_VAR_INT64);
548             break;
549 #endif
550 #ifdef PROVIDE_WORD
551     case WORD_REP:
552             asmInstr(bco,i_VAR_WORD);
553             break;
554 #endif
555 #ifdef PROVIDE_ADDR
556     case ADDR_REP:
557             asmInstr(bco,i_VAR_ADDR);
558             break;
559 #endif
560     case CHAR_REP:
561             asmInstr(bco,i_VAR_CHAR);
562             break;
563     case FLOAT_REP:
564             asmInstr(bco,i_VAR_FLOAT);
565             break;
566     case DOUBLE_REP:
567             asmInstr(bco,i_VAR_DOUBLE);
568             break;
569 #ifdef PROVIDE_STABLE
570     case STABLE_REP:
571             asmInstr(bco,i_VAR_STABLE);
572             break;
573 #endif
574
575 #ifdef PROVIDE_INTEGER
576     case INTEGER_REP:
577 #endif
578 #ifdef PROVIDE_WEAK
579     case WEAK_REP: 
580 #endif
581 #ifdef PROVIDE_FOREIGN
582     case FOREIGN_REP:
583 #endif
584     case ALPHA_REP:    /* a                        */ 
585     case BETA_REP:     /* b                        */
586     case GAMMA_REP:    /* c                        */ 
587     case HANDLER_REP:  /* IOError -> IO a          */
588     case ERROR_REP:    /* IOError                  */
589 #ifdef PROVIDE_ARRAY            
590     case ARR_REP    :  /* PrimArray              a */
591     case BARR_REP   :  /* PrimByteArray          a */
592     case REF_REP    :  /* Ref                  s a */
593     case MUTARR_REP :  /* PrimMutableArray     s a */
594     case MUTBARR_REP:  /* PrimMutableByteArray s a */
595 #endif
596 #ifdef PROVIDE_CONCURRENT
597     case THREADID_REP: /* ThreadId                 */
598     case MVAR_REP:     /* MVar a                   */
599 #endif
600     case PTR_REP:
601             asmInstr(bco,i_VAR);
602             break;
603
604     case VOID_REP:
605             asmInstr(bco,i_VOID);
606             bco->sp += repSizeW(rep);
607             return; /* NB we don't break! */
608     default:
609             barf("asmVar %d",rep);
610     }
611     asmInstr(bco,bco->sp - v);
612     bco->sp += repSizeW(rep);
613 }
614
615 /* --------------------------------------------------------------------------
616  * Tail calls
617  * ------------------------------------------------------------------------*/
618
619 AsmSp asmBeginEnter( AsmBCO bco )
620 {
621     return bco->sp;
622 }
623
624 void asmEndEnter( AsmBCO bco, AsmSp sp1, AsmSp sp2 )
625 {
626     int x = bco->sp - sp1;
627     int y = sp1 - sp2;
628     ASSERT(x >= 0 && y >= 0);
629     if (y != 0) {
630         asmInstr(bco,i_SLIDE);
631         asmInstr(bco,x);
632         asmInstr(bco,y);
633         bco->sp -= sp1 - sp2;
634     }
635     asmInstr(bco,i_ENTER);
636 }
637
638 /* --------------------------------------------------------------------------
639  * Build boxed Ints, Floats, etc
640  * ------------------------------------------------------------------------*/
641
642 AsmVar asmBox( AsmBCO bco, AsmRep rep )
643 {
644     switch (rep) {
645     case CHAR_REP:
646             asmInstr(bco,i_PACK_CHAR);
647             grabHpNonUpd(bco,Czh_sizeW);
648             break;
649     case INT_REP:
650             asmInstr(bco,i_PACK_INT);
651             grabHpNonUpd(bco,Izh_sizeW);
652             break;
653 #ifdef PROVIDE_INT64
654     case INT64_REP:
655             asmInstr(bco,i_PACK_INT64);
656             grabHpNonUpd(bco,I64zh_sizeW);
657             break;
658 #endif
659 #ifdef PROVIDE_WORD
660     case WORD_REP:
661             asmInstr(bco,i_PACK_WORD);
662             grabHpNonUpd(bco,Wzh_sizeW);
663             break;
664 #endif
665 #ifdef PROVIDE_ADDR
666     case ADDR_REP:
667             asmInstr(bco,i_PACK_ADDR);
668             grabHpNonUpd(bco,Azh_sizeW);
669             break;
670 #endif
671     case FLOAT_REP:
672             asmInstr(bco,i_PACK_FLOAT);
673             grabHpNonUpd(bco,Fzh_sizeW);
674             break;
675     case DOUBLE_REP:
676             asmInstr(bco,i_PACK_DOUBLE);
677             grabHpNonUpd(bco,Dzh_sizeW);
678             break;
679 #ifdef PROVIDE_STABLE
680     case STABLE_REP:
681             asmInstr(bco,i_PACK_STABLE);
682             grabHpNonUpd(bco,Stablezh_sizeW);
683             break;
684 #endif
685
686     default:
687             barf("asmBox %d",rep);
688     }
689     /* NB: these operations DO pop their arg       */
690     bco->sp -= repSizeW(rep);   /* pop unboxed arg */
691     bco->sp += sizeofW(StgPtr); /* push box        */
692     return bco->sp;
693 }
694
695 /* --------------------------------------------------------------------------
696  * Unbox Ints, Floats, etc
697  * ------------------------------------------------------------------------*/
698
699 AsmVar asmUnbox( AsmBCO bco, AsmRep rep )
700 {
701     switch (rep) {
702     case INT_REP:
703             asmInstr(bco,i_UNPACK_INT);
704             break;
705 #ifdef PROVIDE_INT64
706     case INT64_REP:
707             asmInstr(bco,i_UNPACK_INT64);
708             break;
709 #endif
710 #ifdef PROVIDE_WORD
711     case WORD_REP:
712             asmInstr(bco,i_UNPACK_WORD);
713             break;
714 #endif
715 #ifdef PROVIDE_ADDR
716     case ADDR_REP:
717             asmInstr(bco,i_UNPACK_ADDR);
718             break;
719 #endif
720     case CHAR_REP:
721             asmInstr(bco,i_UNPACK_CHAR);
722             break;
723     case FLOAT_REP:
724             asmInstr(bco,i_UNPACK_FLOAT);
725             break;
726     case DOUBLE_REP:
727             asmInstr(bco,i_UNPACK_DOUBLE);
728             break;
729 #ifdef PROVIDE_STABLE
730     case STABLE_REP:
731             asmInstr(bco,i_UNPACK_STABLE);
732             break;
733 #endif
734     default:
735             barf("asmUnbox %d",rep);
736     }
737     /* NB: these operations DO NOT pop their arg  */
738     bco->sp += repSizeW(rep); /* push unboxed arg */
739     return bco->sp;
740 }
741
742 /* --------------------------------------------------------------------------
743  * Return unboxed Ints, Floats, etc
744  * ------------------------------------------------------------------------*/
745
746 void asmReturnUnboxed( AsmBCO bco, AsmRep rep )
747 {
748     switch (rep) {
749     case CHAR_REP:
750             asmInstr(bco,i_RETURN_CHAR);
751             break;
752     case INT_REP:
753             asmInstr(bco,i_RETURN_INT);
754             break;
755 #ifdef PROVIDE_INT64
756     case INT64_REP:
757             asmInstr(bco,i_RETURN_INT64);
758             break;
759 #endif
760 #ifdef PROVIDE_WORD
761     case WORD_REP:
762             asmInstr(bco,i_RETURN_WORD);
763             break;
764 #endif
765 #ifdef PROVIDE_ADDR
766     case ADDR_REP:
767             asmInstr(bco,i_RETURN_ADDR);
768             break;
769 #endif
770     case FLOAT_REP:
771             asmInstr(bco,i_RETURN_FLOAT);
772             break;
773     case DOUBLE_REP:
774             asmInstr(bco,i_RETURN_DOUBLE);
775             break;
776 #ifdef PROVIDE_STABLE
777     case STABLE_REP:
778             asmInstr(bco,i_RETURN_STABLE);
779             break;
780 #endif
781 #ifdef PROVIDE_INTEGER
782     case INTEGER_REP: 
783 #endif
784 #ifdef PROVIDE_WEAK
785     case WEAK_REP: 
786 #endif
787 #ifdef PROVIDE_FOREIGN
788     case FOREIGN_REP: 
789 #endif
790 #ifdef PROVIDE_ARRAY
791     case ARR_REP    :  /* PrimArray              a */
792     case BARR_REP   :  /* PrimByteArray          a */
793     case REF_REP    :  /* Ref                  s a */
794     case MUTARR_REP :  /* PrimMutableArray     s a */
795     case MUTBARR_REP:  /* PrimMutableByteArray s a */
796 #endif
797 #ifdef PROVIDE_CONCURRENT
798     case THREADID_REP: /* ThreadId                 */ 
799     case MVAR_REP:     /* MVar a                   */ 
800 #endif
801             asmInstr(bco,i_RETURN_GENERIC);
802             break;
803     default:
804             barf("asmReturnUnboxed %d",rep);
805     }
806 }
807
808 /* --------------------------------------------------------------------------
809  * Push unboxed Ints, Floats, etc
810  * ------------------------------------------------------------------------*/
811
812 void asmConstInt( AsmBCO bco, AsmInt x )
813 {
814     asmInstr(bco,i_CONST_INT);
815     asmInstr(bco,bco->nps.len);
816     asmWords(bco,AsmInt,x);
817     bco->sp += repSizeW(INT_REP);
818 }
819
820 #ifdef PROVIDE_INT64
821 void asmConstInt64( AsmBCO bco, AsmInt64 x )
822 {
823     asmInstr(bco,i_CONST_INT64);
824     asmInstr(bco,bco->nps.len);
825     asmWords(bco,AsmInt64,x);
826     bco->sp += repSizeW(INT64_REP);
827 }
828 #endif
829
830 #ifdef PROVIDE_INTEGER
831 void asmConstInteger( AsmBCO bco, AsmString x )
832 {
833     asmInstr(bco,i_CONST_INTEGER);
834     asmInstr(bco,bco->nps.len);
835     asmWords(bco,AsmString,x);
836     bco->sp += repSizeW(INTEGER_REP);
837 }
838 #endif
839
840 #ifdef PROVIDE_ADDR
841 void asmConstAddr( AsmBCO bco, AsmAddr x )
842 {
843     asmInstr(bco,i_CONST_ADDR);
844     asmInstr(bco,bco->nps.len);
845     asmWords(bco,AsmAddr,x);
846     bco->sp += repSizeW(ADDR_REP);
847 }
848 #endif
849
850 #ifdef PROVIDE_WORD
851 void asmConstWord( AsmBCO bco, AsmWord x )
852 {
853     asmInstr(bco,i_CONST_INT);
854     asmInstr(bco,bco->nps.len);
855     asmWords(bco,AsmWord,x);
856     bco->sp += repSizeW(WORD_REP);
857 }
858 #endif
859
860 void asmConstChar( AsmBCO bco, AsmChar x )
861 {
862     asmInstr(bco,i_CONST_CHAR);
863     asmInstr(bco,bco->nps.len);
864     asmWords(bco,AsmChar,x);
865     bco->sp += repSizeW(CHAR_REP);
866 }
867
868 void asmConstFloat( AsmBCO bco, AsmFloat x )
869 {
870     asmInstr(bco,i_CONST_FLOAT);
871     asmInstr(bco,bco->nps.len);
872     asmWords(bco,AsmFloat,x);
873     bco->sp += repSizeW(FLOAT_REP);
874 }
875
876 void asmConstDouble( AsmBCO bco, AsmDouble x )
877 {
878     asmInstr(bco,i_CONST_DOUBLE);
879     asmInstr(bco,bco->nps.len);
880     asmWords(bco,AsmDouble,x);
881     bco->sp += repSizeW(DOUBLE_REP);
882 }
883
884 /* --------------------------------------------------------------------------
885  *
886  * ------------------------------------------------------------------------*/
887
888 /* a mildly bogus pair of functions... */
889 AsmSp asmBeginCase( AsmBCO bco )
890 {
891     return bco->sp;
892 }
893
894 void asmEndCase( AsmBCO bco )
895 {
896 }
897
898 AsmSp asmContinuation( AsmBCO bco, AsmBCO ret_addr )
899 {
900     asmInstr(bco,i_RETADDR);
901     asmInstr(bco,bco->object.ptrs.len);
902     asmPtr(bco,&(ret_addr->object));
903     bco->sp += 2 * sizeofW(StgPtr);
904     return bco->sp;
905 }
906
907 AsmBCO asmBeginContinuation ( AsmSp sp, int /*List*/ alts )
908 {
909     AsmBCO bco = asmBeginBCO(alts);
910     bco->sp = sp;
911     return bco;
912 }
913
914 void asmEndContinuation ( AsmBCO bco )
915 {
916     asmEndBCO(bco);
917 }
918
919
920 /* --------------------------------------------------------------------------
921  * Branches
922  * ------------------------------------------------------------------------*/
923
924 AsmSp asmBeginAlt( AsmBCO bco )
925 {
926     return bco->sp;
927 }
928
929 void asmEndAlt( AsmBCO bco, AsmSp  sp )
930 {
931 #if 0
932     /* This warning is now redundant since we no longer use the hp/max_hp
933      * information calculated by the assembler 
934      */
935 #warning ToDo: adjust hp/max_hp in asmEndAlt
936 #endif
937     resetSp(bco,sp);
938 }
939
940 AsmPc asmTest( AsmBCO bco, AsmWord tag )
941 {
942     asmInstr(bco,i_TEST);
943     asmInstr(bco,tag);
944     asmInstr(bco,0);
945     return bco->is.len;
946 }
947
948 AsmPc asmTestInt( AsmBCO bco, AsmVar v, AsmInt x )
949 {
950     asmVar(bco,v,INT_REP);
951     asmConstInt(bco,x);
952     asmInstr(bco,i_TEST_INT);
953     asmInstr(bco,0);
954     bco->sp -= 2*repSizeW(INT_REP);
955     return bco->is.len;
956 }
957
958 void asmFixBranch( AsmBCO bco, AsmPc from )
959 {
960     int distance = bco->is.len - from;
961     ASSERT(distance >= 0);
962     setInstrs(&(bco->is),from-1,distance);
963 }
964
965 void asmPanic( AsmBCO bco )
966 {
967     asmInstr(bco,i_PANIC); /* "irrefutable" pattern failed - oops! */
968 }
969
970 /* --------------------------------------------------------------------------
971  * Primops
972  * ------------------------------------------------------------------------*/
973
974 AsmSp asmBeginPrim( AsmBCO bco )
975 {
976     return bco->sp;
977 }
978
979 void   asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
980 {
981     asmInstr(bco,prim->prefix);
982     asmInstr(bco,prim->opcode);
983     bco->sp = base;
984 }
985
986 /* Hugs used to let you add arbitrary primops with arbitrary types
987  * just by editing Prelude.hs or any other file you wanted.
988  * We deliberately avoided that approach because we wanted more
989  * control over which primops are provided.
990  */
991 const AsmPrim asmPrimOps[] = {
992
993     /* Char# operations */
994       { "primGtChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_gtChar }
995     , { "primGeChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_geChar }
996     , { "primEqChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_eqChar }
997     , { "primNeChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_neChar }
998     , { "primLtChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_ltChar }
999     , { "primLeChar",                "CC", "B",  MONAD_Id, i_PRIMOP1, i_leChar }
1000     , { "primCharToInt",             "C",  "I",  MONAD_Id, i_PRIMOP1, i_charToInt }
1001     , { "primIntToChar",             "I",  "C",  MONAD_Id, i_PRIMOP1, i_intToChar }
1002
1003     /* Int# operations */
1004     , { "primGtInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_gtInt }
1005     , { "primGeInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_geInt }
1006     , { "primEqInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_eqInt }
1007     , { "primNeInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_neInt }
1008     , { "primLtInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_ltInt }
1009     , { "primLeInt",                 "II", "B",  MONAD_Id, i_PRIMOP1, i_leInt }
1010     , { "primMinInt",                "",   "I",  MONAD_Id, i_PRIMOP1, i_minInt }
1011     , { "primMaxInt",                "",   "I",  MONAD_Id, i_PRIMOP1, i_maxInt }
1012     , { "primPlusInt",               "II", "I",  MONAD_Id, i_PRIMOP1, i_plusInt }
1013     , { "primMinusInt",              "II", "I",  MONAD_Id, i_PRIMOP1, i_minusInt }
1014     , { "primTimesInt",              "II", "I",  MONAD_Id, i_PRIMOP1, i_timesInt }
1015     , { "primQuotInt",               "II", "I",  MONAD_Id, i_PRIMOP1, i_quotInt }
1016     , { "primRemInt",                "II", "I",  MONAD_Id, i_PRIMOP1, i_remInt }
1017     , { "primQuotRemInt",            "II", "II", MONAD_Id, i_PRIMOP1, i_quotRemInt }
1018     , { "primNegateInt",             "I",  "I",  MONAD_Id, i_PRIMOP1, i_negateInt }
1019
1020     , { "primAndInt",                "II", "I",  MONAD_Id, i_PRIMOP1, i_andInt }
1021     , { "primOrInt",                 "II", "I",  MONAD_Id, i_PRIMOP1, i_orInt }
1022     , { "primXorInt",                "II", "I",  MONAD_Id, i_PRIMOP1, i_xorInt }
1023     , { "primNotInt",                "I",  "I",  MONAD_Id, i_PRIMOP1, i_notInt }
1024     , { "primShiftLInt",             "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftLInt }
1025     , { "primShiftRAInt",            "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftRAInt }
1026     , { "primShiftRLInt",            "II", "I",  MONAD_Id, i_PRIMOP1, i_shiftRLInt }
1027
1028 #ifdef PROVIDE_INT64
1029     /* Int64# operations */
1030     , { "primGtInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_gtInt64 }
1031     , { "primGeInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_geInt64 }
1032     , { "primEqInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_eqInt64 }
1033     , { "primNeInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_neInt64 }
1034     , { "primLtInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_ltInt64 }
1035     , { "primLeInt64",               "zz", "B",  MONAD_Id, i_PRIMOP1, i_leInt64 }
1036     , { "primMinInt64",              "",   "z",  MONAD_Id, i_PRIMOP1, i_minInt64 }
1037     , { "primMaxInt64",              "",   "z",  MONAD_Id, i_PRIMOP1, i_maxInt64 }
1038     , { "primPlusInt64",             "zz", "z",  MONAD_Id, i_PRIMOP1, i_plusInt64 }
1039     , { "primMinusInt64",            "zz", "z",  MONAD_Id, i_PRIMOP1, i_minusInt64 }
1040     , { "primTimesInt64",            "zz", "z",  MONAD_Id, i_PRIMOP1, i_timesInt64 }
1041     , { "primQuotInt64",             "zz", "z",  MONAD_Id, i_PRIMOP1, i_quotInt64 }
1042     , { "primRemInt64",              "zz", "z",  MONAD_Id, i_PRIMOP1, i_remInt64 }
1043     , { "primQuotRemInt64",          "zz", "zz", MONAD_Id, i_PRIMOP1, i_quotRemInt64 }
1044     , { "primNegateInt64",           "z",  "z",  MONAD_Id, i_PRIMOP1, i_negateInt64 }
1045
1046     , { "primAndInt64",               "zz", "z",  MONAD_Id, i_PRIMOP1, i_andInt64 }
1047     , { "primOrInt64",                "zz", "z",  MONAD_Id, i_PRIMOP1, i_orInt64 }
1048     , { "primXorInt64",               "zz", "z",  MONAD_Id, i_PRIMOP1, i_xorInt64 }
1049     , { "primNotInt64",               "z",  "z",  MONAD_Id, i_PRIMOP1, i_notInt64 }
1050     , { "primShiftLInt64",            "zW", "z",  MONAD_Id, i_PRIMOP1, i_shiftLInt64 }
1051     , { "primShiftRAInt64",           "zW", "z",  MONAD_Id, i_PRIMOP1, i_shiftRAInt64 }
1052     , { "primShiftRLInt64",           "zW", "z",  MONAD_Id, i_PRIMOP1, i_shiftRLInt64 }
1053
1054     , { "primInt64ToInt",            "z",  "I",  MONAD_Id, i_PRIMOP1, i_int64ToInt }
1055     , { "primIntToInt64",            "I",  "z",  MONAD_Id, i_PRIMOP1, i_intToInt64 }
1056 #ifdef PROVIDE_WORD
1057     , { "primInt64ToWord",           "z",  "W",  MONAD_Id, i_PRIMOP1, i_int64ToWord }
1058     , { "primWordToInt64",           "W",  "z",  MONAD_Id, i_PRIMOP1, i_wordToInt64 }
1059 #endif
1060     , { "primInt64ToFloat",          "z",  "F",  MONAD_Id, i_PRIMOP1, i_int64ToFloat }
1061     , { "primFloatToInt64",          "F",  "z",  MONAD_Id, i_PRIMOP1, i_floatToInt64 }
1062     , { "primInt64ToDouble",         "z",  "D",  MONAD_Id, i_PRIMOP1, i_int64ToDouble }
1063     , { "primDoubleToInt64",         "D",  "z",  MONAD_Id, i_PRIMOP1, i_doubleToInt64 }
1064 #endif
1065
1066 #ifdef PROVIDE_WORD
1067     /* Word# operations */
1068     , { "primGtWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_gtWord }
1069     , { "primGeWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_geWord }
1070     , { "primEqWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_eqWord }
1071     , { "primNeWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_neWord }
1072     , { "primLtWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_ltWord }
1073     , { "primLeWord",                "WW", "B",  MONAD_Id, i_PRIMOP1, i_leWord }
1074     , { "primMinWord",               "",   "W",  MONAD_Id, i_PRIMOP1, i_minWord }
1075     , { "primMaxWord",               "",   "W",  MONAD_Id, i_PRIMOP1, i_maxWord }
1076     , { "primPlusWord",              "WW", "W",  MONAD_Id, i_PRIMOP1, i_plusWord }
1077     , { "primMinusWord",             "WW", "W",  MONAD_Id, i_PRIMOP1, i_minusWord }
1078     , { "primTimesWord",             "WW", "W",  MONAD_Id, i_PRIMOP1, i_timesWord }
1079     , { "primQuotWord",              "WW", "W",  MONAD_Id, i_PRIMOP1, i_quotWord }
1080     , { "primRemWord",               "WW", "W",  MONAD_Id, i_PRIMOP1, i_remWord }
1081     , { "primQuotRemWord",           "WW", "WW", MONAD_Id, i_PRIMOP1, i_quotRemWord }
1082     , { "primNegateWord",            "W",  "W",  MONAD_Id, i_PRIMOP1, i_negateWord }
1083
1084     , { "primAndWord",               "WW", "W",  MONAD_Id, i_PRIMOP1, i_andWord }
1085     , { "primOrWord",                "WW", "W",  MONAD_Id, i_PRIMOP1, i_orWord }
1086     , { "primXorWord",               "WW", "W",  MONAD_Id, i_PRIMOP1, i_xorWord }
1087     , { "primNotWord",               "W",  "W",  MONAD_Id, i_PRIMOP1, i_notWord }
1088     , { "primShiftLWord",            "WW", "W",  MONAD_Id, i_PRIMOP1, i_shiftLWord }
1089     , { "primShiftRAWord",           "WW", "W",  MONAD_Id, i_PRIMOP1, i_shiftRAWord }
1090     , { "primShiftRLWord",           "WW", "W",  MONAD_Id, i_PRIMOP1, i_shiftRLWord }
1091
1092     , { "primIntToWord",             "I",  "W",  MONAD_Id, i_PRIMOP1, i_intToWord }
1093     , { "primWordToInt",             "W",  "I",  MONAD_Id, i_PRIMOP1, i_wordToInt }
1094 #endif
1095
1096 #ifdef PROVIDE_ADDR
1097     /* Addr# operations */
1098     , { "primGtAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_gtAddr }
1099     , { "primGeAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_geAddr }
1100     , { "primEqAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_eqAddr }
1101     , { "primNeAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_neAddr }
1102     , { "primLtAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_ltAddr }
1103     , { "primLeAddr",                "AA", "B",  MONAD_Id, i_PRIMOP1, i_leAddr }
1104     , { "primIntToAddr",             "I",  "A",  MONAD_Id, i_PRIMOP1, i_intToAddr }
1105     , { "primAddrToInt",             "A",  "I",  MONAD_Id, i_PRIMOP1, i_addrToInt }
1106
1107     , { "primIndexCharOffAddr",      "AI", "C",  MONAD_Id, i_PRIMOP1, i_indexCharOffAddr }
1108     , { "primIndexIntOffAddr",       "AI", "I",  MONAD_Id, i_PRIMOP1, i_indexIntOffAddr }
1109 #ifdef PROVIDE_INT64
1110     , { "primIndexInt64OffAddr",     "AI", "z",  MONAD_Id, i_PRIMOP1, i_indexInt64OffAddr }
1111 #endif
1112 #ifdef PROVIDE_WORD
1113     , { "primIndexWordOffAddr",      "AI", "W",  MONAD_Id, i_PRIMOP1, i_indexWordOffAddr }
1114 #endif
1115     , { "primIndexAddrOffAddr",      "AI", "A",  MONAD_Id, i_PRIMOP1, i_indexAddrOffAddr }
1116     , { "primIndexFloatOffAddr",     "AI", "F",  MONAD_Id, i_PRIMOP1, i_indexFloatOffAddr }
1117     , { "primIndexDoubleOffAddr",    "AI", "D",  MONAD_Id, i_PRIMOP1, i_indexDoubleOffAddr }
1118 #ifdef PROVIDE_STABLE
1119     , { "primIndexStableOffAddr",    "AI", "s",  MONAD_Id, i_PRIMOP1, i_indexStableOffAddr }
1120 #endif
1121
1122     /* These ops really ought to be in the IO monad */
1123     , { "primReadCharOffAddr",       "AI", "C",  MONAD_ST, i_PRIMOP1, i_readCharOffAddr }
1124     , { "primReadIntOffAddr",        "AI", "I",  MONAD_ST, i_PRIMOP1, i_readIntOffAddr }
1125 #ifdef PROVIDE_INT64                 
1126     , { "primReadInt64OffAddr",      "AI", "z",  MONAD_ST, i_PRIMOP1, i_readInt64OffAddr }
1127 #endif                               
1128 #ifdef PROVIDE_WORD
1129     , { "primReadWordOffAddr",       "AI", "W",  MONAD_ST, i_PRIMOP1, i_readWordOffAddr }
1130 #endif
1131     , { "primReadAddrOffAddr",       "AI", "A",  MONAD_ST, i_PRIMOP1, i_readAddrOffAddr }
1132     , { "primReadFloatOffAddr",      "AI", "F",  MONAD_ST, i_PRIMOP1, i_readFloatOffAddr }
1133     , { "primReadDoubleOffAddr",     "AI", "D",  MONAD_ST, i_PRIMOP1, i_readDoubleOffAddr }
1134 #ifdef PROVIDE_STABLE                
1135     , { "primReadStableOffAddr",     "AI", "s",  MONAD_ST, i_PRIMOP1, i_readStableOffAddr }
1136 #endif
1137
1138     /* These ops really ought to be in the IO monad */
1139     , { "primWriteCharOffAddr",      "AIC", "",  MONAD_ST, i_PRIMOP1, i_writeCharOffAddr }
1140     , { "primWriteIntOffAddr",       "AII", "",  MONAD_ST, i_PRIMOP1, i_writeIntOffAddr }
1141 #ifdef PROVIDE_INT64
1142     , { "primWriteInt64OffAddr",     "AIz", "",  MONAD_ST, i_PRIMOP1, i_writeInt64OffAddr }
1143 #endif
1144 #ifdef PROVIDE_WORD
1145     , { "primWriteWordOffAddr",      "AIW", "",  MONAD_ST, i_PRIMOP1, i_writeWordOffAddr }
1146 #endif
1147     , { "primWriteAddrOffAddr",      "AIA", "",  MONAD_ST, i_PRIMOP1, i_writeAddrOffAddr }
1148     , { "primWriteFloatOffAddr",     "AIF", "",  MONAD_ST, i_PRIMOP1, i_writeFloatOffAddr }
1149     , { "primWriteDoubleOffAddr",    "AID", "",  MONAD_ST, i_PRIMOP1, i_writeDoubleOffAddr }
1150 #ifdef PROVIDE_STABLE
1151     , { "primWriteStableOffAddr",    "AIs", "",  MONAD_ST, i_PRIMOP1, i_writeStableOffAddr }
1152 #endif
1153
1154 #endif /* PROVIDE_ADDR */
1155
1156 #ifdef PROVIDE_INTEGER
1157     /* Integer operations */
1158     , { "primCompareInteger",        "ZZ", "I",  MONAD_Id, i_PRIMOP1, i_compareInteger }
1159     , { "primNegateInteger",         "Z",  "Z",  MONAD_Id, i_PRIMOP1, i_negateInteger }
1160     , { "primPlusInteger",           "ZZ", "Z",  MONAD_Id, i_PRIMOP1, i_plusInteger }
1161     , { "primMinusInteger",          "ZZ", "Z",  MONAD_Id, i_PRIMOP1, i_minusInteger }
1162     , { "primTimesInteger",          "ZZ", "Z",  MONAD_Id, i_PRIMOP1, i_timesInteger }
1163     , { "primQuotRemInteger",        "ZZ", "ZZ", MONAD_Id, i_PRIMOP1, i_quotRemInteger }
1164     , { "primDivModInteger",         "ZZ", "ZZ", MONAD_Id, i_PRIMOP1, i_divModInteger }
1165     , { "primIntegerToInt",          "Z",  "I",  MONAD_Id, i_PRIMOP1, i_integerToInt }
1166     , { "primIntToInteger",          "I",  "Z",  MONAD_Id, i_PRIMOP1, i_intToInteger }
1167 #ifdef PROVIDE_INT64
1168     , { "primIntegerToInt64",        "Z",  "z",  MONAD_Id, i_PRIMOP1, i_integerToInt64 }
1169     , { "primInt64ToInteger",        "z",  "Z",  MONAD_Id, i_PRIMOP1, i_int64ToInteger }
1170 #endif
1171 #ifdef PROVIDE_WORD
1172     , { "primIntegerToWord",         "Z",  "W",  MONAD_Id, i_PRIMOP1, i_integerToWord }
1173     , { "primWordToInteger",         "W",  "Z",  MONAD_Id, i_PRIMOP1, i_wordToInteger }
1174 #endif
1175     , { "primIntegerToFloat",        "Z",  "F",  MONAD_Id, i_PRIMOP1, i_integerToFloat }
1176     , { "primFloatToInteger",        "F",  "Z",  MONAD_Id, i_PRIMOP1, i_floatToInteger }
1177     , { "primIntegerToDouble",       "Z",  "D",  MONAD_Id, i_PRIMOP1, i_integerToDouble }
1178     , { "primDoubleToInteger",       "D",  "Z",  MONAD_Id, i_PRIMOP1, i_doubleToInteger }
1179 #endif
1180
1181     /* Float# operations */
1182     , { "primGtFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_gtFloat }
1183     , { "primGeFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_geFloat }
1184     , { "primEqFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_eqFloat }
1185     , { "primNeFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_neFloat }
1186     , { "primLtFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_ltFloat }
1187     , { "primLeFloat",               "FF", "B",  MONAD_Id, i_PRIMOP1, i_leFloat }
1188     , { "primMinFloat",              "",   "F",  MONAD_Id, i_PRIMOP1, i_minFloat }
1189     , { "primMaxFloat",              "",   "F",  MONAD_Id, i_PRIMOP1, i_maxFloat }
1190     , { "primRadixFloat",            "",   "I",  MONAD_Id, i_PRIMOP1, i_radixFloat }
1191     , { "primDigitsFloat",           "",   "I",  MONAD_Id, i_PRIMOP1, i_digitsFloat }
1192     , { "primMinExpFloat",           "",   "I",  MONAD_Id, i_PRIMOP1, i_minExpFloat }
1193     , { "primMaxExpFloat",           "",   "I",  MONAD_Id, i_PRIMOP1, i_maxExpFloat }
1194     , { "primPlusFloat",             "FF", "F",  MONAD_Id, i_PRIMOP1, i_plusFloat }
1195     , { "primMinusFloat",            "FF", "F",  MONAD_Id, i_PRIMOP1, i_minusFloat }
1196     , { "primTimesFloat",            "FF", "F",  MONAD_Id, i_PRIMOP1, i_timesFloat }
1197     , { "primDivideFloat",           "FF", "F",  MONAD_Id, i_PRIMOP1, i_divideFloat }
1198     , { "primNegateFloat",           "F",  "F",  MONAD_Id, i_PRIMOP1, i_negateFloat }
1199     , { "primFloatToInt",            "F",  "I",  MONAD_Id, i_PRIMOP1, i_floatToInt }
1200     , { "primIntToFloat",            "I",  "F",  MONAD_Id, i_PRIMOP1, i_intToFloat }
1201     , { "primExpFloat",              "F",  "F",  MONAD_Id, i_PRIMOP1, i_expFloat }
1202     , { "primLogFloat",              "F",  "F",  MONAD_Id, i_PRIMOP1, i_logFloat }
1203     , { "primSqrtFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_sqrtFloat }
1204     , { "primSinFloat",              "F",  "F",  MONAD_Id, i_PRIMOP1, i_sinFloat }
1205     , { "primCosFloat",              "F",  "F",  MONAD_Id, i_PRIMOP1, i_cosFloat }
1206     , { "primTanFloat",              "F",  "F",  MONAD_Id, i_PRIMOP1, i_tanFloat }
1207     , { "primAsinFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_asinFloat }
1208     , { "primAcosFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_acosFloat }
1209     , { "primAtanFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_atanFloat }
1210     , { "primSinhFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_sinhFloat }
1211     , { "primCoshFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_coshFloat }
1212     , { "primTanhFloat",             "F",  "F",  MONAD_Id, i_PRIMOP1, i_tanhFloat }
1213     , { "primPowerFloat",            "FF", "F",  MONAD_Id, i_PRIMOP1, i_powerFloat }
1214 #ifdef PROVIDE_INT64
1215     , { "primDecodeFloatz",          "F",  "zI", MONAD_Id, i_PRIMOP1, i_decodeFloatz }
1216     , { "primEncodeFloatz",          "zI", "F",  MONAD_Id, i_PRIMOP1, i_encodeFloatz }
1217 #endif
1218 #ifdef PROVIDE_INTEGER
1219     , { "primDecodeFloatZ",          "F",  "ZI", MONAD_Id, i_PRIMOP1, i_decodeFloatZ }
1220     , { "primEncodeFloatZ",          "ZI", "F",  MONAD_Id, i_PRIMOP1, i_encodeFloatZ }
1221 #endif
1222     , { "primIsNaNFloat",            "F",  "B",  MONAD_Id, i_PRIMOP1, i_isNaNFloat }
1223     , { "primIsInfiniteFloat",       "F",  "B",  MONAD_Id, i_PRIMOP1, i_isInfiniteFloat }
1224     , { "primIsDenormalizedFloat",   "F",  "B",  MONAD_Id, i_PRIMOP1, i_isDenormalizedFloat }
1225     , { "primIsNegativeZeroFloat",   "F",  "B",  MONAD_Id, i_PRIMOP1, i_isNegativeZeroFloat }
1226     , { "primIsIEEEFloat",           "",   "B",  MONAD_Id, i_PRIMOP1, i_isIEEEFloat }
1227
1228     /* Double# operations */
1229     , { "primGtDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_gtDouble }
1230     , { "primGeDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_geDouble }
1231     , { "primEqDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_eqDouble }
1232     , { "primNeDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_neDouble }
1233     , { "primLtDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_ltDouble }
1234     , { "primLeDouble",              "DD", "B",  MONAD_Id, i_PRIMOP1, i_leDouble }
1235     , { "primMinDouble",             "",   "D",  MONAD_Id, i_PRIMOP1, i_minDouble }
1236     , { "primMaxDouble",             "",   "D",  MONAD_Id, i_PRIMOP1, i_maxDouble }
1237     , { "primRadixDouble",           "",   "I",  MONAD_Id, i_PRIMOP1, i_radixDouble }
1238     , { "primDigitsDouble",          "",   "I",  MONAD_Id, i_PRIMOP1, i_digitsDouble }
1239     , { "primMinExpDouble",          "",   "I",  MONAD_Id, i_PRIMOP1, i_minExpDouble }
1240     , { "primMaxExpDouble",          "",   "I",  MONAD_Id, i_PRIMOP1, i_maxExpDouble }
1241     , { "primPlusDouble",            "DD", "D",  MONAD_Id, i_PRIMOP1, i_plusDouble }
1242     , { "primMinusDouble",           "DD", "D",  MONAD_Id, i_PRIMOP1, i_minusDouble }
1243     , { "primTimesDouble",           "DD", "D",  MONAD_Id, i_PRIMOP1, i_timesDouble }
1244     , { "primDivideDouble",          "DD", "D",  MONAD_Id, i_PRIMOP1, i_divideDouble }
1245     , { "primNegateDouble",          "D",  "D",  MONAD_Id, i_PRIMOP1, i_negateDouble }
1246     , { "primDoubleToInt",           "D",  "I",  MONAD_Id, i_PRIMOP1, i_doubleToInt }
1247     , { "primIntToDouble",           "I",  "D",  MONAD_Id, i_PRIMOP1, i_intToDouble }
1248     , { "primDoubleToFloat",         "D",  "F",  MONAD_Id, i_PRIMOP1, i_doubleToFloat }
1249     , { "primFloatToDouble",         "F",  "D",  MONAD_Id, i_PRIMOP1, i_floatToDouble }
1250     , { "primExpDouble",             "D",  "D",  MONAD_Id, i_PRIMOP1, i_expDouble }
1251     , { "primLogDouble",             "D",  "D",  MONAD_Id, i_PRIMOP1, i_logDouble }
1252     , { "primSqrtDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_sqrtDouble }
1253     , { "primSinDouble",             "D",  "D",  MONAD_Id, i_PRIMOP1, i_sinDouble }
1254     , { "primCosDouble",             "D",  "D",  MONAD_Id, i_PRIMOP1, i_cosDouble }
1255     , { "primTanDouble",             "D",  "D",  MONAD_Id, i_PRIMOP1, i_tanDouble }
1256     , { "primAsinDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_asinDouble }
1257     , { "primAcosDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_acosDouble }
1258     , { "primAtanDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_atanDouble }
1259     , { "primSinhDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_sinhDouble }
1260     , { "primCoshDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_coshDouble }
1261     , { "primTanhDouble",            "D",  "D",  MONAD_Id, i_PRIMOP1, i_tanhDouble }
1262     , { "primPowerDouble",           "DD", "D",  MONAD_Id, i_PRIMOP1, i_powerDouble }
1263 #ifdef PROVIDE_INT64
1264     , { "primDecodeDoublez",         "D",  "zI", MONAD_Id, i_PRIMOP1, i_decodeDoublez }
1265     , { "primEncodeDoublez",         "zI",  "D", MONAD_Id, i_PRIMOP1, i_encodeDoublez }
1266 #endif
1267 #ifdef PROVIDE_INTEGER
1268     , { "primDecodeDoubleZ",         "D",  "ZI", MONAD_Id, i_PRIMOP1, i_decodeDoubleZ }
1269     , { "primEncodeDoubleZ",         "ZI",  "D", MONAD_Id, i_PRIMOP1, i_encodeDoubleZ }
1270 #endif
1271     , { "primIsNaNDouble",           "D",  "B",  MONAD_Id, i_PRIMOP1, i_isNaNDouble }
1272     , { "primIsInfiniteDouble",      "D",  "B",  MONAD_Id, i_PRIMOP1, i_isInfiniteDouble }
1273     , { "primIsDenormalizedDouble",  "D",  "B",  MONAD_Id, i_PRIMOP1, i_isDenormalizedDouble }
1274     , { "primIsNegativeZeroDouble",  "D",  "B",  MONAD_Id, i_PRIMOP1, i_isNegativeZeroDouble }
1275     , { "primIsIEEEDouble",          "",   "B",  MONAD_Id, i_PRIMOP1, i_isIEEEDouble }
1276
1277
1278     /* Polymorphic force :: a -> (# #) */
1279       /* , { "primForce",                 "a",  "",   MONAD_Id, i_PRIMOP2, i_force } */
1280
1281     /* Error operations - not in IO monad! */
1282       //, { "primRaise",                 "E",  "a",  MONAD_Id, i_PRIMOP2, i_raise }
1283       //, { "primCatch'",                "aH", "a",  MONAD_Id, i_PRIMOP2, i_catch }
1284
1285 #ifdef PROVIDE_ARRAY
1286     /* Ref operations */
1287     , { "primNewRef",                "a",  "R",  MONAD_ST, i_PRIMOP2, i_newRef }
1288     , { "primWriteRef",              "Ra", "",   MONAD_ST, i_PRIMOP2, i_writeRef }
1289     , { "primReadRef",               "R",  "a",  MONAD_ST, i_PRIMOP2, i_readRef }
1290     , { "primSameRef",               "RR", "B",  MONAD_Id, i_PRIMOP2, i_sameRef }
1291
1292     /* PrimArray operations */
1293     , { "primSameMutableArray",      "MM",  "B", MONAD_Id, i_PRIMOP2, i_sameMutableArray }
1294     , { "primUnsafeFreezeArray",     "M",   "X", MONAD_ST, i_PRIMOP2, i_unsafeFreezeArray }
1295     , { "primNewArray",              "Ia",  "M", MONAD_ST, i_PRIMOP2, i_newArray }
1296     , { "primWriteArray",            "MIa", "",  MONAD_ST, i_PRIMOP2, i_writeArray }
1297     , { "primReadArray",             "MI",  "a", MONAD_ST, i_PRIMOP2, i_readArray }
1298     , { "primIndexArray",            "XI",  "a", MONAD_Id, i_PRIMOP2, i_indexArray }
1299     , { "primSizeArray",             "X",   "I", MONAD_Id, i_PRIMOP2, i_sizeArray }
1300     , { "primSizeMutableArray",      "M",   "I", MONAD_Id, i_PRIMOP2, i_sizeMutableArray }
1301
1302     /* Prim[Mutable]ByteArray operations */
1303     , { "primSameMutableByteArray",  "mm", "B", MONAD_Id, i_PRIMOP2, i_sameMutableByteArray }
1304     , { "primUnsafeFreezeByteArray", "m",  "x", MONAD_ST, i_PRIMOP2, i_unsafeFreezeByteArray }
1305     
1306     , { "primNewByteArray",          "I",  "m", MONAD_ST, i_PRIMOP2, i_newByteArray }
1307
1308     , { "primWriteCharArray",        "mIC", "", MONAD_ST, i_PRIMOP2, i_writeCharArray }
1309     , { "primReadCharArray",         "mI", "C", MONAD_ST, i_PRIMOP2, i_readCharArray }
1310     , { "primIndexCharArray",        "xI", "C", MONAD_Id, i_PRIMOP2, i_indexCharArray }
1311     
1312     , { "primWriteIntArray",         "mII", "",  MONAD_ST, i_PRIMOP2, i_writeIntArray }
1313     , { "primReadIntArray",          "mI",  "I", MONAD_ST, i_PRIMOP2, i_readIntArray }
1314     , { "primIndexIntArray",         "xI",  "I", MONAD_Id, i_PRIMOP2, i_indexIntArray }
1315
1316 #ifdef PROVIDE_INT64
1317     , { "primWriteInt64Array",       "mIz", "",  MONAD_ST, i_PRIMOP2, i_writeInt64Array }
1318     , { "primReadInt64Array",        "mI",  "z", MONAD_ST, i_PRIMOP2, i_readInt64Array }
1319     , { "primIndexInt64Array",       "xI",  "z", MONAD_Id, i_PRIMOP2, i_indexInt64Array }
1320 #endif
1321
1322     /* {new,write,read,index}IntegerArray not provided */
1323
1324 #ifdef PROVIDE_WORD
1325     , { "primWriteWordArray",        "mIW", "",  MONAD_ST, i_PRIMOP2, i_writeWordArray }
1326     , { "primReadWordArray",         "mI",  "W", MONAD_ST, i_PRIMOP2, i_readWordArray }
1327     , { "primIndexWordArray",        "xI",  "W", MONAD_Id, i_PRIMOP2, i_indexWordArray }
1328 #endif                                 
1329 #ifdef PROVIDE_ADDR                    
1330     , { "primWriteAddrArray",        "mIA", "",  MONAD_ST, i_PRIMOP2, i_writeAddrArray }
1331     , { "primReadAddrArray",         "mI",  "A", MONAD_ST, i_PRIMOP2, i_readAddrArray }
1332     , { "primIndexAddrArray",        "xI",  "A", MONAD_Id, i_PRIMOP2, i_indexAddrArray }
1333 #endif                                
1334     , { "primWriteFloatArray",       "mIF", "",  MONAD_ST, i_PRIMOP2, i_writeFloatArray }
1335     , { "primReadFloatArray",        "mI",  "F", MONAD_ST, i_PRIMOP2, i_readFloatArray }
1336     , { "primIndexFloatArray",       "xI",  "F", MONAD_Id, i_PRIMOP2, i_indexFloatArray }
1337                                      
1338     , { "primWriteDoubleArray" ,     "mID", "",  MONAD_ST, i_PRIMOP2, i_writeDoubleArray }
1339     , { "primReadDoubleArray",       "mI",  "D", MONAD_ST, i_PRIMOP2, i_readDoubleArray }
1340     , { "primIndexDoubleArray",      "xI",  "D", MONAD_Id, i_PRIMOP2, i_indexDoubleArray }
1341
1342 #ifdef PROVIDE_STABLE                
1343     , { "primWriteStableArray",      "mIs", "",  MONAD_ST, i_PRIMOP2, i_writeStableArray }
1344     , { "primReadStableArray",       "mI",  "s", MONAD_ST, i_PRIMOP2, i_readStableArray }
1345     , { "primIndexStableArray",      "xI",  "s", MONAD_Id, i_PRIMOP2, i_indexStableArray }
1346 #endif
1347
1348     /* {new,write,read,index}ForeignObjArray not provided */
1349
1350 #endif PROVIDE_ARRAY
1351
1352 #ifdef PROVIDE_FOREIGN
1353     /* ForeignObj# operations */
1354     , { "primMakeForeignObj",        "A",  "f",  MONAD_IO, i_PRIMOP2, i_makeForeignObj }
1355 #endif
1356 #ifdef PROVIDE_WEAK
1357     /* WeakPair# operations */
1358     , { "primMakeWeak",              "bac", "w",  MONAD_IO, i_PRIMOP2, i_makeWeak }
1359     , { "primDeRefWeak",             "w",   "Ia", MONAD_IO, i_PRIMOP2, i_deRefWeak }
1360 #endif
1361 #ifdef PROVIDE_STABLE
1362     /* StablePtr# operations */
1363     , { "primMakeStablePtr",         "a", "s",   MONAD_IO, i_PRIMOP2, i_makeStablePtr }
1364     , { "primDeRefStablePtr",        "s", "a",   MONAD_IO, i_PRIMOP2, i_deRefStablePtr }
1365     , { "primFreeStablePtr",         "s", "",    MONAD_IO, i_PRIMOP2, i_freeStablePtr }
1366 #endif
1367 #ifdef PROVIDE_PTREQUALITY
1368     , { "primReallyUnsafePtrEquality", "aa", "B",MONAD_Id, i_PRIMOP2, i_reallyUnsafePtrEquality }
1369 #endif
1370 #ifdef PROVIDE_COERCE
1371     , { "primUnsafeCoerce",          "a", "b",   MONAD_Id, i_PRIMOP2, i_unsafeCoerce }
1372 #endif
1373 #ifdef PROVIDE_CONCURRENT
1374     /* Concurrency operations */
1375     , { "primFork",                  "a", "T",   MONAD_IO, i_PRIMOP2, i_fork }
1376     , { "primKillThread",            "T", "",    MONAD_IO, i_PRIMOP2, i_killThread }
1377     , { "primSameMVar",              "rr", "B",  MONAD_Id, i_PRIMOP2, i_sameMVar }
1378     , { "primNewMVar",               "",  "r",   MONAD_IO, i_PRIMOP2, i_newMVar }
1379     , { "primTakeMVar",              "r", "a",   MONAD_IO, i_PRIMOP2, i_takeMVar }
1380     , { "primPutMVar",               "ra", "",   MONAD_IO, i_PRIMOP2, i_putMVar } 
1381     , { "primDelay",                 "I", "",    MONAD_IO, i_PRIMOP2, i_delay }
1382     , { "primWaitRead",              "I", "",    MONAD_IO, i_PRIMOP2, i_waitRead }
1383     , { "primWaitWrite",             "I", "",    MONAD_IO, i_PRIMOP2, i_waitWrite }
1384 #endif
1385
1386     /* Ccall is polyadic - so it's excluded from this table */
1387
1388     , { 0,0,0,0 }
1389 };
1390
1391 const AsmPrim ccall_Id = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_Id };
1392 const AsmPrim ccall_IO = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_IO };
1393
1394
1395 const AsmPrim* asmFindPrim( char* s )
1396 {
1397     int i;
1398     for (i=0; asmPrimOps[i].name; ++i) {
1399         if (strcmp(s,asmPrimOps[i].name)==0) {
1400             return &asmPrimOps[i];
1401         }
1402     }
1403     return 0;
1404 }
1405
1406 const AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
1407 {
1408     nat i;
1409     for (i=0; asmPrimOps[i].name; ++i) {
1410         if (asmPrimOps[i].prefix == prefix && asmPrimOps[i].opcode == op) {
1411             return &asmPrimOps[i];
1412         }
1413     }
1414     return 0;
1415 }
1416
1417 /* --------------------------------------------------------------------------
1418  * Handwritten primops
1419  * ------------------------------------------------------------------------*/
1420
1421 AsmBCO asm_BCO_catch ( void )
1422 {
1423    AsmBCO bco = asmBeginBCO(0 /*NIL*/);
1424    asmInstr(bco,i_ARG_CHECK); asmInstr(bco,2);
1425    asmInstr(bco,i_PRIMOP1); asmInstr(bco,i_pushcatchframe);
1426    bco->sp += (1-2)*sizeofW(StgPtr) + sizeofW(StgCatchFrame);
1427    asmInstr(bco,i_ENTER);
1428    asmEndBCO(bco);
1429    return bco;
1430 }
1431
1432 AsmBCO asm_BCO_raise ( void )
1433 {
1434    AsmBCO bco = asmBeginBCO(0 /*NIL*/);
1435    asmInstr(bco,i_ARG_CHECK); asmInstr(bco,1);
1436    asmInstr(bco,i_PRIMOP2); asmInstr(bco,i_raise);
1437    asmEndBCO(bco);
1438    return bco;
1439 }
1440
1441 AsmBCO asm_BCO_seq ( void )
1442 {
1443    AsmBCO eval, cont;
1444
1445    cont = asmBeginBCO(0 /*NIL*/);
1446    asmInstr(cont,i_ARG_CHECK); asmInstr(cont,2);
1447    asmInstr(cont,i_VAR); asmInstr(cont,1);
1448    asmInstr(cont,i_SLIDE); asmInstr(cont,1); asmInstr(cont,2);
1449    asmInstr(cont,i_ENTER);
1450    cont->sp += 3*sizeofW(StgPtr);
1451    asmEndBCO(cont);
1452
1453    eval = asmBeginBCO(0 /*NIL*/);
1454    asmInstr(eval,i_ARG_CHECK); asmInstr(eval,2);
1455    asmInstr(eval,i_RETADDR);
1456    asmInstr(eval,eval->object.ptrs.len);
1457    asmPtr(eval,&(cont->object));
1458    asmInstr(eval,i_VAR); asmInstr(eval,2);
1459    asmInstr(eval,i_SLIDE); asmInstr(eval,3); asmInstr(eval,1);
1460    asmInstr(eval,i_PRIMOP1); asmInstr(eval,i_pushseqframe);
1461    asmInstr(eval,i_ENTER);
1462    eval->sp += sizeofW(StgSeqFrame) + 4*sizeofW(StgPtr);
1463    asmEndBCO(eval);
1464
1465    return eval;
1466 }
1467
1468 /* --------------------------------------------------------------------------
1469  * Heap manipulation
1470  * ------------------------------------------------------------------------*/
1471
1472 AsmVar asmAllocCONSTR   ( AsmBCO bco, AsmInfo info )
1473 {
1474     ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1475     asmInstr(bco,i_ALLOC_CONSTR);
1476     asmInstr(bco,bco->nps.len);
1477     asmWords(bco,AsmInfo,info);
1478     bco->sp += sizeofW(StgClosurePtr);
1479     grabHpNonUpd(bco,sizeW_fromITBL(info));
1480     return bco->sp;
1481 }
1482
1483 AsmSp asmBeginPack( AsmBCO bco )
1484 {
1485     return bco->sp;
1486 }
1487
1488 void asmEndPack( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info )
1489 {
1490     nat size = bco->sp - start;
1491     assert(bco->sp >= start);
1492     assert(start >= v);
1493     /* only reason to include info is for this assertion */
1494     assert(info->layout.payload.ptrs == size);
1495     asmInstr(bco,i_PACK);
1496     asmInstr(bco,bco->sp - v);
1497     bco->sp = start;
1498 }
1499
1500 void asmBeginUnpack( AsmBCO bco )
1501 {
1502     /* dummy to make it look prettier */
1503 }
1504
1505 void asmEndUnpack( AsmBCO bco )
1506 {
1507     asmInstr(bco,i_UNPACK);
1508 }
1509
1510 AsmVar asmAllocAP( AsmBCO bco, AsmNat words )
1511 {
1512     asmInstr(bco,i_ALLOC_AP);
1513     asmInstr(bco,words);
1514     bco->sp += sizeofW(StgPtr);
1515     grabHpUpd(bco,AP_sizeW(words));
1516     return bco->sp;
1517 }
1518
1519 AsmSp asmBeginMkAP( AsmBCO bco )
1520 {
1521     return bco->sp;
1522 }
1523
1524 void asmEndMkAP( AsmBCO bco, AsmVar v, AsmSp start )
1525 {
1526     asmInstr(bco,i_MKAP);
1527     asmInstr(bco,bco->sp-v);
1528     asmInstr(bco,bco->sp-start-1);  /* -1 because fun isn't counted */
1529     bco->sp = start;
1530 }
1531
1532 AsmVar asmAllocPAP( AsmBCO bco, AsmNat size )
1533 {
1534     asmInstr(bco,i_ALLOC_PAP);
1535     asmInstr(bco,size);
1536     bco->sp += sizeofW(StgPtr);
1537     return bco->sp;
1538 }
1539
1540 AsmSp asmBeginMkPAP( AsmBCO bco )
1541 {
1542     return bco->sp;
1543 }
1544
1545 void asmEndMkPAP( AsmBCO bco, AsmVar v, AsmSp start )
1546 {
1547     asmInstr(bco,i_MKPAP);
1548     asmInstr(bco,bco->sp-v);
1549     asmInstr(bco,bco->sp-start-1);  /* -1 because fun isn't counted */
1550     bco->sp = start;
1551 }
1552
1553 AsmVar asmClosure( AsmBCO bco, AsmObject p )
1554 {
1555     StgWord o = bco->object.ptrs.len;
1556     if (o < 256) {
1557         asmInstr(bco,i_CONST);
1558         asmInstr(bco,o);
1559         asmPtr(bco,p);
1560     } else {
1561         asmInstr(bco,i_CONST2);
1562         asmInstr(bco,o / 256);
1563         asmInstr(bco,o % 256);
1564         asmPtr(bco,p);
1565     }
1566     bco->sp += sizeofW(StgPtr);
1567     return bco->sp;
1568 }
1569
1570 /* --------------------------------------------------------------------------
1571  * Building InfoTables
1572  * ------------------------------------------------------------------------*/
1573
1574 AsmInfo asmMkInfo( AsmNat tag, AsmNat ptrs )
1575 {
1576     StgInfoTable* info = stgMallocBytes( sizeof(StgInfoTable),"asmMkInfo");
1577     /* Note: the evaluator automatically pads objects with the right number
1578      * of non-ptrs to satisfy MIN_NONUPD_SIZE restrictions.
1579      */
1580     AsmNat nptrs = stg_max(0,MIN_NONUPD_SIZE-ptrs);
1581
1582     /* initialisation code based on INFO_TABLE_CONSTR */
1583     info->layout.payload.ptrs  = ptrs;
1584     info->layout.payload.nptrs = nptrs;
1585     info->srt_len = tag;
1586     info->type    = CONSTR;
1587     info->flags   = FLAGS_CONSTR;
1588 #ifdef USE_MINIINTERPRETER
1589     info->entry   = stgCast(StgFunPtr,&Hugs_CONSTR_entry);
1590 #else
1591 #warning asmMkInfo: Need to insert entry code in some cunning way
1592 #endif
1593     ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1594     return info;
1595 }
1596
1597 /*-------------------------------------------------------------------------*/
1598
1599 #endif /* INTERPRETER */
1600