/* Expanding the bytecode to threaded code *//* sestoft@dina.kvl.dk 1999-01-21 */ #include <stdlib.h>#include <stdio.h> #include "fail.h"#include "instruct.h"#include "misc.h"#include "unalignd.h"#include "interp.h" /* Accessing arguments in the bytecode array: */ #define s16pc s16(pc)#define u16pc u16(pc)#define s32pc s32(pc)#define u32pc u32(pc)#define SHORT (sizeof(short))#define LONG (sizeof(int32)) #define Instruct(name) case name /* Computing the length of the realcode array, and building the address offset translation. In the bytecode, a label is represented by a signed 32-bit offset from the current bytecode PC; hence the jump is done by pcb = pcb + *pcb In the threaded code we want to replace this by the relevant index into the realcode array, thus avoiding the addition when doing the jump. At runtime the jump should be done by: pcr = *pcr When preparing the threaded code we therefore need to know the realcode[] index corresponding to the bytecode index pcb + *pcb. One way to compute this is to maintain a mapping from all bytecode addresses to the corresponding realcode addresses. This can be built incrementally while computing the length of the realcode corresponding to the bytecode. Perhaps this scheme can be optimized, but let's leave that for later.*/ /* Computes and returns the length of the required realcode array; allocates and fills in the realaddress array; the argument realaddress is a pointer to a variable pointing to that array. */ int buildrealmap(bytecode_t byteprog, int code_size, int realaddress[]){#ifdef THREADED int realsize = 0; bytecode_t pc = byteprog; /* Initialize to catch errors */ int i; for (i=0; i<code_size; i++) realaddress[i] = -1; while (pc-byteprog < code_size) { int cur_inst = *pc; // printf("%d:%d\t real = %d\n", pc-byteprog, cur_inst, realsize); realaddress[pc++ - byteprog] = realsize++; switch (cur_inst) { /* No arguments: */ Instruct(SWAP): Instruct(PUSH): Instruct(PUSHACC0): Instruct(ACC0): Instruct(PUSHACC1): Instruct(ACC1): Instruct(PUSHACC2): Instruct(ACC2): Instruct(PUSHACC3): Instruct(ACC3): Instruct(PUSHACC4): Instruct(ACC4): Instruct(PUSHACC5): Instruct(ACC5): Instruct(PUSHACC6): Instruct(ACC6): Instruct(PUSHACC7): Instruct(ACC7): Instruct(PUSHENV1): Instruct(ENV1): Instruct(PUSHENV2): Instruct(ENV2): Instruct(PUSHENV3): Instruct(ENV3): Instruct(PUSHENV4): Instruct(ENV4): Instruct(PUSHENV5): Instruct(ENV5): Instruct(PUSHENV6): Instruct(ENV6): Instruct(PUSHENV7): Instruct(ENV7): Instruct(PUSH_ENV1_APPLY1): Instruct(PUSH_ENV1_APPLY2): Instruct(PUSH_ENV1_APPLY3): Instruct(PUSH_ENV1_APPLY4): Instruct(APPLY1): Instruct(APPLY2): Instruct(APPLY3): Instruct(APPLY4): Instruct(RETURN1): Instruct(RETURN2): Instruct(RESTART): Instruct(UPDATE): Instruct(CHECK_SIGNALS): Instruct(PUSHATOM0): Instruct(ATOM0): Instruct(ATOM1): Instruct(ATOM2): Instruct(ATOM3): Instruct(ATOM4): Instruct(ATOM5): Instruct(ATOM6): Instruct(ATOM7): Instruct(ATOM8): Instruct(ATOM9): Instruct(GETFIELD0): Instruct(GETFIELD1): Instruct(GETFIELD2): Instruct(GETFIELD3): Instruct(GETFIELD0_0): Instruct(GETFIELD0_1): Instruct(GETFIELD1_0): Instruct(GETFIELD1_1): Instruct(SETFIELD0): Instruct(SETFIELD1): Instruct(SETFIELD2): Instruct(SETFIELD3): Instruct(VECTLENGTH): Instruct(GETVECTITEM): Instruct(SETVECTITEM): Instruct(GETSTRINGCHAR): Instruct(SETSTRINGCHAR): Instruct(BOOLNOT): Instruct(POPTRAP): Instruct(RAISE): Instruct(PUSHCONST0): Instruct(CONST0): Instruct(PUSHCONST1): Instruct(CONST1): Instruct(PUSHCONST2): Instruct(CONST2): Instruct(PUSHCONST3): Instruct(CONST3): Instruct(ADDINT): Instruct(SUBINT): Instruct(MULINT): Instruct(DIVINT): Instruct(MODINT): Instruct(ANDINT): Instruct(ORINT): Instruct(XORINT): Instruct(SHIFTLEFTINT): Instruct(SHIFTRIGHTINTSIGNED): Instruct(SHIFTRIGHTINTUNSIGNED): Instruct(TAGOF): Instruct(EQ): Instruct(NEQ): Instruct(LTINT): Instruct(GTINT): Instruct(LEINT): Instruct(GEINT): Instruct(EQUNSIGN): Instruct(NEQUNSIGN): Instruct(LTUNSIGN): Instruct(GTUNSIGN): Instruct(LEUNSIGN): Instruct(GEUNSIGN): Instruct(FLOATOFINT): Instruct(SMLNEGFLOAT): Instruct(SMLADDFLOAT): Instruct(SMLSUBFLOAT): Instruct(SMLMULFLOAT): Instruct(SMLDIVFLOAT): Instruct(INTOFFLOAT): Instruct(EQFLOAT): Instruct(NEQFLOAT): Instruct(LTFLOAT): Instruct(GTFLOAT): Instruct(LEFLOAT): Instruct(GEFLOAT): Instruct(STRINGLENGTH): Instruct(EQSTRING): Instruct(NEQSTRING): Instruct(LTSTRING): Instruct(GTSTRING): Instruct(LESTRING): Instruct(GESTRING): Instruct(MAKEVECTOR): Instruct(SMLNEGINT): Instruct(SMLSUCCINT): Instruct(SMLPREDINT): Instruct(SMLADDINT): Instruct(SMLSUBINT): Instruct(SMLMULINT): Instruct(SMLDIVINT): Instruct(SMLMODINT): Instruct(MAKEREFVECTOR): Instruct(SMLQUOTINT): Instruct(SMLREMINT): Instruct(STOP): break; /* A one-byte argument: */ Instruct(APPLY): Instruct(GRAB): Instruct(PUSHATOM): Instruct(ATOM): Instruct(MAKEBLOCK1): Instruct(MAKEBLOCK2): Instruct(MAKEBLOCK3): Instruct(MAKEBLOCK4): Instruct(CONSTBYTE): pc++; realsize++; break; /* A four-byte label argument. The label should be translated to an address in the realprog[] array. This requires an auxiliary table. */ Instruct(PUSH_RETADDR): Instruct(PUSHTRAP): Instruct(BRANCH): Instruct(BRANCHIF): Instruct(BRANCHIFNOT): Instruct(POPBRANCHIFNOT): Instruct(BRANCHIFEQ): Instruct(BRANCHIFNEQ): Instruct(BRANCHIFLT): Instruct(BRANCHIFGT): Instruct(BRANCHIFLE): Instruct(BRANCHIFGE): pc += LONG; realsize++; break; /* Two four-byte label arguments. The labels should be translated to an address in the realprog[] array. This requires an auxiliary table. */ Instruct(BRANCHINTERVAL): pc += LONG; realsize++; pc += LONG; realsize++; break; /* A two-byte signed argument. */ Instruct(CONSTSHORT): pc += SHORT; realsize++; break; /* A two-byte unsigned argument. */ Instruct(PUSHACC): Instruct(ACCESS): Instruct(POP): Instruct(ASSIGN): Instruct(PUSHENVACC): Instruct(ENVACC): Instruct(DUMMY): Instruct(RETURN): Instruct(SETGLOBAL): Instruct(GETGLOBAL): Instruct(APPTERM1): Instruct(APPTERM2): Instruct(APPTERM3): Instruct(APPTERM4): Instruct(PUSH_ENV1_APPTERM1): Instruct(PUSH_ENV1_APPTERM2): Instruct(PUSH_ENV1_APPTERM3): Instruct(PUSH_ENV1_APPTERM4): Instruct(PUSH_GETGLOBAL): Instruct(PUSH_GETGLOBAL_APPLY1): Instruct(PUSH_GETGLOBAL_APPLY2): Instruct(PUSH_GETGLOBAL_APPLY3): Instruct(PUSH_GETGLOBAL_APPLY4): Instruct(GETFIELD): Instruct(SETFIELD): Instruct(C_CALL1): Instruct(C_CALL2): Instruct(C_CALL3): Instruct(C_CALL4): Instruct(C_CALL5): pc += SHORT; realsize++; break; /* A four-byte unsigned argument. */ Instruct(MAKEBLOCK): pc += LONG; realsize++; break; /* A four-byte signed argument. */ Instruct(PUSHCONSTINT): Instruct(CONSTINT): pc += LONG; realsize++; break; /* A one-byte argument and a four-byte signed (label) argument. */ Instruct(CLOSURE): Instruct(CLOSREC): Instruct(BRANCHIFNEQTAG): pc++; realsize++; pc += LONG; realsize++; break; /* A one-byte argument and a two-byte unsigned argument. */ Instruct(APPTERM): Instruct(C_CALLN): pc++; realsize++; pc += SHORT; realsize++; break; /* Two two-byte unsigned arguments. */ Instruct(PUSH_GETGLOBAL_APPTERM1): Instruct(PUSH_GETGLOBAL_APPTERM2): Instruct(PUSH_GETGLOBAL_APPTERM3): Instruct(PUSH_GETGLOBAL_APPTERM4): pc += SHORT; realsize++; pc += SHORT; realsize++; break; /* A one-byte argument and a table of four-byte signed (label) arguments */ /* We keep the byte argument for consistency. */ Instruct(SWITCH): { int n = *pc; pc++; realsize++; /* The byte */ pc += n * LONG; realsize += n; /* The n labels */ } break; default: printf("buildrealmap: opcode = %d at %d\n", *pc, pc-byteprog); fatal_error("bad opcode\n"); } } // printf("buildrealmap finished\n"); return realsize;#else return 0; /* bogus */#endif} // buildrealmap /* Computing the real address from the bytecode address and an offset */ #define REALADDR(pc, offset) \ realprog + realaddress[(int)(pc - byteprog) + (int)offset]; /* The expander itself *//* Returns a pointer to the realcode array (an array of C code addresses). */ realcode_t expandcode(bytecode_t byteprog, int code_size, void * jumptable[]){#ifdef THREADED bytecode_t pc = byteprog; int *realaddress = (int*)(malloc(code_size * sizeof(int))); int realsize = buildrealmap(byteprog, code_size, realaddress); realcode_t realprog = (realcode_t)malloc(realsize * sizeof(void*)); int codeptr = 0; while (pc - byteprog < code_size) { // printf("%d:%d\t\n", pc-byteprog, *pc); switch (*pc) { /* No arguments: */ Instruct(SWAP): Instruct(PUSH): Instruct(PUSHACC0): Instruct(ACC0): Instruct(PUSHACC1): Instruct(ACC1): Instruct(PUSHACC2): Instruct(ACC2): Instruct(PUSHACC3): Instruct(ACC3): Instruct(PUSHACC4): Instruct(ACC4): Instruct(PUSHACC5): Instruct(ACC5): Instruct(PUSHACC6): Instruct(ACC6): Instruct(PUSHACC7): Instruct(ACC7): Instruct(PUSHENV1): Instruct(ENV1): Instruct(PUSHENV2): Instruct(ENV2): Instruct(PUSHENV3): Instruct(ENV3): Instruct(PUSHENV4): Instruct(ENV4): Instruct(PUSHENV5): Instruct(ENV5): Instruct(PUSHENV6): Instruct(ENV6): Instruct(PUSHENV7): Instruct(ENV7): Instruct(PUSH_ENV1_APPLY1): Instruct(PUSH_ENV1_APPLY2): Instruct(PUSH_ENV1_APPLY3): Instruct(PUSH_ENV1_APPLY4): Instruct(APPLY1): Instruct(APPLY2): Instruct(APPLY3): Instruct(APPLY4): Instruct(RETURN1): Instruct(RETURN2): Instruct(RESTART): Instruct(UPDATE): Instruct(CHECK_SIGNALS): Instruct(PUSHATOM0): Instruct(ATOM0): Instruct(ATOM1): Instruct(ATOM2): Instruct(ATOM3): Instruct(ATOM4): Instruct(ATOM5): Instruct(ATOM6): Instruct(ATOM7): Instruct(ATOM8): Instruct(ATOM9): Instruct(GETFIELD0): Instruct(GETFIELD1): Instruct(GETFIELD2): Instruct(GETFIELD3): Instruct(GETFIELD0_0): Instruct(GETFIELD0_1): Instruct(GETFIELD1_0): Instruct(GETFIELD1_1): Instruct(SETFIELD0): Instruct(SETFIELD1): Instruct(SETFIELD2): Instruct(SETFIELD3): Instruct(VECTLENGTH): Instruct(GETVECTITEM): Instruct(SETVECTITEM): Instruct(GETSTRINGCHAR): Instruct(SETSTRINGCHAR): Instruct(BOOLNOT): Instruct(POPTRAP): Instruct(RAISE): Instruct(PUSHCONST0): Instruct(CONST0): Instruct(PUSHCONST1): Instruct(CONST1): Instruct(PUSHCONST2): Instruct(CONST2): Instruct(PUSHCONST3): Instruct(CONST3): Instruct(ADDINT): Instruct(SUBINT): Instruct(MULINT): Instruct(DIVINT): Instruct(MODINT): Instruct(ANDINT): Instruct(ORINT): Instruct(XORINT): Instruct(SHIFTLEFTINT): Instruct(SHIFTRIGHTINTSIGNED): Instruct(SHIFTRIGHTINTUNSIGNED): Instruct(TAGOF): Instruct(EQ): Instruct(NEQ): Instruct(LTINT): Instruct(GTINT): Instruct(LEINT): Instruct(GEINT): Instruct(EQUNSIGN): Instruct(NEQUNSIGN): Instruct(LTUNSIGN): Instruct(GTUNSIGN): Instruct(LEUNSIGN): Instruct(GEUNSIGN): Instruct(FLOATOFINT): Instruct(SMLNEGFLOAT): Instruct(SMLADDFLOAT): Instruct(SMLSUBFLOAT): Instruct(SMLMULFLOAT): Instruct(SMLDIVFLOAT): Instruct(INTOFFLOAT): Instruct(EQFLOAT): Instruct(NEQFLOAT): Instruct(LTFLOAT): Instruct(GTFLOAT): Instruct(LEFLOAT): Instruct(GEFLOAT): Instruct(STRINGLENGTH): Instruct(EQSTRING): Instruct(NEQSTRING): Instruct(LTSTRING): Instruct(GTSTRING): Instruct(LESTRING): Instruct(GESTRING): Instruct(MAKEVECTOR): Instruct(SMLNEGINT):Lines 1–500 of 674. Load more
/* Expanding the bytecode to threaded code */ /* sestoft@dina.kvl.dk 1999-01-21 */ #include <stdlib.h> #include <stdio.h> #include "fail.h" #include "instruct.h" #include "misc.h" #include "unalignd.h" #include "interp.h" /* Accessing arguments in the bytecode array: */ #define s16pc s16(pc) #define u16pc u16(pc) #define s32pc s32(pc) #define u32pc u32(pc) #define SHORT (sizeof(short)) #define LONG (sizeof(int32)) #define Instruct(name) case name /* Computing the length of the realcode array, and building the address offset translation. In the bytecode, a label is represented by a signed 32-bit offset from the current bytecode PC; hence the jump is done by pcb = pcb + *pcb In the threaded code we want to replace this by the relevant index into the realcode array, thus avoiding the addition when doing the jump. At runtime the jump should be done by: pcr = *pcr When preparing the threaded code we therefore need to know the realcode[] index corresponding to the bytecode index pcb + *pcb. One way to compute this is to maintain a mapping from all bytecode addresses to the corresponding realcode addresses. This can be built incrementally while computing the length of the realcode corresponding to the bytecode. Perhaps this scheme can be optimized, but let's leave that for later. */ /* Computes and returns the length of the required realcode array; allocates and fills in the realaddress array; the argument realaddress is a pointer to a variable pointing to that array. */ int buildrealmap(bytecode_t byteprog, int code_size, int realaddress[]) { #ifdef THREADED int realsize = 0; bytecode_t pc = byteprog; /* Initialize to catch errors */ int i; for (i=0; i<code_size; i++) realaddress[i] = -1; while (pc-byteprog < code_size) { int cur_inst = *pc; // printf("%d:%d\t real = %d\n", pc-byteprog, cur_inst, realsize); realaddress[pc++ - byteprog] = realsize++; switch (cur_inst) { /* No arguments: */ Instruct(SWAP): Instruct(PUSH): Instruct(PUSHACC0): Instruct(ACC0): Instruct(PUSHACC1): Instruct(ACC1): Instruct(PUSHACC2): Instruct(ACC2): Instruct(PUSHACC3): Instruct(ACC3): Instruct(PUSHACC4): Instruct(ACC4): Instruct(PUSHACC5): Instruct(ACC5): Instruct(PUSHACC6): Instruct(ACC6): Instruct(PUSHACC7): Instruct(ACC7): Instruct(PUSHENV1): Instruct(ENV1): Instruct(PUSHENV2): Instruct(ENV2): Instruct(PUSHENV3): Instruct(ENV3): Instruct(PUSHENV4): Instruct(ENV4): Instruct(PUSHENV5): Instruct(ENV5): Instruct(PUSHENV6): Instruct(ENV6): Instruct(PUSHENV7): Instruct(ENV7): Instruct(PUSH_ENV1_APPLY1): Instruct(PUSH_ENV1_APPLY2): Instruct(PUSH_ENV1_APPLY3): Instruct(PUSH_ENV1_APPLY4): Instruct(APPLY1): Instruct(APPLY2): Instruct(APPLY3): Instruct(APPLY4): Instruct(RETURN1): Instruct(RETURN2): Instruct(RESTART): Instruct(UPDATE): Instruct(CHECK_SIGNALS): Instruct(PUSHATOM0): Instruct(ATOM0): Instruct(ATOM1): Instruct(ATOM2): Instruct(ATOM3): Instruct(ATOM4): Instruct(ATOM5): Instruct(ATOM6): Instruct(ATOM7): Instruct(ATOM8): Instruct(ATOM9): Instruct(GETFIELD0): Instruct(GETFIELD1): Instruct(GETFIELD2): Instruct(GETFIELD3): Instruct(GETFIELD0_0): Instruct(GETFIELD0_1): Instruct(GETFIELD1_0): Instruct(GETFIELD1_1): Instruct(SETFIELD0): Instruct(SETFIELD1): Instruct(SETFIELD2): Instruct(SETFIELD3): Instruct(VECTLENGTH): Instruct(GETVECTITEM): Instruct(SETVECTITEM): Instruct(GETSTRINGCHAR): Instruct(SETSTRINGCHAR): Instruct(BOOLNOT): Instruct(POPTRAP): Instruct(RAISE): Instruct(PUSHCONST0): Instruct(CONST0): Instruct(PUSHCONST1): Instruct(CONST1): Instruct(PUSHCONST2): Instruct(CONST2): Instruct(PUSHCONST3): Instruct(CONST3): Instruct(ADDINT): Instruct(SUBINT): Instruct(MULINT): Instruct(DIVINT): Instruct(MODINT): Instruct(ANDINT): Instruct(ORINT): Instruct(XORINT): Instruct(SHIFTLEFTINT): Instruct(SHIFTRIGHTINTSIGNED): Instruct(SHIFTRIGHTINTUNSIGNED): Instruct(TAGOF): Instruct(EQ): Instruct(NEQ): Instruct(LTINT): Instruct(GTINT): Instruct(LEINT): Instruct(GEINT): Instruct(EQUNSIGN): Instruct(NEQUNSIGN): Instruct(LTUNSIGN): Instruct(GTUNSIGN): Instruct(LEUNSIGN): Instruct(GEUNSIGN): Instruct(FLOATOFINT): Instruct(SMLNEGFLOAT): Instruct(SMLADDFLOAT): Instruct(SMLSUBFLOAT): Instruct(SMLMULFLOAT): Instruct(SMLDIVFLOAT): Instruct(INTOFFLOAT): Instruct(EQFLOAT): Instruct(NEQFLOAT): Instruct(LTFLOAT): Instruct(GTFLOAT): Instruct(LEFLOAT): Instruct(GEFLOAT): Instruct(STRINGLENGTH): Instruct(EQSTRING): Instruct(NEQSTRING): Instruct(LTSTRING): Instruct(GTSTRING): Instruct(LESTRING): Instruct(GESTRING): Instruct(MAKEVECTOR): Instruct(SMLNEGINT): Instruct(SMLSUCCINT): Instruct(SMLPREDINT): Instruct(SMLADDINT): Instruct(SMLSUBINT): Instruct(SMLMULINT): Instruct(SMLDIVINT): Instruct(SMLMODINT): Instruct(MAKEREFVECTOR): Instruct(SMLQUOTINT): Instruct(SMLREMINT): Instruct(STOP): break; /* A one-byte argument: */ Instruct(APPLY): Instruct(GRAB): Instruct(PUSHATOM): Instruct(ATOM): Instruct(MAKEBLOCK1): Instruct(MAKEBLOCK2): Instruct(MAKEBLOCK3): Instruct(MAKEBLOCK4): Instruct(CONSTBYTE): pc++; realsize++; break; /* A four-byte label argument. The label should be translated to an address in the realprog[] array. This requires an auxiliary table. */ Instruct(PUSH_RETADDR): Instruct(PUSHTRAP): Instruct(BRANCH): Instruct(BRANCHIF): Instruct(BRANCHIFNOT): Instruct(POPBRANCHIFNOT): Instruct(BRANCHIFEQ): Instruct(BRANCHIFNEQ): Instruct(BRANCHIFLT): Instruct(BRANCHIFGT): Instruct(BRANCHIFLE): Instruct(BRANCHIFGE): pc += LONG; realsize++; break; /* Two four-byte label arguments. The labels should be translated to an address in the realprog[] array. This requires an auxiliary table. */ Instruct(BRANCHINTERVAL): pc += LONG; realsize++; pc += LONG; realsize++; break; /* A two-byte signed argument. */ Instruct(CONSTSHORT): pc += SHORT; realsize++; break; /* A two-byte unsigned argument. */ Instruct(PUSHACC): Instruct(ACCESS): Instruct(POP): Instruct(ASSIGN): Instruct(PUSHENVACC): Instruct(ENVACC): Instruct(DUMMY): Instruct(RETURN): Instruct(SETGLOBAL): Instruct(GETGLOBAL): Instruct(APPTERM1): Instruct(APPTERM2): Instruct(APPTERM3): Instruct(APPTERM4): Instruct(PUSH_ENV1_APPTERM1): Instruct(PUSH_ENV1_APPTERM2): Instruct(PUSH_ENV1_APPTERM3): Instruct(PUSH_ENV1_APPTERM4): Instruct(PUSH_GETGLOBAL): Instruct(PUSH_GETGLOBAL_APPLY1): Instruct(PUSH_GETGLOBAL_APPLY2): Instruct(PUSH_GETGLOBAL_APPLY3): Instruct(PUSH_GETGLOBAL_APPLY4): Instruct(GETFIELD): Instruct(SETFIELD): Instruct(C_CALL1): Instruct(C_CALL2): Instruct(C_CALL3): Instruct(C_CALL4): Instruct(C_CALL5): pc += SHORT; realsize++; break; /* A four-byte unsigned argument. */ Instruct(MAKEBLOCK): pc += LONG; realsize++; break; /* A four-byte signed argument. */ Instruct(PUSHCONSTINT): Instruct(CONSTINT): pc += LONG; realsize++; break; /* A one-byte argument and a four-byte signed (label) argument. */ Instruct(CLOSURE): Instruct(CLOSREC): Instruct(BRANCHIFNEQTAG): pc++; realsize++; pc += LONG; realsize++; break; /* A one-byte argument and a two-byte unsigned argument. */ Instruct(APPTERM): Instruct(C_CALLN): pc++; realsize++; pc += SHORT; realsize++; break; /* Two two-byte unsigned arguments. */ Instruct(PUSH_GETGLOBAL_APPTERM1): Instruct(PUSH_GETGLOBAL_APPTERM2): Instruct(PUSH_GETGLOBAL_APPTERM3): Instruct(PUSH_GETGLOBAL_APPTERM4): pc += SHORT; realsize++; pc += SHORT; realsize++; break; /* A one-byte argument and a table of four-byte signed (label) arguments */ /* We keep the byte argument for consistency. */ Instruct(SWITCH): { int n = *pc; pc++; realsize++; /* The byte */ pc += n * LONG; realsize += n; /* The n labels */ } break; default: printf("buildrealmap: opcode = %d at %d\n", *pc, pc-byteprog); fatal_error("bad opcode\n"); } } // printf("buildrealmap finished\n"); return realsize; #else return 0; /* bogus */ #endif } // buildrealmap /* Computing the real address from the bytecode address and an offset */ #define REALADDR(pc, offset) \ realprog + realaddress[(int)(pc - byteprog) + (int)offset]; /* The expander itself */ /* Returns a pointer to the realcode array (an array of C code addresses). */ realcode_t expandcode(bytecode_t byteprog, int code_size, void * jumptable[]) { #ifdef THREADED bytecode_t pc = byteprog; int *realaddress = (int*)(malloc(code_size * sizeof(int))); int realsize = buildrealmap(byteprog, code_size, realaddress); realcode_t realprog = (realcode_t)malloc(realsize * sizeof(void*)); int codeptr = 0; while (pc - byteprog < code_size) { // printf("%d:%d\t\n", pc-byteprog, *pc); switch (*pc) { /* No arguments: */ Instruct(SWAP): Instruct(PUSH): Instruct(PUSHACC0): Instruct(ACC0): Instruct(PUSHACC1): Instruct(ACC1): Instruct(PUSHACC2): Instruct(ACC2): Instruct(PUSHACC3): Instruct(ACC3): Instruct(PUSHACC4): Instruct(ACC4): Instruct(PUSHACC5): Instruct(ACC5): Instruct(PUSHACC6): Instruct(ACC6): Instruct(PUSHACC7): Instruct(ACC7): Instruct(PUSHENV1): Instruct(ENV1): Instruct(PUSHENV2): Instruct(ENV2): Instruct(PUSHENV3): Instruct(ENV3): Instruct(PUSHENV4): Instruct(ENV4): Instruct(PUSHENV5): Instruct(ENV5): Instruct(PUSHENV6): Instruct(ENV6): Instruct(PUSHENV7): Instruct(ENV7): Instruct(PUSH_ENV1_APPLY1): Instruct(PUSH_ENV1_APPLY2): Instruct(PUSH_ENV1_APPLY3): Instruct(PUSH_ENV1_APPLY4): Instruct(APPLY1): Instruct(APPLY2): Instruct(APPLY3): Instruct(APPLY4): Instruct(RETURN1): Instruct(RETURN2): Instruct(RESTART): Instruct(UPDATE): Instruct(CHECK_SIGNALS): Instruct(PUSHATOM0): Instruct(ATOM0): Instruct(ATOM1): Instruct(ATOM2): Instruct(ATOM3): Instruct(ATOM4): Instruct(ATOM5): Instruct(ATOM6): Instruct(ATOM7): Instruct(ATOM8): Instruct(ATOM9): Instruct(GETFIELD0): Instruct(GETFIELD1): Instruct(GETFIELD2): Instruct(GETFIELD3): Instruct(GETFIELD0_0): Instruct(GETFIELD0_1): Instruct(GETFIELD1_0): Instruct(GETFIELD1_1): Instruct(SETFIELD0): Instruct(SETFIELD1): Instruct(SETFIELD2): Instruct(SETFIELD3): Instruct(VECTLENGTH): Instruct(GETVECTITEM): Instruct(SETVECTITEM): Instruct(GETSTRINGCHAR): Instruct(SETSTRINGCHAR): Instruct(BOOLNOT): Instruct(POPTRAP): Instruct(RAISE): Instruct(PUSHCONST0): Instruct(CONST0): Instruct(PUSHCONST1): Instruct(CONST1): Instruct(PUSHCONST2): Instruct(CONST2): Instruct(PUSHCONST3): Instruct(CONST3): Instruct(ADDINT): Instruct(SUBINT): Instruct(MULINT): Instruct(DIVINT): Instruct(MODINT): Instruct(ANDINT): Instruct(ORINT): Instruct(XORINT): Instruct(SHIFTLEFTINT): Instruct(SHIFTRIGHTINTSIGNED): Instruct(SHIFTRIGHTINTUNSIGNED): Instruct(TAGOF): Instruct(EQ): Instruct(NEQ): Instruct(LTINT): Instruct(GTINT): Instruct(LEINT): Instruct(GEINT): Instruct(EQUNSIGN): Instruct(NEQUNSIGN): Instruct(LTUNSIGN): Instruct(GTUNSIGN): Instruct(LEUNSIGN): Instruct(GEUNSIGN): Instruct(FLOATOFINT): Instruct(SMLNEGFLOAT): Instruct(SMLADDFLOAT): Instruct(SMLSUBFLOAT): Instruct(SMLMULFLOAT): Instruct(SMLDIVFLOAT): Instruct(INTOFFLOAT): Instruct(EQFLOAT): Instruct(NEQFLOAT): Instruct(LTFLOAT): Instruct(GTFLOAT): Instruct(LEFLOAT): Instruct(GEFLOAT): Instruct(STRINGLENGTH): Instruct(EQSTRING): Instruct(NEQSTRING): Instruct(LTSTRING): Instruct(GTSTRING): Instruct(LESTRING): Instruct(GESTRING): Instruct(MAKEVECTOR): Instruct(SMLNEGINT):