From 9a6f6051962f4c06920fb12a7b2c4d57ac510af8 Mon Sep 17 00:00:00 2001 From: crc Date: Sat, 28 Jun 2008 20:07:15 -0400 Subject: [PATCH] Added new experimental VM from Mat. This is the 'faster vm' option. --- ngaro/c-mat/vm.c | 444 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- ngaro/c-mat/vm.h | 28 ++-- 2 files changed, 450 insertions(+), 22 deletions(-) diff --git a/ngaro/c-mat/vm.c b/ngaro/c-mat/vm.c index d5054f0..7fca05d 100755 --- a/ngaro/c-mat/vm.c +++ b/ngaro/c-mat/vm.c @@ -18,6 +18,7 @@ /* Variables specific to the VM */ + VM_STATE vm; @@ -28,6 +29,7 @@ VM_STATE vm; * This zeros out everything in the VM_STATE struct * to give us a known starting point. ******************************************************/ + void init_vm() { int a; @@ -43,25 +45,119 @@ void init_vm() } +/****************************************************** + *|F| void vm_process (void) + * + * Token threading interpreter + * + static data-stack caching (first two elements) + * + static adress-stack caching (per link register) + * + generation of dynamic super instructions (dtc) + * + dynamic generation of new instructions (dtc) + * + direct data-cache adressing instructions + ******************************************************/ + +/* bytecode to adress arrays for token and direct threading */ void **vm_process_ct_otab[255]; +void **vm_process_tr_otab[255]; -void vm_process (void) +void vm_process (void) { - int a, b, c; + /* scratch variables */ + + int a, b, c; + + /* register file: + + ip = instruction pointer (token threading) + sp = data stack pointer (to third stack element) + rsp = return adress stack pointer (to third stack-element) + IAC = integer accumulator (cached first stack element) + IOP = integer operand (cached second stack element) + LNK = return adress (for LCALL and LRETURN) + + image = pointer to the bytecode image + data = start adress of the data stack + adress = start adress of the return-adress stack + + INST = pointer to a token threading primitive + TINST = pointer to a direct threading stream */ register int ip; ip = vm.ip; register int sp; sp = vm.sp; register int rsp; rsp = vm.rsp; - register void *INST; - register int *image = vm.image; register int *data = vm.data; register int *address = vm.address; register int IAC; IAC = 0; register int IOP; IOP = 0; + register int LNK; LNK = 0; + + register void *INST; + register void **TINST; + + /* direct threading streams, + tptr = pointer to free space in stream array */ + + void *tstream [MAX_STREAM * STREAM_LEN]; + int tptr = 0; + + /* initialisation of bytecode to DTC adress table */ + + vm_process_tr_otab[VM_NOP] = &&tVM_NOP; + vm_process_tr_otab[VM_LIT] = &&tVM_LIT; + vm_process_tr_otab[VM_DUP] = &&tVM_DUP; + vm_process_tr_otab[VM_DROP] = &&tVM_DROP; + vm_process_tr_otab[VM_SWAP] = &&tVM_SWAP; + vm_process_tr_otab[VM_PUSH] = &&tVM_PUSH; + vm_process_tr_otab[VM_POP] = &&tVM_POP; + vm_process_tr_otab[VM_CALL] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_JUMP] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_RETURN] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_GT_JUMP] = &&tVM_GT_JUMP; + vm_process_tr_otab[VM_LT_JUMP] = &&tVM_LT_JUMP; + vm_process_tr_otab[VM_NE_JUMP] = &&tVM_NE_JUMP; + vm_process_tr_otab[VM_EQ_JUMP] = &&tVM_EQ_JUMP; + vm_process_tr_otab[VM_FETCH] = &&tVM_FETCH; + vm_process_tr_otab[VM_STORE] = &&tVM_STORE; + vm_process_tr_otab[VM_ADD] = &&tVM_ADD; + vm_process_tr_otab[VM_SUB] = &&tVM_SUB; + vm_process_tr_otab[VM_MUL] = &&tVM_MUL; + vm_process_tr_otab[VM_DIVMOD] = &&tVM_DIVMOD; + vm_process_tr_otab[VM_AND] = &&tVM_AND; + vm_process_tr_otab[VM_OR] = &&tVM_OR; + vm_process_tr_otab[VM_XOR] = &&tVM_XOR; + vm_process_tr_otab[VM_SHL] = &&tVM_SHL; + vm_process_tr_otab[VM_SHR] = &&tVM_SHR; + vm_process_tr_otab[VM_ZERO_EXIT] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_INC] = &&tVM_INC; + vm_process_tr_otab[VM_DEC] = &&tVM_DEC; + vm_process_tr_otab[VM_IN] = &&tVM_IN; + vm_process_tr_otab[VM_OUT] = &&tVM_OUT; + vm_process_tr_otab[VM_WAIT] = &&tVM_WAIT; + vm_process_tr_otab[VM_PICK] = &&tVM_PICK; + vm_process_tr_otab[VM_BACK] = &&tVM_BACK; + vm_process_tr_otab[VM_ROT] = &&tVM_ROT; + vm_process_tr_otab[VM_SINST] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_XOP] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_EXE] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_LI_IAC] = &&tVM_LI_IAC; + vm_process_tr_otab[VM_LI_IOP] = &&tVM_LI_IOP; + vm_process_tr_otab[VM_PICK_IAC] = &&tVM_PICK_IAC; + vm_process_tr_otab[VM_PICK_IOP] = &&tVM_PICK_IOP; + vm_process_tr_otab[VM_RADD] = &&tVM_RADD; + vm_process_tr_otab[VM_RSUB] = &&tVM_RSUB; + vm_process_tr_otab[VM_MUL] = &&tVM_RMUL; + vm_process_tr_otab[VM_RAND] = &&tVM_RAND; + vm_process_tr_otab[VM_ROR] = &&tVM_ROR; + vm_process_tr_otab[VM_XOR] = &&tVM_RXOR; + vm_process_tr_otab[VM_LCALL] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_LRETURN] = &&tVM_ILLEGAL; + vm_process_tr_otab[VM_DEFAULT] = &&tVM_DEFAULT; + + /* initialisation of bytecode to TTC adress table */ vm_process_ct_otab[VM_NOP] = &&fVM_NOP; vm_process_ct_otab[VM_LIT] = &&fVM_LIT; @@ -94,12 +190,253 @@ void vm_process (void) vm_process_ct_otab[VM_IN] = &&fVM_IN; vm_process_ct_otab[VM_OUT] = &&fVM_OUT; vm_process_ct_otab[VM_WAIT] = &&fVM_WAIT; + vm_process_ct_otab[VM_PICK] = &&fVM_PICK; + vm_process_ct_otab[VM_PICK] = &&fVM_BACK; + vm_process_ct_otab[VM_ROT] = &&fVM_ROT; + vm_process_ct_otab[VM_SINST] = &&fVM_SINST; + vm_process_ct_otab[VM_XOP] = &&fVM_XOP; + vm_process_ct_otab[VM_EXE] = &&fVM_EXE; + vm_process_ct_otab[VM_LI_IAC] = &&fVM_LI_IAC; + vm_process_ct_otab[VM_LI_IOP] = &&fVM_LI_IOP; + vm_process_ct_otab[VM_PICK_IAC] = &&fVM_PICK_IAC; + vm_process_ct_otab[VM_PICK_IOP] = &&fVM_PICK_IOP; + vm_process_ct_otab[VM_RADD] = &&fVM_RADD; + vm_process_ct_otab[VM_RSUB] = &&fVM_RSUB; + vm_process_ct_otab[VM_RMUL] = &&fVM_RMUL; + vm_process_ct_otab[VM_RAND] = &&fVM_RAND; + vm_process_ct_otab[VM_ROR] = &&fVM_ROR; + vm_process_ct_otab[VM_XOR] = &&fVM_RXOR; + vm_process_ct_otab[VM_LCALL] = &&fVM_LCALL; + vm_process_ct_otab[VM_LRETURN] = &&fVM_LRETURN; vm_process_ct_otab[VM_DEFAULT] = &&fVM_DEFAULT; + /* vm exit point */ + vm.image[IMAGE_SIZE] = VM_DEFAULT; + /* threading though the vm image */ + + printf ("[ngaro] threading vm version 0.2a (2008)\n"); + printf ("\n"); + NEXT + /* direct threading primitives */ + + tVM_NOP: TNEXT + tVM_LIT: data[++sp] = IOP; + IOP = IAC; + IAC = (int) *TINST++; + TNEXT + tVM_DUP: data[++sp] = IOP; + IOP = IAC; + TNEXT + tVM_DROP: IAC = IOP; + IOP = data[sp--]; + TNEXT + tVM_SWAP: a = IAC; + IAC = IOP; + IOP = a; + TNEXT + tVM_PUSH: address[++rsp] = IAC; + IAC = IOP; + IOP = data[sp--]; + TNEXT + tVM_POP: data[++sp] = IOP; + IOP = IAC; + IAC = address[rsp--]; + TNEXT + /* + tVM_CALL: address[++rsp] = *TINST++; + TINST = *TINST-1; + TNEXT + tVM_JUMP: TINST = *TINST; + TNEXT + tVM_RETURN: ip = address[rsp--]+1; + TNEXT + */ + tVM_GT_JUMP: if(IOP > IAC) + { + LNK = (int) *TINST; + TINST = tstream + LNK; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + } + TINST++; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_LT_JUMP: if(IOP < IAC) + { + LNK = (int) *TINST; + TINST = tstream + LNK; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + } + TINST++; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_NE_JUMP: if(IAC != IOP) + { + LNK = (int) *TINST; + TINST = tstream + LNK; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + } + TINST++; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_EQ_JUMP: if(IAC == IOP) + { + LNK = (int) *TINST; + TINST = tstream + LNK; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + } + TINST++; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_FETCH: IAC = image[IAC]; + TNEXT + tVM_STORE: image[IAC] = IOP; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_ADD: IOP += IAC; + IAC = IOP; + IOP = data[sp--]; + TNEXT + tVM_SUB: IOP -= IAC; + IAC = IOP; + IOP = data[sp--]; + TNEXT + tVM_MUL: IOP *= IAC; + IAC = IOP; + IOP = data[sp--]; + TNEXT + tVM_DIVMOD: a = IAC; + b = IOP; + IAC = b / a; + IOP = b % a; + TNEXT + tVM_AND: IAC = IAC & IOP; + IOP = data[sp--]; + TNEXT + tVM_OR: IAC = IAC | IOP; + IOP = data[sp--]; + TNEXT + tVM_XOR: IAC = IAC ^ IOP; + IOP = data[sp--]; + TNEXT + tVM_SHL: IAC = IOP << IAC; + IOP = data[sp--]; + TNEXT + tVM_SHR: IAC = IOP >>= IAC; + IOP = data[sp--]; + TNEXT + /* + tVM_ZERO_EXIT:if (IAC == 0) + { + IAC = IOP; + IOP = data[sp--]; + TINST = address[rsp--]+1; + } + TNEXT + */ + tVM_INC: IAC += 1; + TNEXT + tVM_DEC: IAC -= 1; + TNEXT + tVM_IN: a = IAC; + IAC = vm.ports[a]; + vm.ports[a] = 0; + TNEXT + tVM_OUT: vm.ports[0] = 0; + vm.ports[IAC] = IOP; + IAC = data[sp--]; + IOP = data[sp--]; + TNEXT + tVM_PICK: a = (int) *TINST++; + data[++sp] = IOP; + IOP = IAC; + IAC = data[a]; + TNEXT + tVM_BACK: a = (int) *TINST++; + data[a] = IAC; + TNEXT; + tVM_ROT: a = IAC; + IAC = data[sp]; + data[sp] = a; + TNEXT + tVM_WAIT: + if (vm.ports[0] == 0 && vm.ports[1] == 1) + { + vm.ports[1] = getchar(); + vm.ports[0] = 1; + } + if (vm.ports[2] == 1) + { + c = IAC; + IAC = IOP; + IOP = data[sp--]; + draw_character(c); + vm.ports[2] = 0; + vm.ports[0] = 1; + } + if (vm.ports[4] == 1) + { + vm_save_image(vm.filename); + vm.ports[4] = 0; + vm.ports[0] = 1; + } + /* Capabilities */ + if (vm.ports[5] == -1) + { + vm.ports[5] = IMAGE_SIZE; + vm.ports[0] = 1; + } + if (vm.ports[5] == -2 || vm.ports[5] == -3 || vm.ports[5] == -4) + { + vm.ports[5] = 0; + vm.ports[0] = 1; + } + TNEXT + tVM_DEFAULT: goto fVM_DEFAULT; + tVM_ILLEGAL: printf ("[XOP,EXE] branch opcode in DTC stream detected !\n"); + exit (-3); + tVM_EXIT: NEXT + tVM_LI_IAC: IAC = (int) *TINST++; + TNEXT + tVM_LI_IOP: IOP = (int) *TINST++; + TNEXT + tVM_PICK_IAC: a = (int) *TINST++; + IAC = data[a]; + TNEXT + tVM_PICK_IOP: a = (int) *TINST++; + IOP = data[a]; + TNEXT + tVM_RADD: IAC = IAC + IOP; + TNEXT + tVM_RSUB: IAC = IOP - IAC; + TNEXT + tVM_RMUL: IAC = IAC * IOP; + TNEXT + tVM_RAND: IAC = IAC & (int) *TINST++; + TNEXT + tVM_ROR: IAC = IAC | (int) *TINST++; + TNEXT + tVM_RXOR: IAC = IAC ^ (int) *TINST++; + TNEXT + + /* token-threading bytecode primitives */ + fVM_NOP: NEXT fVM_LIT: data[++sp] = IOP; IOP = IAC; @@ -252,11 +589,12 @@ void vm_process (void) vm_save_image(vm.filename); vm.ports[4] = 0; vm.ports[0] = 1; - } + } /* Capabilities */ if (vm.ports[5] == -1) { - vm.ports[5] = IMAGE_SIZE; vm.ports[0] = 1; + vm.ports[5] = IMAGE_SIZE; + vm.ports[0] = 1; } if (vm.ports[5] == -2 || vm.ports[5] == -3 || vm.ports[5] == -4) { @@ -264,7 +602,101 @@ void vm_process (void) vm.ports[0] = 1; } NEXT + fVM_PICK: data[++sp] = IOP; + IOP = IAC; + IAC = data[image[ip++]]; + NEXT + fVM_BACK: data[image[ip++]] = IAC; + NEXT + fVM_ROT: a = IAC; + IAC = data[sp]; + data[sp] = a; + NEXT + fVM_SINST: a = image[ip++]; + c = tptr; + for (b = 0; b < a; b++) + { + if (tptr < (255*1024)) + { + //printf ("Bytecode: %i\n",image[ip]); + if (image[ip] <= NUM_OPS) + { + if ((image[ip] == VM_LIT) || + (image[ip] == VM_GT_JUMP) || + (image[ip] == VM_LT_JUMP) || + (image[ip] == VM_NE_JUMP) || + (image[ip] == VM_EQ_JUMP) || + (image[ip] == VM_PICK) || + (image[ip] == VM_BACK) || + (image[ip] == VM_LI_IAC) || + (image[ip] == VM_LI_IOP) || + (image[ip] == VM_PICK_IAC) || + (image[ip] == VM_PICK_IOP) || + (image[ip] == VM_RAND) || + (image[ip] == VM_ROR) || + (image[ip] == VM_RXOR)) + { + tstream[tptr++] = vm_process_tr_otab[image[ip++]]; + tstream[tptr++] = (void*) image[ip++]; + } + else tstream[tptr++] = vm_process_tr_otab[image[ip++]]; + } + else + { + printf ("[SINST] illegal opcode detected !\n"); + exit (-1); + } + } + else + { + printf ("[SINST] No space for new opcodes left !\n"); + exit (-2); + } + } + tstream[tptr++] = &&tVM_EXIT; + data[++sp] = IOP; + IOP = IAC; + IAC = c; + NEXT + fVM_XOP: TINST = tstream + image[ip++]; + TNEXT + fVM_EXE: TINST = tstream + IAC; + IAC = IOP; + IOP = data[sp--]; + TNEXT + fVM_LI_IAC: IAC = image[ip++]; + NEXT + fVM_LI_IOP: IOP = image[ip++]; + NEXT + fVM_PICK_IAC: IAC = data[image[ip++]]; + printf ("%i\n",image[ip-1]); + NEXT + fVM_PICK_IOP: IOP = data[image[ip++]]; + NEXT + fVM_RADD: IAC = IAC + IOP; + NEXT + fVM_RSUB: IAC = IOP - IAC; + NEXT + fVM_RMUL: IAC = IAC * IOP; + NEXT + fVM_RAND: IAC = IAC & image[ip++]; + NEXT + fVM_ROR: IAC = IAC | image[ip++]; + NEXT + fVM_RXOR: IAC = IAC ^ image[ip++]; + NEXT + fVM_LCALL: LNK = ip++; + ip = image[ip-1]; + NEXT + fVM_LRETURN: ip = LNK; + NEXT; fVM_DEFAULT: vm.ip = ip; vm.sp = sp; vm.rsp = rsp; + printf ("\n[ngaro] exit vm process\n"); + printf ("[ngaro] IAC: %i|",IAC); + printf ("IOP: %i|",IOP); + printf ("LNK: %i|",LNK); + printf ("SP: %i|",sp); + printf ("RSP: %i\n",rsp); } diff --git a/ngaro/c-mat/vm.h b/ngaro/c-mat/vm.h index 6a8d169..7dbd692 100755 --- a/ngaro/c-mat/vm.h +++ b/ngaro/c-mat/vm.h @@ -3,29 +3,26 @@ enum vm_opcode {VM_NOP, VM_LIT, VM_DUP, VM_DROP, VM_SWAP, VM_PUSH, VM_POP, VM_CALL, VM_JUMP, VM_RETURN, VM_GT_JUMP, VM_LT_JUMP, - VM_NE_JUMP,VM_EQ_JUMP, VM_FETCH, VM_STORE, VM_ADD, + VM_NE_JUMP, VM_EQ_JUMP, VM_FETCH, VM_STORE, VM_ADD, VM_SUB, VM_MUL, VM_DIVMOD, VM_AND, VM_OR, VM_XOR, VM_SHL, VM_SHR, VM_ZERO_EXIT, VM_INC, VM_DEC, VM_IN, VM_OUT, - VM_WAIT, VM_DEFAULT}; + VM_WAIT, VM_PICK, VM_BACK, VM_ROT, VM_SINST, VM_XOP, VM_EXE, + VM_LI_IAC, VM_LI_IOP, VM_PICK_IAC, VM_PICK_IOP, VM_RADD, + VM_RSUB, VM_RMUL, VM_RAND, VM_ROR, VM_RXOR, VM_LCALL, + VM_LRETURN, VM_DEFAULT}; -#define CELL int -#define DROP vm.data[vm.sp] = 0; vm.sp--; -#define TOS vm.data[vm.sp] -#define NOS vm.data[vm.sp-1] -#define TORS vm.address[vm.rsp] -#define NORS vm.address[vm.rsp-1] - -#define drop data[sp] = 0; sp--; -#define tos data[sp] -#define nos data[sp-1] -#define tors address[rsp] -#define nors address[rsp-1] +#define NUM_OPS 51 +#define MAX_STREAM 255 +#define STREAM_LEN 1024 #define IMAGE_SIZE 5000000 #define STACK_DEPTH 100 #define ADDRESSES 1024 -#define NEXT goto *INST = vm_process_ct_otab[vm.image[ip++]]; +#define CELL int + +#define NEXT goto *INST = vm_process_ct_otab[vm.image[ip++]]; +#define TNEXT goto **TINST++; typedef struct { int sp; @@ -35,7 +32,6 @@ typedef struct { int address[ADDRESSES]; int ports[1024]; int image[IMAGE_SIZE]; - /* This is needed to avoid corruption of the file name. A bug? */ int padding; char filename[2048]; } VM_STATE; -- 2.11.4.GIT