1 /* -*- mode: hugs-c; -*- */
2 /* --------------------------------------------------------------------------
3 * $Id: Assembler.c,v 1.4 1999/02/05 16:02:34 simonm Exp $
5 * Copyright (c) The GHC Team 1994-1998.
9 * This module provides functions to construct BCOs and other closures
10 * required by the bytecode compiler.
12 * It is supposed to shield the compiler from platform dependent information
18 * and from details of how the abstract machine is implemented such as:
20 * o what does a BCO look like?
21 * o how many bytes does the "Push InfoTable" instruction require?
24 * o (To handle letrecs) We allocate Aps, Paps and Cons using number of
25 * heap allocated args to determine size.
26 * We can't handle unboxed args :-(
27 * o All stack offsets are relative to position of Sp at start of
28 * function or thunk (not BCO - consider continuations)
29 * o Active thunks must be roots during GC - how to achieve this?
30 * o Each BCO contains its own stack and heap check
31 * We don't try to exploit the Hp check optimisation - easier to make
32 * each thunk stand on its own.
33 * o asBind returns a "varid" (which is, in fact, a stack offset)
34 * asVar acts on a "varid" - combining it with the current stack size to
35 * determine actual position
36 * o Assembler.h uses totally neutral types: strings, floats, ints, etc
37 * to minimise conflicts with other parts of the system.
39 * ------------------------------------------------------------------------*/
47 #include "Bytecodes.h"
49 #include "Disassembler.h"
50 #include "Evaluator.h"
51 #include "StgMiscClosures.h"
54 #define INSIDE_ASSEMBLER_C
55 #include "Assembler.h"
56 #undef INSIDE_ASSEMBLER_C
58 /* --------------------------------------------------------------------------
59 * References between BCOs
61 * These are necessary because there can be circular references between
62 * BCOs so we have to keep track of all the references to each object
63 * and fill in all the references once we're done.
65 * ToDo: generalise to allow references between any objects
66 * ------------------------------------------------------------------------*/
69 AsmObject ref; /* who refers to it */
70 AsmNat i; /* index into some table held by referer */
73 /* --------------------------------------------------------------------------
74 * Queues (of instructions, ptrs, nonptrs)
75 * ------------------------------------------------------------------------*/
77 /* ToDo: while debugging, we use a chunk size of 1 to stress-test the code
78 * this should be fine-tuned using statistics on common sizes
81 #define InstrsChunkSize 40
82 #define PtrsChunkSize 10
83 #define RefsChunkSize 10
84 #define NonPtrsChunkSize 10
88 #include "QueueTemplate.h"
93 #define Type AsmObject
94 #include "QueueTemplate.h"
100 #include "QueueTemplate.h"
104 #define Queue NonPtrs
106 #include "QueueTemplate.h"
110 /* --------------------------------------------------------------------------
111 * AsmObjects are used to build heap objects.
113 * AsmObjects can contain circular references to each other
114 * so we have to keep track of all the references which can't be filled
117 * When we finish building an AsmObject, we allocate an actual heap object and
118 * fill in all the references to the asmObject with pointers to the heap object.
120 * We obtain a limited form of polymorphism through inheritance by putting
121 * the AsmObject first in every structure (as in C++ implementations).
122 * We use the closure type of the allocated object to figure out
123 * where the payload lives in the closure.
124 * ------------------------------------------------------------------------*/
125 /* ToDo: clean up terminology: is Closure right or should it be object or ... */
130 AsmNat num_unresolved; /* number of unfilled references */
131 StgClosure* closure; /* where object was allocated */
135 struct AsmObject_ object; /* must be first in struct */
141 struct AsmObject_ object; /* must be first in struct */
145 struct AsmObject_ object; /* must be first in struct */
150 /* abstract machine ("executed" during compilation) */
151 AsmSp sp; /* stack ptr */
153 StgWord hp; /* heap ptr */
157 static void asmResolveRef( AsmObject obj, AsmNat i, AsmClosure reference )
159 ASSERT(obj->closure);
160 switch (get_itbl(obj->closure)->type) {
163 StgBCO* bco = stgCast(StgBCO*,obj->closure);
164 ASSERT(i < bco->n_ptrs && bcoConstPtr(bco,i) == NULL);
165 bcoConstCPtr(bco,i) = reference;
170 StgCAF* caf = stgCast(StgCAF*,obj->closure);
171 ASSERT(i == 0 && caf->body == NULL);
172 caf->body = reference;
177 StgClosure* con = stgCast(StgClosure*,obj->closure);
178 ASSERT(i < get_itbl(con)->layout.payload.nptrs && payloadCPtr(con,i) == NULL);
179 payloadCPtr(con,i) = reference;
184 StgAP_UPD* ap = stgCast(StgAP_UPD*,obj->closure);
185 ASSERT(i < 1+ap->n_args);
187 ASSERT(ap->fun == NULL);
190 ASSERT(payloadCPtr(ap,i-1) == NULL);
191 payloadCPtr(ap,i-1) = reference;
196 barf("asmResolveRef");
198 obj->num_unresolved -= 1;
200 if (obj->num_unresolved == 0) {
201 /* todo: free the queues */
203 /* we don't print until all ptrs are resolved */
204 IF_DEBUG(codegen,printObj(obj->closure));
208 static void asmAddRef( AsmObject referent, AsmObject referer, AsmNat i )
210 if (referent->closure) {
211 asmResolveRef(referer,i,(AsmClosure)referent->closure);
213 insertRefs(&(referent->refs),(AsmRef){referer,i});
217 void asmAddPtr( AsmObject obj, AsmObject arg )
219 ASSERT(obj->closure == 0); /* can't extend an object once it's allocated */
220 insertPtrs( &obj->ptrs, arg );
223 static void asmBeginObject( AsmObject obj )
226 obj->num_unresolved = 0;
227 initRefs(&obj->refs);
228 initPtrs(&obj->ptrs);
231 static void asmEndObject( AsmObject obj, StgClosure* c )
233 obj->num_unresolved = obj->ptrs.len;
235 mapQueue(Ptrs, AsmObject, obj->ptrs, asmAddRef(x,obj,i));
236 mapQueue(Refs, AsmRef, obj->refs, asmResolveRef(x.ref,x.i,c));
237 if (obj->num_unresolved == 0) {
238 /* todo: free the queues */
239 /* we don't print until all ptrs are resolved */
240 IF_DEBUG(codegen,printObj(obj->closure));
244 int asmObjectHasClosure ( AsmObject obj )
246 return (obj->num_unresolved == 0 && obj->closure);
249 AsmClosure asmClosureOfObject ( AsmObject obj )
251 ASSERT(asmObjectHasClosure(obj));
255 void asmMarkObject ( AsmObject obj )
257 ASSERT(obj->num_unresolved == 0 && obj->closure);
258 obj->closure = MarkRoot(obj->closure);
261 /* --------------------------------------------------------------------------
263 * ------------------------------------------------------------------------*/
265 static StgClosure* asmAlloc( nat size )
267 StgClosure* o = stgCast(StgClosure*,allocate(size));
268 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
269 /* printf("Allocated %p .. %p\n", o, o+size-1); */
273 static void grabHpUpd( AsmBCO bco, nat size )
275 /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
276 ASSERT( size >= MIN_UPD_SIZE + sizeofW(StgHeader) );
280 static void grabHpNonUpd( AsmBCO bco, nat size )
282 /* ToDo: sometimes we should test for MIN_UPD_SIZE instead */
283 ASSERT( size >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
287 static void resetHp( AsmBCO bco, nat hp )
289 bco->max_hp = stg_max(bco->hp,bco->max_hp);
293 static void resetSp( AsmBCO bco, AsmSp sp )
295 bco->max_sp = stg_max(bco->sp,bco->max_sp);
299 /* --------------------------------------------------------------------------
301 * ------------------------------------------------------------------------*/
303 AsmObject asmMkObject( AsmClosure c )
305 AsmObject obj = malloc(sizeof(struct AsmObject_));
307 barf("Can't allocate AsmObject");
314 AsmCon asmBeginCon( AsmInfo info )
316 AsmCon con = malloc(sizeof(struct AsmCon_));
318 barf("Can't allocate AsmCon");
320 asmBeginObject(&con->object);
325 void asmEndCon( AsmCon con )
327 nat p = con->object.ptrs.len;
328 nat np = stg_max(0,MIN_NONUPD_SIZE-p);
330 StgClosure* c = asmAlloc(CONSTR_sizeW(p,np));
331 StgClosure* o = stgCast(StgClosure*,c);
332 SET_HDR(o,con->info,??);
333 mapQueue(Ptrs, AsmObject, con->object.ptrs, payloadCPtr(o,i) = NULL);
334 { nat i; for( i=0; i<np; ++i ) { payloadWord(o,p+i) = 0xdeadbeef; } }
335 asmEndObject(&con->object,c);
338 AsmCAF asmBeginCAF( void )
340 AsmCAF caf = malloc(sizeof(struct AsmCAF_));
342 barf("Can't allocate AsmCAF");
344 asmBeginObject(&caf->object);
348 void asmEndCAF( AsmCAF caf, AsmBCO body )
350 StgClosure* c = asmAlloc(CAF_sizeW());
351 StgCAF* o = stgCast(StgCAF*,c);
352 SET_HDR(o,&CAF_UNENTERED_info,??);
354 o->value = stgCast(StgClosure*,0xdeadbeef);
355 o->link = stgCast(StgCAF*,0xdeadbeef);
356 asmAddPtr(&caf->object,&body->object);
357 asmEndObject(&caf->object,c);
360 AsmBCO asmBeginBCO( void )
362 AsmBCO bco = malloc(sizeof(struct AsmBCO_));
364 barf("Can't allocate AsmBCO");
366 asmBeginObject(&bco->object);
367 initInstrs(&bco->is);
368 initNonPtrs(&bco->nps);
370 bco->max_sp = bco->sp = 0;
371 bco->max_hp = bco->hp = 0;
375 void asmEndBCO( AsmBCO bco )
377 nat p = bco->object.ptrs.len;
378 nat np = bco->nps.len;
380 nat is = bco->is.len + 4; /* 4 for stack and heap checks */
382 nat is = bco->is.len + 2; /* 4 for stack check */
385 StgClosure* c = asmAlloc(BCO_sizeW(p,np,is));
386 StgBCO* o = stgCast(StgBCO*,c);
387 SET_HDR(o,&BCO_info,??);
391 mapQueue(Ptrs, AsmObject, bco->object.ptrs, bcoConstCPtr(o,i) = NULL);
392 mapQueue(NonPtrs, StgWord, bco->nps, bcoConstWord(o,i) = x);
395 bco->max_sp = stg_max(bco->sp,bco->max_sp);
396 bco->max_hp = stg_max(bco->hp,bco->max_hp);
397 bcoInstr(o,j++) = i_STK_CHECK;
398 bcoInstr(o,j++) = bco->max_sp;
400 bcoInstr(o,j++) = i_HP_CHECK;
401 bcoInstr(o,j++) = bco->max_hp;
403 mapQueue(Instrs, StgNat8, bco->is, bcoInstr(o,j++) = x);
406 asmEndObject(&bco->object,c);
409 /* --------------------------------------------------------------------------
411 * ------------------------------------------------------------------------*/
413 static void asmInstr( AsmBCO bco, StgWord i )
415 ASSERT(i < 256); /* must be a byte */
416 insertInstrs(&(bco->is),i);
419 static void asmPtr( AsmBCO bco, AsmObject x )
421 insertPtrs( &bco->object.ptrs, x );
424 static void asmWord( AsmBCO bco, StgWord i )
426 insertNonPtrs( &bco->nps, i );
429 #define asmWords(bco,ty,x) \
431 union { ty a; AsmWord b[sizeofW(ty)]; } p; \
434 for( i = 0; i < sizeofW(ty); i++ ) { \
435 asmWord(bco,p.b[i]); \
439 static StgWord repSizeW( AsmRep rep )
442 case CHAR_REP: return sizeofW(StgWord) + sizeofW(StgChar);
445 case INT_REP: return sizeofW(StgWord) + sizeofW(StgInt);
447 case INT64_REP: return sizeofW(StgWord) + sizeofW(StgInt64);
450 case WORD_REP: return sizeofW(StgWord) + sizeofW(StgWord);
453 case ADDR_REP: return sizeofW(StgWord) + sizeofW(StgAddr);
455 case FLOAT_REP: return sizeofW(StgWord) + sizeofW(StgFloat);
456 case DOUBLE_REP: return sizeofW(StgWord) + sizeofW(StgDouble);
457 #ifdef PROVIDE_STABLE
458 case STABLE_REP: return sizeofW(StgWord) + sizeofW(StgWord);
461 #ifdef PROVIDE_INTEGER
467 #ifdef PROVIDE_FOREIGN
470 case ALPHA_REP: /* a */
471 case BETA_REP: /* b */
472 case GAMMA_REP: /* c */
473 case HANDLER_REP: /* IOError -> IO a */
474 case ERROR_REP: /* IOError */
476 case ARR_REP : /* PrimArray a */
477 case BARR_REP : /* PrimByteArray a */
478 case REF_REP : /* Ref s a */
479 case MUTARR_REP : /* PrimMutableArray s a */
480 case MUTBARR_REP: /* PrimMutableByteArray s a */
482 #ifdef PROVIDE_CONCURRENT
483 case THREADID_REP: /* ThreadId */
484 case MVAR_REP: /* MVar a */
486 case PTR_REP: return sizeofW(StgPtr);
488 case VOID_REP: return sizeofW(StgWord);
489 default: barf("repSizeW %d",rep);
493 /* --------------------------------------------------------------------------
495 * ------------------------------------------------------------------------*/
497 AsmSp asmBeginArgCheck ( AsmBCO bco )
499 ASSERT(bco->sp == 0);
503 void asmEndArgCheck ( AsmBCO bco, AsmSp last_arg )
505 nat args = bco->sp - last_arg;
506 if (args != 0) { /* optimisation */
507 asmInstr(bco,i_ARG_CHECK);
509 grabHpNonUpd(bco,PAP_sizeW(args-1));
514 /* --------------------------------------------------------------------------
515 * Creating and using "variables"
516 * ------------------------------------------------------------------------*/
518 AsmVar asmBind ( AsmBCO bco, AsmRep rep )
520 bco->sp += repSizeW(rep);
524 void asmVar ( AsmBCO bco, AsmVar v, AsmRep rep )
529 asmInstr(bco,i_VAR_INT);
533 asmInstr(bco,i_VAR_INT64);
538 asmInstr(bco,i_VAR_WORD);
543 asmInstr(bco,i_VAR_ADDR);
547 asmInstr(bco,i_VAR_CHAR);
550 asmInstr(bco,i_VAR_FLOAT);
553 asmInstr(bco,i_VAR_DOUBLE);
555 #ifdef PROVIDE_STABLE
557 asmInstr(bco,i_VAR_STABLE);
561 #ifdef PROVIDE_INTEGER
567 #ifdef PROVIDE_FOREIGN
570 case ALPHA_REP: /* a */
571 case BETA_REP: /* b */
572 case GAMMA_REP: /* c */
573 case HANDLER_REP: /* IOError -> IO a */
574 case ERROR_REP: /* IOError */
576 case ARR_REP : /* PrimArray a */
577 case BARR_REP : /* PrimByteArray a */
578 case REF_REP : /* Ref s a */
579 case MUTARR_REP : /* PrimMutableArray s a */
580 case MUTBARR_REP: /* PrimMutableByteArray s a */
582 #ifdef PROVIDE_CONCURRENT
583 case THREADID_REP: /* ThreadId */
584 case MVAR_REP: /* MVar a */
591 asmInstr(bco,i_VOID);
592 bco->sp += repSizeW(rep);
593 return; /* NB we don't break! */
595 barf("asmVar %d",rep);
597 asmInstr(bco,bco->sp - v);
598 bco->sp += repSizeW(rep);
601 /* --------------------------------------------------------------------------
603 * ------------------------------------------------------------------------*/
605 AsmSp asmBeginEnter( AsmBCO bco )
610 void asmEndEnter( AsmBCO bco, AsmSp sp1, AsmSp sp2 )
612 int x = bco->sp - sp1;
614 ASSERT(x >= 0 && y >= 0);
616 asmInstr(bco,i_SLIDE);
619 bco->sp -= sp1 - sp2;
621 asmInstr(bco,i_ENTER);
624 /* --------------------------------------------------------------------------
625 * Build boxed Ints, Floats, etc
626 * ------------------------------------------------------------------------*/
628 AsmVar asmBox( AsmBCO bco, AsmRep rep )
632 asmInstr(bco,i_PACK_CHAR);
633 grabHpNonUpd(bco,Czh_sizeW);
636 asmInstr(bco,i_PACK_INT);
637 grabHpNonUpd(bco,Izh_sizeW);
641 asmInstr(bco,i_PACK_INT64);
642 grabHpNonUpd(bco,I64zh_sizeW);
647 asmInstr(bco,i_PACK_WORD);
648 grabHpNonUpd(bco,Wzh_sizeW);
653 asmInstr(bco,i_PACK_ADDR);
654 grabHpNonUpd(bco,Azh_sizeW);
658 asmInstr(bco,i_PACK_FLOAT);
659 grabHpNonUpd(bco,Fzh_sizeW);
662 asmInstr(bco,i_PACK_DOUBLE);
663 grabHpNonUpd(bco,Dzh_sizeW);
665 #ifdef PROVIDE_STABLE
667 asmInstr(bco,i_PACK_STABLE);
668 grabHpNonUpd(bco,Stablezh_sizeW);
673 barf("asmBox %d",rep);
675 /* NB: these operations DO pop their arg */
676 bco->sp -= repSizeW(rep); /* pop unboxed arg */
677 bco->sp += sizeofW(StgPtr); /* push box */
681 /* --------------------------------------------------------------------------
682 * Unbox Ints, Floats, etc
683 * ------------------------------------------------------------------------*/
685 AsmVar asmUnbox( AsmBCO bco, AsmRep rep )
689 asmInstr(bco,i_UNPACK_INT);
693 asmInstr(bco,i_UNPACK_INT64);
698 asmInstr(bco,i_UNPACK_WORD);
703 asmInstr(bco,i_UNPACK_ADDR);
707 asmInstr(bco,i_UNPACK_CHAR);
710 asmInstr(bco,i_UNPACK_FLOAT);
713 asmInstr(bco,i_UNPACK_DOUBLE);
716 asmInstr(bco,i_UNPACK_STABLE);
720 barf("asmUnbox %d",rep);
722 /* NB: these operations DO NOT pop their arg */
723 bco->sp += repSizeW(rep); /* push unboxed arg */
727 /* --------------------------------------------------------------------------
728 * Return unboxed Ints, Floats, etc
729 * ------------------------------------------------------------------------*/
731 void asmReturnUnboxed( AsmBCO bco, AsmRep rep )
735 asmInstr(bco,i_RETURN_CHAR);
738 asmInstr(bco,i_RETURN_INT);
742 asmInstr(bco,i_RETURN_INT64);
747 asmInstr(bco,i_RETURN_WORD);
752 asmInstr(bco,i_RETURN_ADDR);
756 asmInstr(bco,i_RETURN_FLOAT);
759 asmInstr(bco,i_RETURN_DOUBLE);
761 #ifdef PROVIDE_STABLE
763 asmInstr(bco,i_RETURN_STABLE);
766 #ifdef PROVIDE_INTEGER
772 #ifdef PROVIDE_FOREIGN
776 case ARR_REP : /* PrimArray a */
777 case BARR_REP : /* PrimByteArray a */
778 case REF_REP : /* Ref s a */
779 case MUTARR_REP : /* PrimMutableArray s a */
780 case MUTBARR_REP: /* PrimMutableByteArray s a */
782 #ifdef PROVIDE_CONCURRENT
783 case THREADID_REP: /* ThreadId */
784 case MVAR_REP: /* MVar a */
786 asmInstr(bco,i_RETURN_GENERIC);
789 barf("asmReturnUnboxed %d",rep);
793 /* --------------------------------------------------------------------------
794 * Push unboxed Ints, Floats, etc
795 * ------------------------------------------------------------------------*/
797 void asmConstInt( AsmBCO bco, AsmInt x )
799 asmInstr(bco,i_CONST_INT);
800 asmInstr(bco,bco->nps.len);
801 asmWords(bco,AsmInt,x);
802 bco->sp += repSizeW(INT_REP);
806 void asmConstInt64( AsmBCO bco, AsmInt64 x )
808 asmInstr(bco,i_CONST_INT64);
809 asmInstr(bco,bco->nps.len);
810 asmWords(bco,AsmInt64,x);
811 bco->sp += repSizeW(INT64_REP);
815 #ifdef PROVIDE_INTEGER
816 void asmConstInteger( AsmBCO bco, AsmString x )
818 asmInstr(bco,i_CONST_INTEGER);
819 asmInstr(bco,bco->nps.len);
820 asmWords(bco,AsmString,x);
821 bco->sp += repSizeW(INTEGER_REP);
826 void asmConstAddr( AsmBCO bco, AsmAddr x )
828 asmInstr(bco,i_CONST_ADDR);
829 asmInstr(bco,bco->nps.len);
830 asmWords(bco,AsmAddr,x);
831 bco->sp += repSizeW(ADDR_REP);
836 void asmConstWord( AsmBCO bco, AsmWord x )
838 asmInstr(bco,i_CONST_INT);
839 asmInstr(bco,bco->nps.len);
840 asmWords(bco,AsmWord,x);
841 bco->sp += repSizeW(WORD_REP);
845 void asmConstChar( AsmBCO bco, AsmChar x )
847 asmInstr(bco,i_CONST_CHAR);
848 asmInstr(bco,bco->nps.len);
849 asmWords(bco,AsmChar,x);
850 bco->sp += repSizeW(CHAR_REP);
853 void asmConstFloat( AsmBCO bco, AsmFloat x )
855 asmInstr(bco,i_CONST_FLOAT);
856 asmInstr(bco,bco->nps.len);
857 asmWords(bco,AsmFloat,x);
858 bco->sp += repSizeW(FLOAT_REP);
861 void asmConstDouble( AsmBCO bco, AsmDouble x )
863 asmInstr(bco,i_CONST_DOUBLE);
864 asmInstr(bco,bco->nps.len);
865 asmWords(bco,AsmDouble,x);
866 bco->sp += repSizeW(DOUBLE_REP);
869 /* --------------------------------------------------------------------------
871 * ------------------------------------------------------------------------*/
873 /* a mildly bogus pair of functions... */
874 AsmSp asmBeginCase( AsmBCO bco )
879 void asmEndCase( AsmBCO bco )
883 AsmSp asmContinuation( AsmBCO bco, AsmBCO ret_addr )
885 asmInstr(bco,i_RETADDR);
886 asmInstr(bco,bco->object.ptrs.len);
887 asmPtr(bco,&(ret_addr->object));
888 bco->sp += 2 * sizeofW(StgPtr);
892 AsmBCO asmBeginContinuation ( AsmSp sp )
894 AsmBCO bco = asmBeginBCO();
899 void asmEndContinuation ( AsmBCO bco )
904 /* --------------------------------------------------------------------------
906 * ------------------------------------------------------------------------*/
908 AsmSp asmBeginAlt( AsmBCO bco )
913 void asmEndAlt( AsmBCO bco, AsmSp sp )
916 /* This warning is now redundant since we no longer use the hp/max_hp
917 * information calculated by the assembler
919 #warning ToDo: adjust hp/max_hp in asmEndAlt
924 AsmPc asmTest( AsmBCO bco, AsmWord tag )
926 asmInstr(bco,i_TEST);
932 AsmPc asmTestInt( AsmBCO bco, AsmVar v, AsmInt x )
934 asmVar(bco,v,INT_REP);
936 asmInstr(bco,i_TEST_INT);
938 bco->sp -= 2*repSizeW(INT_REP);
942 void asmFixBranch( AsmBCO bco, AsmPc from )
944 int distance = bco->is.len - from;
945 ASSERT(distance >= 0);
946 setInstrs(&(bco->is),from-1,distance);
949 void asmPanic( AsmBCO bco )
951 asmInstr(bco,i_PANIC); /* "irrefutable" pattern failed - oops! */
954 /* --------------------------------------------------------------------------
956 * ------------------------------------------------------------------------*/
958 AsmSp asmBeginPrim( AsmBCO bco )
963 void asmEndPrim( AsmBCO bco, const AsmPrim* prim, AsmSp base )
965 asmInstr(bco,prim->prefix);
966 asmInstr(bco,prim->opcode);
970 /* Hugs used to let you add arbitrary primops with arbitrary types
971 * just by editing Prelude.hs or any other file you wanted.
972 * We deliberately avoided that approach because we wanted more
973 * control over which primops are provided.
975 const AsmPrim asmPrimOps[] = {
977 /* Char# operations */
978 { "primGtChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_gtChar }
979 , { "primGeChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_geChar }
980 , { "primEqChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_eqChar }
981 , { "primNeChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_neChar }
982 , { "primLtChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_ltChar }
983 , { "primLeChar", "CC", "B", MONAD_Id, i_PRIMOP1, i_leChar }
984 , { "primCharToInt", "C", "I", MONAD_Id, i_PRIMOP1, i_charToInt }
985 , { "primIntToChar", "I", "C", MONAD_Id, i_PRIMOP1, i_intToChar }
987 /* Int# operations */
988 , { "primGtInt", "II", "B", MONAD_Id, i_PRIMOP1, i_gtInt }
989 , { "primGeInt", "II", "B", MONAD_Id, i_PRIMOP1, i_geInt }
990 , { "primEqInt", "II", "B", MONAD_Id, i_PRIMOP1, i_eqInt }
991 , { "primNeInt", "II", "B", MONAD_Id, i_PRIMOP1, i_neInt }
992 , { "primLtInt", "II", "B", MONAD_Id, i_PRIMOP1, i_ltInt }
993 , { "primLeInt", "II", "B", MONAD_Id, i_PRIMOP1, i_leInt }
994 , { "primMinInt", "", "I", MONAD_Id, i_PRIMOP1, i_minInt }
995 , { "primMaxInt", "", "I", MONAD_Id, i_PRIMOP1, i_maxInt }
996 , { "primPlusInt", "II", "I", MONAD_Id, i_PRIMOP1, i_plusInt }
997 , { "primMinusInt", "II", "I", MONAD_Id, i_PRIMOP1, i_minusInt }
998 , { "primTimesInt", "II", "I", MONAD_Id, i_PRIMOP1, i_timesInt }
999 , { "primQuotInt", "II", "I", MONAD_Id, i_PRIMOP1, i_quotInt }
1000 , { "primRemInt", "II", "I", MONAD_Id, i_PRIMOP1, i_remInt }
1001 , { "primQuotRemInt", "II", "II", MONAD_Id, i_PRIMOP1, i_quotRemInt }
1002 , { "primNegateInt", "I", "I", MONAD_Id, i_PRIMOP1, i_negateInt }
1004 , { "primAndInt", "II", "I", MONAD_Id, i_PRIMOP1, i_andInt }
1005 , { "primOrInt", "II", "I", MONAD_Id, i_PRIMOP1, i_orInt }
1006 , { "primXorInt", "II", "I", MONAD_Id, i_PRIMOP1, i_xorInt }
1007 , { "primNotInt", "I", "I", MONAD_Id, i_PRIMOP1, i_notInt }
1008 , { "primShiftLInt", "IW", "I", MONAD_Id, i_PRIMOP1, i_shiftLInt }
1009 , { "primShiftRAInt", "IW", "I", MONAD_Id, i_PRIMOP1, i_shiftRAInt }
1010 , { "primShiftRLInt", "IW", "I", MONAD_Id, i_PRIMOP1, i_shiftRLInt }
1012 #ifdef PROVIDE_INT64
1013 /* Int64# operations */
1014 , { "primGtInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_gtInt64 }
1015 , { "primGeInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_geInt64 }
1016 , { "primEqInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_eqInt64 }
1017 , { "primNeInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_neInt64 }
1018 , { "primLtInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_ltInt64 }
1019 , { "primLeInt64", "zz", "B", MONAD_Id, i_PRIMOP1, i_leInt64 }
1020 , { "primMinInt64", "", "z", MONAD_Id, i_PRIMOP1, i_minInt64 }
1021 , { "primMaxInt64", "", "z", MONAD_Id, i_PRIMOP1, i_maxInt64 }
1022 , { "primPlusInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_plusInt64 }
1023 , { "primMinusInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_minusInt64 }
1024 , { "primTimesInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_timesInt64 }
1025 , { "primQuotInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_quotInt64 }
1026 , { "primRemInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_remInt64 }
1027 , { "primQuotRemInt64", "zz", "zz", MONAD_Id, i_PRIMOP1, i_quotRemInt64 }
1028 , { "primNegateInt64", "z", "z", MONAD_Id, i_PRIMOP1, i_negateInt64 }
1030 , { "primAndInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_andInt64 }
1031 , { "primOrInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_orInt64 }
1032 , { "primXorInt64", "zz", "z", MONAD_Id, i_PRIMOP1, i_xorInt64 }
1033 , { "primNotInt64", "z", "z", MONAD_Id, i_PRIMOP1, i_notInt64 }
1034 , { "primShiftLInt64", "zW", "z", MONAD_Id, i_PRIMOP1, i_shiftLInt64 }
1035 , { "primShiftRAInt64", "zW", "z", MONAD_Id, i_PRIMOP1, i_shiftRAInt64 }
1036 , { "primShiftRLInt64", "zW", "z", MONAD_Id, i_PRIMOP1, i_shiftRLInt64 }
1038 , { "primInt64ToInt", "z", "I", MONAD_Id, i_PRIMOP1, i_int64ToInt }
1039 , { "primIntToInt64", "I", "z", MONAD_Id, i_PRIMOP1, i_intToInt64 }
1041 , { "primInt64ToWord", "z", "W", MONAD_Id, i_PRIMOP1, i_int64ToWord }
1042 , { "primWordToInt64", "W", "z", MONAD_Id, i_PRIMOP1, i_wordToInt64 }
1044 , { "primInt64ToFloat", "z", "F", MONAD_Id, i_PRIMOP1, i_int64ToFloat }
1045 , { "primFloatToInt64", "F", "z", MONAD_Id, i_PRIMOP1, i_floatToInt64 }
1046 , { "primInt64ToDouble", "z", "D", MONAD_Id, i_PRIMOP1, i_int64ToDouble }
1047 , { "primDoubleToInt64", "D", "z", MONAD_Id, i_PRIMOP1, i_doubleToInt64 }
1051 /* Word# operations */
1052 , { "primGtWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_gtWord }
1053 , { "primGeWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_geWord }
1054 , { "primEqWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_eqWord }
1055 , { "primNeWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_neWord }
1056 , { "primLtWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_ltWord }
1057 , { "primLeWord", "WW", "B", MONAD_Id, i_PRIMOP1, i_leWord }
1058 , { "primMinWord", "", "W", MONAD_Id, i_PRIMOP1, i_minWord }
1059 , { "primMaxWord", "", "W", MONAD_Id, i_PRIMOP1, i_maxWord }
1060 , { "primPlusWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_plusWord }
1061 , { "primMinusWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_minusWord }
1062 , { "primTimesWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_timesWord }
1063 , { "primQuotWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_quotWord }
1064 , { "primRemWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_remWord }
1065 , { "primQuotRemWord", "WW", "WW", MONAD_Id, i_PRIMOP1, i_quotRemWord }
1066 , { "primNegateWord", "W", "W", MONAD_Id, i_PRIMOP1, i_negateWord }
1068 , { "primAndWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_andWord }
1069 , { "primOrWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_orWord }
1070 , { "primXorWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_xorWord }
1071 , { "primNotWord", "W", "W", MONAD_Id, i_PRIMOP1, i_notWord }
1072 , { "primShiftLWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_shiftLWord }
1073 , { "primShiftRAWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_shiftRAWord }
1074 , { "primShiftRLWord", "WW", "W", MONAD_Id, i_PRIMOP1, i_shiftRLWord }
1076 , { "primIntToWord", "I", "W", MONAD_Id, i_PRIMOP1, i_intToWord }
1077 , { "primWordToInt", "W", "I", MONAD_Id, i_PRIMOP1, i_wordToInt }
1081 /* Addr# operations */
1082 , { "primGtAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_gtAddr }
1083 , { "primGeAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_geAddr }
1084 , { "primEqAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_eqAddr }
1085 , { "primNeAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_neAddr }
1086 , { "primLtAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_ltAddr }
1087 , { "primLeAddr", "AA", "B", MONAD_Id, i_PRIMOP1, i_leAddr }
1088 , { "primIntToAddr", "I", "A", MONAD_Id, i_PRIMOP1, i_intToAddr }
1089 , { "primAddrToInt", "A", "I", MONAD_Id, i_PRIMOP1, i_addrToInt }
1091 , { "primIndexCharOffAddr", "AI", "C", MONAD_Id, i_PRIMOP1, i_indexCharOffAddr }
1092 , { "primIndexIntOffAddr", "AI", "I", MONAD_Id, i_PRIMOP1, i_indexIntOffAddr }
1093 #ifdef PROVIDE_INT64
1094 , { "primIndexInt64OffAddr", "AI", "z", MONAD_Id, i_PRIMOP1, i_indexInt64OffAddr }
1096 , { "primIndexWordOffAddr", "AI", "W", MONAD_Id, i_PRIMOP1, i_indexWordOffAddr }
1097 , { "primIndexAddrOffAddr", "AI", "A", MONAD_Id, i_PRIMOP1, i_indexAddrOffAddr }
1098 , { "primIndexFloatOffAddr", "AI", "F", MONAD_Id, i_PRIMOP1, i_indexFloatOffAddr }
1099 , { "primIndexDoubleOffAddr", "AI", "D", MONAD_Id, i_PRIMOP1, i_indexDoubleOffAddr }
1100 #ifdef PROVIDE_STABLE
1101 , { "primIndexStableOffAddr", "AI", "s", MONAD_Id, i_PRIMOP1, i_indexStableOffAddr }
1104 /* These ops really ought to be in the IO monad */
1105 , { "primReadCharOffAddr", "AI", "C", MONAD_ST, i_PRIMOP1, i_readCharOffAddr }
1106 , { "primReadIntOffAddr", "AI", "I", MONAD_ST, i_PRIMOP1, i_readIntOffAddr }
1107 #ifdef PROVIDE_INT64
1108 , { "primReadInt64OffAddr", "AI", "z", MONAD_ST, i_PRIMOP1, i_readInt64OffAddr }
1110 , { "primReadWordOffAddr", "AI", "W", MONAD_ST, i_PRIMOP1, i_readWordOffAddr }
1111 , { "primReadAddrOffAddr", "AI", "A", MONAD_ST, i_PRIMOP1, i_readAddrOffAddr }
1112 , { "primReadFloatOffAddr", "AI", "F", MONAD_ST, i_PRIMOP1, i_readFloatOffAddr }
1113 , { "primReadDoubleOffAddr", "AI", "D", MONAD_ST, i_PRIMOP1, i_readDoubleOffAddr }
1114 #ifdef PROVIDE_STABLE
1115 , { "primReadStableOffAddr", "AI", "s", MONAD_ST, i_PRIMOP1, i_readStableOffAddr }
1118 /* These ops really ought to be in the IO monad */
1119 , { "primWriteCharOffAddr", "AIC", "", MONAD_ST, i_PRIMOP1, i_writeCharOffAddr }
1120 , { "primWriteIntOffAddr", "AII", "", MONAD_ST, i_PRIMOP1, i_writeIntOffAddr }
1121 #ifdef PROVIDE_INT64
1122 , { "primWriteInt64OffAddr", "AIz", "", MONAD_ST, i_PRIMOP1, i_writeInt64OffAddr }
1124 , { "primWriteWordOffAddr", "AIW", "", MONAD_ST, i_PRIMOP1, i_writeWordOffAddr }
1125 , { "primWriteAddrOffAddr", "AIA", "", MONAD_ST, i_PRIMOP1, i_writeAddrOffAddr }
1126 , { "primWriteFloatOffAddr", "AIF", "", MONAD_ST, i_PRIMOP1, i_writeFloatOffAddr }
1127 , { "primWriteDoubleOffAddr", "AID", "", MONAD_ST, i_PRIMOP1, i_writeDoubleOffAddr }
1128 #ifdef PROVIDE_STABLE
1129 , { "primWriteStableOffAddr", "AIs", "", MONAD_ST, i_PRIMOP1, i_writeStableOffAddr }
1132 #endif /* PROVIDE_ADDR */
1134 #ifdef PROVIDE_INTEGER
1135 /* Integer operations */
1136 , { "primCompareInteger", "ZZ", "I", MONAD_Id, i_PRIMOP1, i_compareInteger }
1137 , { "primNegateInteger", "Z", "Z", MONAD_Id, i_PRIMOP1, i_negateInteger }
1138 , { "primPlusInteger", "ZZ", "Z", MONAD_Id, i_PRIMOP1, i_plusInteger }
1139 , { "primMinusInteger", "ZZ", "Z", MONAD_Id, i_PRIMOP1, i_minusInteger }
1140 , { "primTimesInteger", "ZZ", "Z", MONAD_Id, i_PRIMOP1, i_timesInteger }
1141 , { "primQuotRemInteger", "ZZ", "ZZ", MONAD_Id, i_PRIMOP1, i_quotRemInteger }
1142 , { "primDivModInteger", "ZZ", "ZZ", MONAD_Id, i_PRIMOP1, i_divModInteger }
1143 , { "primIntegerToInt", "Z", "I", MONAD_Id, i_PRIMOP1, i_integerToInt }
1144 , { "primIntToInteger", "I", "Z", MONAD_Id, i_PRIMOP1, i_intToInteger }
1145 , { "primIntegerToInt64", "Z", "z", MONAD_Id, i_PRIMOP1, i_integerToInt64 }
1146 , { "primInt64ToInteger", "z", "Z", MONAD_Id, i_PRIMOP1, i_int64ToInteger }
1148 , { "primIntegerToWord", "Z", "W", MONAD_Id, i_PRIMOP1, i_integerToWord }
1149 , { "primWordToInteger", "W", "Z", MONAD_Id, i_PRIMOP1, i_wordToInteger }
1151 , { "primIntegerToFloat", "Z", "F", MONAD_Id, i_PRIMOP1, i_integerToFloat }
1152 , { "primFloatToInteger", "F", "Z", MONAD_Id, i_PRIMOP1, i_floatToInteger }
1153 , { "primIntegerToDouble", "Z", "D", MONAD_Id, i_PRIMOP1, i_integerToDouble }
1154 , { "primDoubleToInteger", "D", "Z", MONAD_Id, i_PRIMOP1, i_doubleToInteger }
1157 /* Float# operations */
1158 , { "primGtFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_gtFloat }
1159 , { "primGeFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_geFloat }
1160 , { "primEqFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_eqFloat }
1161 , { "primNeFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_neFloat }
1162 , { "primLtFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_ltFloat }
1163 , { "primLeFloat", "FF", "B", MONAD_Id, i_PRIMOP1, i_leFloat }
1164 , { "primMinFloat", "", "F", MONAD_Id, i_PRIMOP1, i_minFloat }
1165 , { "primMaxFloat", "", "F", MONAD_Id, i_PRIMOP1, i_maxFloat }
1166 , { "primRadixFloat", "", "I", MONAD_Id, i_PRIMOP1, i_radixFloat }
1167 , { "primDigitsFloat", "", "I", MONAD_Id, i_PRIMOP1, i_digitsFloat }
1168 , { "primMinExpFloat", "", "I", MONAD_Id, i_PRIMOP1, i_minExpFloat }
1169 , { "primMaxExpFloat", "", "I", MONAD_Id, i_PRIMOP1, i_maxExpFloat }
1170 , { "primPlusFloat", "FF", "F", MONAD_Id, i_PRIMOP1, i_plusFloat }
1171 , { "primMinusFloat", "FF", "F", MONAD_Id, i_PRIMOP1, i_minusFloat }
1172 , { "primTimesFloat", "FF", "F", MONAD_Id, i_PRIMOP1, i_timesFloat }
1173 , { "primDivideFloat", "FF", "F", MONAD_Id, i_PRIMOP1, i_divideFloat }
1174 , { "primNegateFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_negateFloat }
1175 , { "primFloatToInt", "F", "I", MONAD_Id, i_PRIMOP1, i_floatToInt }
1176 , { "primIntToFloat", "I", "F", MONAD_Id, i_PRIMOP1, i_intToFloat }
1177 , { "primExpFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_expFloat }
1178 , { "primLogFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_logFloat }
1179 , { "primSqrtFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_sqrtFloat }
1180 , { "primSinFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_sinFloat }
1181 , { "primCosFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_cosFloat }
1182 , { "primTanFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_tanFloat }
1183 , { "primAsinFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_asinFloat }
1184 , { "primAcosFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_acosFloat }
1185 , { "primAtanFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_atanFloat }
1186 , { "primSinhFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_sinhFloat }
1187 , { "primCoshFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_coshFloat }
1188 , { "primTanhFloat", "F", "F", MONAD_Id, i_PRIMOP1, i_tanhFloat }
1189 , { "primPowerFloat", "FF", "F", MONAD_Id, i_PRIMOP1, i_powerFloat }
1190 #ifdef PROVIDE_INT64
1191 , { "primDecodeFloatz", "F", "zI", MONAD_Id, i_PRIMOP1, i_decodeFloatz }
1192 , { "primEncodeFloatz", "zI", "F", MONAD_Id, i_PRIMOP1, i_encodeFloatz }
1194 #ifdef PROVIDE_INTEGER
1195 , { "primDecodeFloatZ", "F", "ZI", MONAD_Id, i_PRIMOP1, i_decodeFloatZ }
1196 , { "primEncodeFloatZ", "ZI", "F", MONAD_Id, i_PRIMOP1, i_encodeFloatZ }
1198 , { "primIsNaNFloat", "F", "B", MONAD_Id, i_PRIMOP1, i_isNaNFloat }
1199 , { "primIsInfiniteFloat", "F", "B", MONAD_Id, i_PRIMOP1, i_isInfiniteFloat }
1200 , { "primIsDenormalizedFloat", "F", "B", MONAD_Id, i_PRIMOP1, i_isDenormalizedFloat }
1201 , { "primIsNegativeZeroFloat", "F", "B", MONAD_Id, i_PRIMOP1, i_isNegativeZeroFloat }
1202 , { "primIsIEEEFloat", "", "B", MONAD_Id, i_PRIMOP1, i_isIEEEFloat }
1204 /* Double# operations */
1205 , { "primGtDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_gtDouble }
1206 , { "primGeDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_geDouble }
1207 , { "primEqDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_eqDouble }
1208 , { "primNeDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_neDouble }
1209 , { "primLtDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_ltDouble }
1210 , { "primLeDouble", "DD", "B", MONAD_Id, i_PRIMOP1, i_leDouble }
1211 , { "primMinDouble", "", "D", MONAD_Id, i_PRIMOP1, i_minDouble }
1212 , { "primMaxDouble", "", "D", MONAD_Id, i_PRIMOP1, i_maxDouble }
1213 , { "primRadixDouble", "", "I", MONAD_Id, i_PRIMOP1, i_radixDouble }
1214 , { "primDigitsDouble", "", "I", MONAD_Id, i_PRIMOP1, i_digitsDouble }
1215 , { "primMinExpDouble", "", "I", MONAD_Id, i_PRIMOP1, i_minExpDouble }
1216 , { "primMaxExpDouble", "", "I", MONAD_Id, i_PRIMOP1, i_maxExpDouble }
1217 , { "primPlusDouble", "DD", "D", MONAD_Id, i_PRIMOP1, i_plusDouble }
1218 , { "primMinusDouble", "DD", "D", MONAD_Id, i_PRIMOP1, i_minusDouble }
1219 , { "primTimesDouble", "DD", "D", MONAD_Id, i_PRIMOP1, i_timesDouble }
1220 , { "primDivideDouble", "DD", "D", MONAD_Id, i_PRIMOP1, i_divideDouble }
1221 , { "primNegateDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_negateDouble }
1222 , { "primDoubleToInt", "D", "I", MONAD_Id, i_PRIMOP1, i_doubleToInt }
1223 , { "primIntToDouble", "I", "D", MONAD_Id, i_PRIMOP1, i_intToDouble }
1224 , { "primDoubleToFloat", "D", "F", MONAD_Id, i_PRIMOP1, i_doubleToFloat }
1225 , { "primFloatToDouble", "F", "D", MONAD_Id, i_PRIMOP1, i_floatToDouble }
1226 , { "primExpDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_expDouble }
1227 , { "primLogDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_logDouble }
1228 , { "primSqrtDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_sqrtDouble }
1229 , { "primSinDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_sinDouble }
1230 , { "primCosDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_cosDouble }
1231 , { "primTanDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_tanDouble }
1232 , { "primAsinDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_asinDouble }
1233 , { "primAcosDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_acosDouble }
1234 , { "primAtanDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_atanDouble }
1235 , { "primSinhDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_sinhDouble }
1236 , { "primCoshDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_coshDouble }
1237 , { "primTanhDouble", "D", "D", MONAD_Id, i_PRIMOP1, i_tanhDouble }
1238 , { "primPowerDouble", "DD", "D", MONAD_Id, i_PRIMOP1, i_powerDouble }
1239 #ifdef PROVIDE_INT64
1240 , { "primDecodeDoublez", "D", "zI", MONAD_Id, i_PRIMOP1, i_decodeDoublez }
1241 , { "primEncodeDoublez", "zI", "D", MONAD_Id, i_PRIMOP1, i_encodeDoublez }
1243 #ifdef PROVIDE_INTEGER
1244 , { "primDecodeDoubleZ", "D", "ZI", MONAD_Id, i_PRIMOP1, i_decodeDoubleZ }
1245 , { "primEncodeDoubleZ", "ZI", "D", MONAD_Id, i_PRIMOP1, i_encodeDoubleZ }
1247 , { "primIsNaNDouble", "D", "B", MONAD_Id, i_PRIMOP1, i_isNaNDouble }
1248 , { "primIsInfiniteDouble", "D", "B", MONAD_Id, i_PRIMOP1, i_isInfiniteDouble }
1249 , { "primIsDenormalizedDouble", "D", "B", MONAD_Id, i_PRIMOP1, i_isDenormalizedDouble }
1250 , { "primIsNegativeZeroDouble", "D", "B", MONAD_Id, i_PRIMOP1, i_isNegativeZeroDouble }
1251 , { "primIsIEEEDouble", "", "B", MONAD_Id, i_PRIMOP1, i_isIEEEDouble }
1254 /* Polymorphic force :: a -> (# #) */
1255 , { "primForce", "a", "", MONAD_Id, i_PRIMOP2, i_force }
1257 /* Error operations - not in IO monad! */
1258 , { "primRaise", "E", "a", MONAD_Id, i_PRIMOP2, i_raise }
1259 , { "primCatch'", "aH", "a", MONAD_Id, i_PRIMOP2, i_catch }
1261 #ifdef PROVIDE_ARRAY
1262 /* Ref operations */
1263 , { "primNewRef", "a", "R", MONAD_ST, i_PRIMOP2, i_newRef }
1264 , { "primWriteRef", "Ra", "", MONAD_ST, i_PRIMOP2, i_writeRef }
1265 , { "primReadRef", "R", "a", MONAD_ST, i_PRIMOP2, i_readRef }
1266 , { "primSameRef", "RR", "B", MONAD_Id, i_PRIMOP2, i_sameRef }
1268 /* PrimArray operations */
1269 , { "primSameMutableArray", "MM", "B", MONAD_Id, i_PRIMOP2, i_sameMutableArray }
1270 , { "primUnsafeFreezeArray", "M", "X", MONAD_ST, i_PRIMOP2, i_unsafeFreezeArray }
1271 , { "primNewArray", "Ia", "M", MONAD_ST, i_PRIMOP2, i_newArray }
1272 , { "primWriteArray", "MIa", "", MONAD_ST, i_PRIMOP2, i_writeArray }
1273 , { "primReadArray", "MI", "a", MONAD_ST, i_PRIMOP2, i_readArray }
1274 , { "primIndexArray", "XI", "a", MONAD_Id, i_PRIMOP2, i_indexArray }
1275 , { "primSizeArray", "X", "I", MONAD_Id, i_PRIMOP2, i_sizeArray }
1276 , { "primSizeMutableArray", "M", "I", MONAD_Id, i_PRIMOP2, i_sizeMutableArray }
1278 /* Prim[Mutable]ByteArray operations */
1279 , { "primSameMutableByteArray", "mm", "B", MONAD_Id, i_PRIMOP2, i_sameMutableByteArray }
1280 , { "primUnsafeFreezeByteArray", "m", "x", MONAD_ST, i_PRIMOP2, i_unsafeFreezeByteArray }
1282 , { "primNewByteArray", "I", "m", MONAD_ST, i_PRIMOP2, i_newByteArray }
1284 , { "primWriteCharArray", "mIC", "", MONAD_ST, i_PRIMOP2, i_writeCharArray }
1285 , { "primReadCharArray", "mI", "C", MONAD_ST, i_PRIMOP2, i_readCharArray }
1286 , { "primIndexCharArray", "xI", "C", MONAD_Id, i_PRIMOP2, i_indexCharArray }
1288 , { "primWriteIntArray", "mII", "", MONAD_ST, i_PRIMOP2, i_writeIntArray }
1289 , { "primReadIntArray", "mI", "I", MONAD_ST, i_PRIMOP2, i_readIntArray }
1290 , { "primIndexIntArray", "xI", "I", MONAD_Id, i_PRIMOP2, i_indexIntArray }
1292 #ifdef PROVIDE_INT64
1293 , { "primWriteInt64Array", "mIz", "", MONAD_ST, i_PRIMOP2, i_writeInt64Array }
1294 , { "primReadInt64Array", "mI", "z", MONAD_ST, i_PRIMOP2, i_readInt64Array }
1295 , { "primIndexInt64Array", "xI", "z", MONAD_Id, i_PRIMOP2, i_indexInt64Array }
1298 /* {new,write,read,index}IntegerArray not provided */
1301 , { "primWriteWordArray", "mIW", "", MONAD_ST, i_PRIMOP2, i_writeWordArray }
1302 , { "primReadWordArray", "mI", "W", MONAD_ST, i_PRIMOP2, i_readWordArray }
1303 , { "primIndexWordArray", "xI", "W", MONAD_Id, i_PRIMOP2, i_indexWordArray }
1306 , { "primWriteAddrArray", "mIA", "", MONAD_ST, i_PRIMOP2, i_writeAddrArray }
1307 , { "primReadAddrArray", "mI", "A", MONAD_ST, i_PRIMOP2, i_readAddrArray }
1308 , { "primIndexAddrArray", "xI", "A", MONAD_Id, i_PRIMOP2, i_indexAddrArray }
1310 , { "primWriteFloatArray", "mIF", "", MONAD_ST, i_PRIMOP2, i_writeFloatArray }
1311 , { "primReadFloatArray", "mI", "F", MONAD_ST, i_PRIMOP2, i_readFloatArray }
1312 , { "primIndexFloatArray", "xI", "F", MONAD_Id, i_PRIMOP2, i_indexFloatArray }
1314 , { "primWriteDoubleArray" , "mID", "", MONAD_ST, i_PRIMOP2, i_writeDoubleArray }
1315 , { "primReadDoubleArray", "mI", "D", MONAD_ST, i_PRIMOP2, i_readDoubleArray }
1316 , { "primIndexDoubleArray", "xI", "D", MONAD_Id, i_PRIMOP2, i_indexDoubleArray }
1318 #ifdef PROVIDE_STABLE
1319 , { "primWriteStableArray", "mIs", "", MONAD_ST, i_PRIMOP2, i_writeStableArray }
1320 , { "primReadStableArray", "mI", "s", MONAD_ST, i_PRIMOP2, i_readStableArray }
1321 , { "primIndexStableArray", "xI", "s", MONAD_Id, i_PRIMOP2, i_indexStableArray }
1324 /* {new,write,read,index}ForeignObjArray not provided */
1326 #endif PROVIDE_ARRAY
1328 #ifdef PROVIDE_FOREIGN
1329 /* ForeignObj# operations */
1330 , { "primMakeForeignObj", "A", "f", MONAD_IO, i_PRIMOP2, i_makeForeignObj }
1333 /* WeakPair# operations */
1334 , { "primMakeWeak", "bac", "w", MONAD_IO, i_PRIMOP2, i_makeWeak }
1335 , { "primDeRefWeak", "w", "Ia", MONAD_IO, i_PRIMOP2, i_deRefWeak }
1337 #ifdef PROVIDE_STABLE
1338 /* StablePtr# operations */
1339 , { "primMakeStablePtr", "a", "s", MONAD_IO, i_PRIMOP2, i_makeStablePtr }
1340 , { "primDeRefStablePtr", "s", "a", MONAD_IO, i_PRIMOP2, i_deRefStablePtr }
1341 , { "primFreeStablePtr", "s", "", MONAD_IO, i_PRIMOP2, i_freeStablePtr }
1343 #ifdef PROVIDE_PTREQUALITY
1344 , { "primReallyUnsafePtrEquality", "aa", "B",MONAD_Id, i_PRIMOP2, i_reallyUnsafePtrEquality }
1346 #ifdef PROVIDE_COERCE
1347 , { "primUnsafeCoerce", "a", "b", MONAD_Id, i_PRIMOP2, i_unsafeCoerce }
1349 #ifdef PROVIDE_CONCURRENT
1350 /* Concurrency operations */
1351 , { "primFork", "a", "T", MONAD_IO, i_PRIMOP2, i_fork }
1352 , { "primKillThread", "T", "", MONAD_IO, i_PRIMOP2, i_killThread }
1353 , { "primSameMVar", "rr", "B", MONAD_Id, i_PRIMOP2, i_sameMVar }
1354 , { "primNewMVar", "", "r", MONAD_IO, i_PRIMOP2, i_newMVar }
1355 , { "primTakeMVar", "r", "a", MONAD_IO, i_PRIMOP2, i_takeMVar }
1356 , { "primPutMVar", "ra", "", MONAD_IO, i_PRIMOP2, i_putMVar }
1357 , { "primDelay", "I", "", MONAD_IO, i_PRIMOP2, i_delay }
1358 , { "primWaitRead", "I", "", MONAD_IO, i_PRIMOP2, i_waitRead }
1359 , { "primWaitWrite", "I", "", MONAD_IO, i_PRIMOP2, i_waitWrite }
1362 /* Ccall is polyadic - so it's excluded from this table */
1367 const AsmPrim ccall_Id = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_Id };
1368 const AsmPrim ccall_IO = { "ccall", 0, 0, MONAD_IO, i_PRIMOP2, i_ccall_IO };
1370 const AsmPrim* asmFindPrim( char* s )
1373 for (i=0; asmPrimOps[i].name; ++i) {
1374 if (strcmp(s,asmPrimOps[i].name)==0) {
1375 return &asmPrimOps[i];
1381 const AsmPrim* asmFindPrimop( AsmInstr prefix, AsmInstr op )
1384 for (i=0; asmPrimOps[i].name; ++i) {
1385 if (asmPrimOps[i].prefix == prefix && asmPrimOps[i].opcode == op) {
1386 return &asmPrimOps[i];
1392 /* --------------------------------------------------------------------------
1394 * ------------------------------------------------------------------------*/
1396 AsmVar asmAllocCONSTR ( AsmBCO bco, AsmInfo info )
1398 ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1399 asmInstr(bco,i_ALLOC_CONSTR);
1400 asmInstr(bco,bco->nps.len);
1401 asmWords(bco,AsmInfo,info);
1402 bco->sp += sizeofW(StgClosurePtr);
1403 grabHpNonUpd(bco,sizeW_fromITBL(info));
1407 AsmSp asmBeginPack( AsmBCO bco )
1412 void asmEndPack( AsmBCO bco, AsmVar v, AsmSp start, AsmInfo info )
1414 nat size = bco->sp - start;
1415 ASSERT(bco->sp >= start);
1417 /* only reason to include info is for this assertion */
1418 ASSERT(info->layout.payload.ptrs == size);
1419 asmInstr(bco,i_PACK);
1420 asmInstr(bco,bco->sp - v);
1424 void asmBeginUnpack( AsmBCO bco )
1426 /* dummy to make it look prettier */
1429 void asmEndUnpack( AsmBCO bco )
1431 asmInstr(bco,i_UNPACK);
1434 AsmVar asmAllocAP( AsmBCO bco, AsmNat words )
1436 asmInstr(bco,i_ALLOC_AP);
1437 asmInstr(bco,words);
1438 bco->sp += sizeofW(StgPtr);
1439 grabHpUpd(bco,AP_sizeW(words));
1443 AsmSp asmBeginMkAP( AsmBCO bco )
1448 void asmEndMkAP( AsmBCO bco, AsmVar v, AsmSp start )
1450 asmInstr(bco,i_MKAP);
1451 asmInstr(bco,bco->sp-v);
1452 asmInstr(bco,bco->sp-start-1); /* -1 because fun isn't counted */
1456 AsmVar asmAllocPAP( AsmBCO bco, AsmNat size )
1458 asmInstr(bco,i_ALLOC_PAP);
1460 bco->sp += sizeofW(StgPtr);
1464 AsmSp asmBeginMkPAP( AsmBCO bco )
1469 void asmEndMkPAP( AsmBCO bco, AsmVar v, AsmSp start )
1471 asmInstr(bco,i_MKPAP);
1472 asmInstr(bco,bco->sp-v);
1473 asmInstr(bco,bco->sp-start-1); /* -1 because fun isn't counted */
1477 AsmVar asmClosure( AsmBCO bco, AsmObject p )
1479 StgWord o = bco->object.ptrs.len;
1481 asmInstr(bco,i_CONST);
1485 asmInstr(bco,i_CONST2);
1486 asmInstr(bco,o / 256);
1487 asmInstr(bco,o % 256);
1490 bco->sp += sizeofW(StgPtr);
1494 /* --------------------------------------------------------------------------
1495 * Building InfoTables
1496 * ------------------------------------------------------------------------*/
1498 AsmInfo asmMkInfo( AsmNat tag, AsmNat ptrs )
1500 StgInfoTable* info = stgMallocBytes( sizeof(StgInfoTable),"asmMkInfo");
1501 /* Note: the evaluator automatically pads objects with the right number
1502 * of non-ptrs to satisfy MIN_NONUPD_SIZE restrictions.
1504 AsmNat nptrs = stg_max(0,MIN_NONUPD_SIZE-ptrs);
1506 /* initialisation code based on INFO_TABLE_CONSTR */
1507 info->layout.payload.ptrs = ptrs;
1508 info->layout.payload.nptrs = nptrs;
1509 info->srt_len = tag;
1510 info->type = CONSTR;
1511 info->flags = FLAGS_CONSTR;
1512 #ifdef USE_MINIINTERPRETER
1513 info->entry = stgCast(StgFunPtr,&Hugs_CONSTR_entry);
1515 #warning asmMkInfo: Need to insert entry code in some cunning way
1517 ASSERT( sizeW_fromITBL(info) >= MIN_NONUPD_SIZE + sizeofW(StgHeader) );
1521 /*-------------------------------------------------------------------------*/
1523 #endif /* INTERPRETER */