First full version. Added all opcodes, improved work with contexts

This commit is contained in:
Alex Vanin 2014-01-28 12:46:28 +04:00
parent 7712440064
commit 159c5ed01f
11 changed files with 767 additions and 251 deletions

View file

@ -3,11 +3,11 @@
#pragma pack(push, 1) #pragma pack(push, 1)
struct struct
{ {
char signature[4]; char signature[2];
int version; int version;
int count_const; int count_const;
int size_const; int size_const;
}First_Header; }Const_Header;
struct struct
{ {

View file

@ -31,3 +31,21 @@ context* pop_context()
node_last = node_last->prev; node_last = node_last->prev;
return last->obj; return last->obj;
} }
//Find Context in Context Stack.
context* find_context(int id)
{
context* result = NULL;
c_node* current = node_last;
while (current != NULL || current->prev != NULL)
{
if (current->obj->id == id)
{
result = current->obj;
break;
}
else
current = current->prev;
}
return result;
}

View file

@ -23,5 +23,6 @@ context* create_context(int function, func** hash,char** code);
void push_context(context*); void push_context(context*);
context* pop_context(); context* pop_context();
void remove_context(context*); void remove_context(context*);
context* find_context(int id);
#endif #endif

View file

@ -2,6 +2,8 @@
#include "CodeHeader.h" #include "CodeHeader.h"
#include <string.h> #include <string.h>
int version = 0100;
int read_bytecode(FILE* stream, func*** hash) int read_bytecode(FILE* stream, func*** hash)
{ {
int i; int i;
@ -39,21 +41,33 @@ int read_constant(FILE* stream, int* count, char*** index)
int i, j; int i, j;
char* buffer; char* buffer;
fread_s(&First_Header, sizeof(First_Header), sizeof(First_Header), 1, stream); //Reading first part of header fread_s(&Const_Header, sizeof(Const_Header), sizeof(Const_Header), 1, stream); //Reading first part of header
*(count) = First_Header.count_const; if (Const_Header.signature[0]==Const_Header.signature[1]== 0xBA)
{
printf("%s", "Wrong file-format");
return 1;
}
buffer = (char*)malloc(First_Header.size_const+1); if (Const_Header.version != version)
{
printf("%s", "Unsupported bytecode format");
return 1;
}
*(count) = Const_Header.count_const;
buffer = (char*)malloc(Const_Header.size_const+1);
buffer[0]=0; buffer[0]=0;
*(index) = (char**)malloc(sizeof(char**)*First_Header.count_const); *(index) = (char**)malloc(sizeof(char**)*Const_Header.count_const);
fread_s(buffer+1, First_Header.size_const, sizeof(char), First_Header.size_const, stream); //Reading constant values fread_s(buffer+1, Const_Header.size_const, sizeof(char), Const_Header.size_const, stream); //Reading constant values
j=0; j=0;
(*(index))[j++]=buffer; (*(index))[j++]=buffer;
for (i = 0; i<First_Header.size_const+1; i++) for (i = 0; i<Const_Header.size_const+1; i++)
{ {
if (j==First_Header.count_const) if (j>Const_Header.count_const)
break; break;
if (buffer[i] == 0) if (buffer[i] == 0)

38
VaninVM/LocalVars.c Normal file
View file

@ -0,0 +1,38 @@
#include <string.h>
#include "LocalVars.h"
long long getlocal_int(context* cont, int id)
{
long long result;
result = ((long long*)(cont->locals))[id];
return result;
}
double getlocal_double(context* cont, int id)
{
double result;
result = ((double*)(cont->locals))[id];
return result;
}
int getlocal_string(context* cont, int id)
{
long long result;
result = ((long long*)(cont->locals))[id];
return (int)result;
}
void putlocal_int(long long* num, context* cont, int id)
{
memcpy(((long long*)cont->locals)+id, num, sizeof(long long));
}
void putlocal_double(double* num, context* cont, int id)
{
memcpy(((double*)cont->locals)+id, num, sizeof(double));
}
void putlocal_string(int* str, context* cont, int id)
{
memcpy(((long long*)cont->locals)+id, (long long*)str, sizeof(long long));
}

12
VaninVM/LocalVars.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef LOCALVARS_H
#define LOCALVARS_H
#include "Context.h"
long long getlocal_int(context*, int);
double getlocal_double(context*, int);
int getlocal_string(context*, int);
void putlocal_int(long long*, context*, int);
void putlocal_double(double*, context*, int);
void putlocal_string(int*, context*, int);
#endif

View file

@ -1,11 +1,16 @@
#include "IOcode.h"
#include "TOS.h"
#include "OpCode.h" #include "OpCode.h"
#include "IOcode.h"
#include "CodeHeader.h" #include "CodeHeader.h"
#include "TOS.h"
#include "Context.h" #include "Context.h"
#include "ReturnStack.h" #include "ReturnStack.h"
#include "LocalVars.h"
long long cmp_int(long long* a, long long* b);
double cmp_double(double* a, double* b);
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -15,7 +20,7 @@ int main(int argc, char** argv)
//ExecutionProcess Variables //ExecutionProcess Variables
double d1, d2; double d1, d2;
long long i1, i2; long long i1, i2;
short s1; short s1, s2;
char* code; char* code;
int ip, startfunc; int ip, startfunc;
@ -30,9 +35,17 @@ int main(int argc, char** argv)
//Running Variable //Running Variable
int exec_status = 1; int exec_status = 1;
fopen_s(&input, "bytecode", "rb");
if (argc<2)
{
printf("%s", "File is not specified");
return 1;
}
fopen_s(&input, argv[1], "rb");
//const_pull //const_pull
read_constant(input, &const_count, &const_index); if (read_constant(input, &const_count, &const_index) != 0)
return 1;
//code_pull //code_pull
startfunc = read_bytecode(input, &phash_table); startfunc = read_bytecode(input, &phash_table);
fclose(input); fclose(input);
@ -43,196 +56,559 @@ int main(int argc, char** argv)
ip = 0; ip = 0;
current_context = create_context(startfunc, phash_table, &code); current_context = create_context(startfunc, phash_table, &code);
node_last = NULL;
while (exec_status) while (exec_status)
{ {
switch (code[ip]) switch (code[ip])
{ {
case INVALID: case INVALID:
//DO(INVALID, "Invalid instruction.", 1) //DO(INVALID, "Invalid instruction.", 1)
ip++; break; ip++; break;
case DLOAD: case DLOAD:
//DO(DLOAD, "Load double on TOS, inlined into insn stream.", 9) //DO(DLOAD, "Load double on TOS, inlined into insn stream.", 9)
d1 = *((double*)(code+(++ip))); d1 = *((double*)(code+(++ip)));
push_double(d1);
ip+=8; break;
case ILOAD:
//DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9)
i1 = *((long long*)(code+(++ip)));
push_int(i1);
ip+=8; break;
case SLOAD:
s1 = *((short*)(code+(++ip)));
push_int((long long)(const_index[s1]));
ip+=2; break;
case DLOAD0:
// DO(DLOAD0, "Load double 0 on TOS.", 1)
push_double(0);
ip++; break;
case ILOAD0:
//DO(ILOAD0, "Load int 0 on TOS.", 1)
push_int(0);
ip++; break;
case SLOAD0:
//DO(SLOAD0, "Load empty string on TOS.", 1)
push_int((long long)(const_index[0]));
ip++; break;
case DLOAD1:
//DO(DLOAD1, "Load double 1 on TOS.", 1)
push_double(1);
ip++; break;
case ILOAD1:
//DO(ILOAD1, "Load int 1 on TOS.", 1)
push_int(1);
ip++; break;
case DLOADM1:
//DO(DLOADM1, "Load double -1 on TOS.", 1)
push_double(-1);
ip++; break;
case ILOADM1:
//DO(ILOADM1, "Load int -1 on TOS.", 1)
push_int(-1);
ip++; break;
case DADD:
//DO(DADD, "Add 2 doubles on TOS, push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 += d2;
push_double(d1);
ip++; break;
case IADD:
//DO(IADD, "Add 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 += i2;
push_int(i1);
ip++; break;
case DSUB:
//DO(DSUB, "Subtract 2 doubles on TOS (lower from upper), push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d2 -= d1;
push_double(d2);
ip++; break;
case ISUB:
//DO(ISUB, "Subtract 2 ints on TOS (lower from upper), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i2 -= i1;
push_int(i2);
ip++; break;
case DMUL:
//DO(DMUL, "Multiply 2 doubles on TOS, push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 *= d2;
push_double(d1);
ip++; break;
case IMUL:
//DO(IMUL, "Multiply 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 *= i2;
push_int(i1);
ip++; break;
case DDIV:
//DO(DDIV, "Divide 2 doubles on TOS (upper to lower), push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 = d1/d2;
push_double(d1);
ip++; break;
case IDIV:
//DO(IDIV, "Divide 2 ints on TOS (upper to lower), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1/i2;
push_int(i1);
ip++; break;
case IMOD:
//DO(IMOD, "Modulo operation on 2 ints on TOS (upper to lower), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1 % i2;
push_int(i1);
ip++; break;
case DNEG:
//DO(DNEG, "Negate double on TOS.", 1)
d1 = pop_double();
d1 = -d1;
push_double(d1);
ip++; break;
case INEG:
//DO(INEG, "Negate int on TOS.", 1)
i1 = pop_int();
i1 = - i1;
push_int(i1);
ip++; break;
case IAOR:
//DO(IAOR, "Arithmetic OR of 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1 | i2;
push_int(i1);
ip++; break;
case IAAND:
//DO(IAAND, "Arithmetic AND of 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1 & i2;
push_int(i1);
ip++; break;
case IAXOR:
//DO(IAXOR, "Arithmetic XOR of 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1 ^ i2;
push_int(i1);
ip++; break;
case IPRINT:
//DO(IPRINT, "Pop and print integer TOS.", 1)
i1 = pop_int();
printf("%llu", i1);
ip++; break;
case DPRINT:
//DO(DPRINT, "Pop and print double TOS.", 1)
d1 = pop_double();
printf("%f", d1);
ip++; break;
case SPRINT:
//DO(SPRINT, "Pop and print string TOS.", 1)
i1 = pop_int();
printf("%s", (char*)i1);
ip++; break;
case I2D:
//DO(I2D, "Convert int on TOS to double.", 1)
i1 = pop_int();
d1 = (double)i1;
push_double(d1);
ip++; break;
case D2I:
//DO(D2I, "Convert double on TOS to int.", 1)
d1 = pop_double();
i1 = (int)d1;
push_int(i1);
ip++; break;
case S2I:
//DO(S2I, "Convert string on TOS to int.", 1)
ip++; break;
case SWAP:
//DO(SWAP, "Swap 2 topmost values.", 1)
i1 = pop_int();
i2 = pop_int();
push_int(i1);
push_int(i2);
ip++; break;
case POP:
//DO(POP, "Remove topmost value.", 1)
TOS--;
ip++; break;
case LOADDVAR0:
//DO(LOADDVAR0, "Load double from variable 0, push on TOS.", 1)
d1 = getlocal_double(current_context, 0);
push_double(d1);
ip++;break;
case LOADDVAR1:
//DO(LOADDVAR1, "Load double from variable 1, push on TOS.", 1)
d1 = getlocal_double(current_context, 1);
push_double(d1);
ip++;break;
case LOADDVAR2:
//DO(LOADDVAR2, "Load double from variable 2, push on TOS.", 1)
d1 = getlocal_double(current_context, 2);
push_double(d1);
ip++;break;
case LOADDVAR3:
//DO(LOADDVAR3, "Load double from variable 3, push on TOS.", 1)
d1 = getlocal_double(current_context, 3);
push_double(d1);
ip++; break;
case LOADIVAR0:
//DO(LOADIVAR0, "Load int from variable 0, push on TOS.", 1)
i1 = getlocal_int(current_context, 0);
push_int(i1);
ip++; break;
case LOADIVAR1:
//DO(LOADIVAR1, "Load int from variable 1, push on TOS.", 1)
i1 = getlocal_int(current_context, 1);
push_int(i1);
ip++; break;
case LOADIVAR2:
//DO(LOADIVAR2, "Load int from variable 2, push on TOS.", 1)
i1 = getlocal_int(current_context, 2);
push_int(i1);
ip++; break;
case LOADIVAR3:
//DO(LOADIVAR3, "Load int from variable 3, push on TOS.", 1)
i1 = getlocal_int(current_context, 3);
push_int(i1);
ip++; break;
case LOADSVAR0:
//DO(LOADSVAR0, "Load string from variable 0, push on TOS.", 1)
i1 = (long long)getlocal_string(current_context, 0);
push_int(i1);
ip++; break;
case LOADSVAR1:
//DO(LOADSVAR1, "Load string from variable 1, push on TOS.", 1)
i1 = (long long)getlocal_string(current_context, 1);
push_int(i1);
ip++; break;
case LOADSVAR2:
//DO(LOADSVAR2, "Load string from variable 2, push on TOS.", 1)
i1 = (long long)getlocal_string(current_context, 2);
push_int(i1);
ip++; break;
case LOADSVAR3:
//DO(LOADSVAR3, "Load string from variable 3, push on TOS.", 1)
i1 = (long long)getlocal_string(current_context, 3);
push_int(i1);
ip++; break;
case STOREDVAR0:
//DO(STOREDVAR0, "Pop TOS and store to double variable 0.", 1)
d1 = pop_double();
putlocal_double(&d1, current_context, 0);
ip++; break;
case STOREDVAR1:
//DO(STOREDVAR1, "Pop TOS and store to double variable 1.", 1)
d1 = pop_double();
putlocal_double(&d1, current_context, 1);
ip++; break;
case STOREDVAR2:
//DO(STOREDVAR2, "Pop TOS and store to double variable 2.", 1)
d1 = pop_double();
putlocal_double(&d1, current_context, 2);
ip++; break;
case STOREDVAR3:
//DO(STOREDVAR3, "Pop TOS and store to double variable 3.", 1)
d1 = pop_double();
putlocal_double(&d1, current_context, 3);
ip++; break;
case STOREIVAR0:
//DO(STOREIVAR0, "Pop TOS and store to int variable 0.", 1)
i1 = pop_int();
putlocal_int(&i1, current_context, 0);
ip++; break;
case STOREIVAR1:
//DO(STOREIVAR1, "Pop TOS and store to int variable 1.", 1)
i1 = pop_int();
putlocal_int(&i1, current_context, 1);
ip++; break;
case STOREIVAR2:
//DO(STOREIVAR2, "Pop TOS and store to int variable 2.", 1)
i1 = pop_int();
putlocal_int(&i1, current_context, 2);
ip++; break;
case STOREIVAR3:
//DO(STOREIVAR3, "Pop TOS and store to int variable 3.", 1)
i1 = pop_int();
putlocal_int(&i1, current_context, 3);
ip++; break;
case STORESVAR0:
//DO(STORESVAR0, "Pop TOS and store to string variable 0.", 1)
i1 = pop_int();
putlocal_string((int*)&i1, current_context, 0);
ip++; break;
case STORESVAR1:
//DO(STORESVAR1, "Pop TOS and store to string variable 1.", 1)
i1 = pop_int();
putlocal_string((int*)&i1, current_context, 1);
ip++; break;
case STORESVAR2:
//DO(STORESVAR2, "Pop TOS and store to string variable 2.", 1)
i1 = pop_int();
putlocal_string((int*)&i1, current_context, 2);
ip++; break;
case STORESVAR3:
//DO(STORESVAR3, "Pop TOS and store to string variable 3.", 1)
i1 = pop_int();
putlocal_string((int*)&i1, current_context, 3);
ip++; break;
case LOADDVAR:
//DO(LOADDVAR, "Load double from variable, whose 2-byte is id inlined to insn stream, push on TOS.", 3)
s1 = *((short*)(code+(++ip)));
d1 = getlocal_double(current_context, s1);
push_double(d1);
ip+=2; break;
case LOADIVAR:
//DO(LOADIVAR, "Load int from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3)
s1 = *((short*)(code+(++ip)));
i1 = getlocal_int(current_context, s1);
push_int(i1);
ip+=2; break;
case LOADSVAR:
//DO(LOADSVAR, "Load string from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3)
s1 = *((short*)(code+(++ip)));
i1 = (long long)getlocal_string(current_context, s1);
push_int(i1);
ip+=2; break;
case STOREDVAR:
//DO(STOREDVAR, "Pop TOS and store to double variable, whose 2-byte id is inlined to insn stream.", 3)
s1 = *((short*)(code+(++ip)));
d1 = pop_double();
putlocal_double(&d1, current_context, s1);
ip+=2; break;
case STOREIVAR:
//DO(STOREIVAR, "Pop TOS and store to int variable, whose 2-byte id is inlined to insn stream.", 3)
s1 = *((short*)(code+(++ip)));
i1 = pop_int();
putlocal_int(&i1, current_context, s1);
ip+=2; break;
case STORESVAR:
//DO(STORESVAR, "Pop TOS and store to string variable, whose 2-byte id is inlined to insn stream.", 3)
s1 = *((short*)(code+(++ip)));
i1 = pop_int();
putlocal_string((int*)&i1, current_context, s1);
ip+=2; break;
case LOADCTXDVAR:
//DO(LOADCTXDVAR, "Load double from variable, whose 2-byte context and 2-byte id inlined to insn stream, push on TOS.", 5)
s1 = *((short*)(code+(++ip)));
ip+=2;
s2 = *((short*)(code+(ip)));
if (find_context(s1) != NULL)
{
d1 = getlocal_double(find_context(s1), s2);
push_double(d1); push_double(d1);
ip+=8; break; }
case ILOAD: else
//DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9) {
i1 = *((long long*)(code+(++ip))); printf("%s", "Context Not Found");
push_int(i1);
ip+=8; break;
case SLOAD:
s1 = *((short*)(code+(++ip)));
push_int((long long)(const_index[s1]));
ip+=2; break;
case DLOAD0:
// DO(DLOAD0, "Load double 0 on TOS.", 1)
push_double(0);
ip++; break;
case ILOAD0:
//DO(ILOAD0, "Load int 0 on TOS.", 1)
push_int(0);
ip++; break;
case DLOAD1:
//DO(DLOAD1, "Load double 1 on TOS.", 1)
push_double(1);
ip++; break;
case ILOAD1:
//DO(ILOAD1, "Load int 1 on TOS.", 1)
push_int(1);
ip++; break;
case DLOADM1:
//DO(DLOADM1, "Load double -1 on TOS.", 1)
push_double(-1);
ip++; break;
case ILOADM1:
//DO(ILOADM1, "Load int -1 on TOS.", 1)
push_int(-1);
ip++; break;
case DADD:
//DO(DADD, "Add 2 doubles on TOS, push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 += d2;
push_double(d1);
ip++; break;
case IADD:
//DO(IADD, "Add 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 += i2;
push_int(i1);
ip++; break;
case DSUB:
//DO(DSUB, "Subtract 2 doubles on TOS (lower from upper), push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 -= d2;
push_double(d1);
ip++; break;
case ISUB:
//DO(ISUB, "Subtract 2 ints on TOS (lower from upper), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 -= i2;
push_int(i1);
ip++; break;
case DMUL:
//DO(DMUL, "Multiply 2 doubles on TOS, push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 *= d2;
push_double(d1);
ip++; break;
case IMUL:
//DO(IMUL, "Multiply 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 *= i2;
push_int(i1);
ip++; break;
case DDIV:
//DO(DDIV, "Divide 2 doubles on TOS (upper to lower), push value back.", 1)
d1 = pop_double();
d2 = pop_double();
d1 /= d2;
push_double(d1);
ip++; break;
case IDIV:
//DO(IDIV, "Divide 2 ints on TOS (upper to lower), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 /= i2;
push_int(i1);
ip++; break;
case IMOD:
//DO(IMOD, "Modulo operation on 2 ints on TOS (upper to lower), push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 %= i2;
push_int(i1);
ip++; break;
case DNEG:
//DO(DNEG, "Negate double on TOS.", 1)
d1 = pop_double();
d1 = -d1;
push_double(d1);
ip++; break;
case INEG:
//DO(INEG, "Negate int on TOS.", 1)
i1 = pop_int();
i1 = - i1;
push_int(i1);
ip++; break;
case IAOR:
//DO(IAOR, "Arithmetic OR of 2 ints on TOS, push value back.", 1)
i1 = pop_int();
i2 = pop_int();
i1 = i1 | i2;
push_int(i1);
ip++; break;
case IAAND:
//DO(IAAND, "Arithmetic AND of 2 ints on TOS, push value back.", 1)
ip++; break;
case IAXOR:
//DO(IAXOR, "Arithmetic XOR of 2 ints on TOS, push value back.", 1)
case IPRINT:
//DO(IPRINT, "Pop and print integer TOS.", 1)
i1 = pop_int();
printf("%d", i1);
ip++; break;
case DPRINT:
//DO(DPRINT, "Pop and print double TOS.", 1)
d1 = pop_double();
printf("%f", d1);
ip++; break;
case SPRINT:
//DO(SPRINT, "Pop and print string TOS.", 1)
i1 = pop_int();
printf("%s", (char*)i1);
ip++; break;
case I2D:
//DO(I2D, "Convert int on TOS to double.", 1)
i1 = pop_int();
d1 = (double)i1;
push_double(d1);
ip++; break;
case D2I:
//DO(D2I, "Convert double on TOS to int.", 1)
d1 = pop_double();
i1 = (int)d1;
push_int(i1);
ip++; break;
case SWAP:
//DO(SWAP, "Swap 2 topmost values.", 1)
i1 = pop_int();
i2 = pop_int();
push_int(i1);
push_int(i2);
ip++; break;
case POP:
//DO(POP, "Remove topmost value.", 1)
TOS--;
ip++; break;
case STOP:
//DO(STOP, "Stop execution.", 1)
exec_status = 0; exec_status = 0;
break; }
case CALL: ip+=2; break;
s1 = *((short*)(code+(++ip))); case LOADCTXIVAR:
ip+=2; push_ret(ip); //DO(LOADCTXIVAR, "Load int from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5)
push_context(current_context); s1 = *((short*)(code+(++ip)));
current_context = create_context(s1, phash_table, &code); ip+=2;
ip = 0; break; s2 = *((short*)(code+(ip)));
case RETURN: if (find_context(s1) != NULL)
remove_context(current_context); {
current_context = pop_context(); i1 = getlocal_int(find_context(s1), s2);
code = phash_table[current_context->id]->code; push_int(i1);
ip = pop_ret(); break; }
else
{
printf("%s", "Context Not Found");
exec_status = 0;
}
ip+=2; break;
case LOADCTXSVAR:
//DO(LOADCTXSVAR, "Load string from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5)
s1 = *((short*)(code+(++ip)));
ip+=2;
s2 = *((short*)(code+(ip)));
if (find_context(s1) != NULL)
{
i1 = (long long)getlocal_string(find_context(s1), s2);
push_double(i1);
}
else
{
printf("%s", "Context Not Found");
exec_status = 0;
}
ip+=2; break;
case STORECTXDVAR:
//DO(STORECTXDVAR, "Pop TOS and store to double variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5)
s1 = *((short*)(code+(++ip)));
ip+=2;
s2 = *((short*)(code+(ip)));
d1 = pop_double();
if (find_context(s1) != NULL)
{
putlocal_double(&d1, find_context(s1), s2);
}
else
{
printf("%s", "Context Not Found");
exec_status = 0;
}
ip+=2; break;
case STORECTXIVAR:
//DO(STORECTXIVAR, "Pop TOS and store to int variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5)
s1 = *((short*)(code+(++ip)));
ip+=2;
s2 = *((short*)(code+(ip)));
i1 = pop_int();
if (find_context(s1) != NULL)
{
putlocal_int(&i1, find_context(s1), s2);
}
else
{
printf("%s", "Context Not Found");
exec_status = 0;
}
ip+=2; break;
case STORECTXSVAR:
//DO(STORECTXSVAR, "Pop TOS and store to string variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5)
s1 = *((short*)(code+(++ip)));
ip+=2;
s2 = *((short*)(code+(ip)));
i1 = pop_int();
if (find_context(s1) != NULL)
{
putlocal_string((int*)&d1, find_context(s1), s2);
}
else
{
printf("%s", "Context Not Found");
exec_status = 0;
}
ip+=2; break;
case DCMP:
//DO(DCMP, "Compare 2 topmost doubles, pushing libc-style comparator value cmp(upper, lower) as integer.", 1)
d1 = TOS[tp-1];
d2 = TOS[tp-2];
push_double(cmp_double(&d1, &d2));
ip++; break;
case ICMP:
//DO(ICMP, "Compare 2 topmost ints, pushing libc-style comparator value cmp(upper, lower) as integer.", 1)
i1 = get_int(tp-1);
i2 = get_int(tp-2);
push_int(cmp_int(&i1, &i2));
ip++; break;
case JA:
//DO(JA, "Jump always, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip += (2+s1); break;
case IFICMPNE:
// DO(IFICMPNE, "Compare two topmost integers and jump if upper != lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 != i2)
ip += s1;
break;
case IFICMPE:
//DO(IFICMPE, "Compare two topmost integers and jump if upper == lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 == i2)
ip += s1;
break;
case IFICMPG:
//DO(IFICMPG, "Compare two topmost integers and jump if upper > lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 > i2)
ip += s1;
break;
case IFICMPGE:
//DO(IFICMPGE, "Compare two topmost integers and jump if upper >= lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 >= i2)
ip += s1;
break;
case IFICMPL:
//DO(IFICMPL, "Compare two topmost integers and jump if upper < lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 < i2)
ip += s1;
break;
case IFICMPLE:
//DO(IFICMPLE, "Compare two topmost integers and jump if upper <= lower, next two bytes - signed offset of jump destination.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2;
i1 = get_int(tp-1);
i2 = get_int(tp-2);
if (i1 <= i2)
ip += s1;
break;
case DUMP:
//DO(DUMP, "Dump value on TOS, without removing it.", 1)
i1 = get_int(tp-1);
d1 = TOS[tp-1];
printf("TOS: Double:%e Integer:%llu Hex:%#08llx", d1, i1, i1);
ip++; break;
case STOP:
//DO(STOP, "Stop execution.", 1)
exec_status = 0;
break;
case CALL:
//DO(CALL, "Call function, next two bytes - unsigned function id.", 3)
s1 = *((short*)(code+(++ip)));
ip+=2; push_ret(ip);
push_context(current_context);
current_context = create_context(s1, phash_table, &code);
ip = 0; break;
case RETURN:
//DO(RETURN, "Return to call location", 1)
remove_context(current_context);
current_context = pop_context();
code = phash_table[current_context->id]->code;
ip = pop_ret(); break;
case BREAK:
//DO(BREAK, "Breakpoint for the debugger.", 1)
getchar();
ip++; break;
} }
} }
remove_context(current_context); remove_context(current_context);
getchar();
return 0; return 0;
} }
double cmp_double(long long* a, long long* b)
{
if (*a == *b) return 0;
else if (*a > *b) return 1;
else return -1;
}
long long cmp_int(long long* a, long long* b)
{
if (*a == *b) return 0;
else if (*a > *b) return 1;
else return -1;
}

View file

@ -8,6 +8,7 @@ enum opcode
SLOAD, SLOAD,
DLOAD0, DLOAD0,
ILOAD0, ILOAD0,
SLOAD0,
DLOAD1, DLOAD1,
ILOAD1, ILOAD1,
DLOADM1, DLOADM1,
@ -31,10 +32,58 @@ enum opcode
SPRINT, SPRINT,
I2D, I2D,
D2I, D2I,
S2I,
SWAP, SWAP,
POP, POP,
LOADDVAR0,
LOADDVAR1,
LOADDVAR2,
LOADDVAR3,
LOADIVAR0,
LOADIVAR1,
LOADIVAR2,
LOADIVAR3,
LOADSVAR0,
LOADSVAR1,
LOADSVAR2,
LOADSVAR3,
STOREDVAR0,
STOREDVAR1,
STOREDVAR2,
STOREDVAR3,
STOREIVAR0,
STOREIVAR1,
STOREIVAR2,
STOREIVAR3,
STORESVAR0,
STORESVAR1,
STORESVAR2,
STORESVAR3,
LOADDVAR,
LOADIVAR,
LOADSVAR,
STOREDVAR,
STOREIVAR,
STORESVAR,
LOADCTXDVAR,
LOADCTXIVAR,
LOADCTXSVAR,
STORECTXDVAR,
STORECTXIVAR,
STORECTXSVAR,
DCMP,
ICMP,
JA,
IFICMPNE,
IFICMPE,
IFICMPG,
IFICMPGE,
IFICMPL,
IFICMPLE,
DUMP,
STOP, STOP,
CALL, CALL,
RETURN RETURN,
BREAK
}; };
#endif #endif

View file

@ -15,6 +15,13 @@ long long pop_int()
return number.num_i; return number.num_i;
} }
long long get_int(int id)
{
tos_num number;
number.num_d = TOS[id];
return number.num_i;
}
void push_double(double num) void push_double(double num)
{ {
TOS[tp++] = num; TOS[tp++] = num;

View file

@ -13,6 +13,7 @@ int initTOS();
void push_int(long long); void push_int(long long);
void push_double(double); void push_double(double);
long long pop_int(); long long pop_int();
long long get_int(int);
double pop_double(); double pop_double();
#endif #endif

View file

@ -1,11 +1,11 @@
#define FOR_BYTECODES(DO) \ #define FOR_BYTECODES(DO) \
-DO(INVALID, "Invalid instruction.", 1) \ ?-DO(INVALID, "Invalid instruction.", 1) \
+DO(DLOAD, "Load double on TOS, inlined into insn stream.", 9) \ +DO(DLOAD, "Load double on TOS, inlined into insn stream.", 9) \
+DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9) \ +DO(ILOAD, "Load int on TOS, inlined into insn stream.", 9) \
+DO(SLOAD, "Load string reference on TOS, next two bytes - constant id.", 3) \ +DO(SLOAD, "Load string reference on TOS, next two bytes - constant id.", 3) \
+DO(DLOAD0, "Load double 0 on TOS.", 1) \ +DO(DLOAD0, "Load double 0 on TOS.", 1) \
+DO(ILOAD0, "Load int 0 on TOS.", 1) \ +DO(ILOAD0, "Load int 0 on TOS.", 1) \
DO(SLOAD0, "Load empty string on TOS.", 1) \ +DO(SLOAD0, "Load empty string on TOS.", 1) \
+DO(DLOAD1, "Load double 1 on TOS.", 1) \ +DO(DLOAD1, "Load double 1 on TOS.", 1) \
+DO(ILOAD1, "Load int 1 on TOS.", 1) \ +DO(ILOAD1, "Load int 1 on TOS.", 1) \
+DO(DLOADM1, "Load double -1 on TOS.", 1) \ +DO(DLOADM1, "Load double -1 on TOS.", 1) \
@ -26,60 +26,60 @@
+DO(IAXOR, "Arithmetic XOR of 2 ints on TOS, push value back.", 1) \ +DO(IAXOR, "Arithmetic XOR of 2 ints on TOS, push value back.", 1) \
+DO(IPRINT, "Pop and print integer TOS.", 1) \ +DO(IPRINT, "Pop and print integer TOS.", 1) \
+DO(DPRINT, "Pop and print double TOS.", 1) \ +DO(DPRINT, "Pop and print double TOS.", 1) \
DO(SPRINT, "Pop and print string TOS.", 1) \ +DO(SPRINT, "Pop and print string TOS.", 1) \
+DO(I2D, "Convert int on TOS to double.", 1) \ +DO(I2D, "Convert int on TOS to double.", 1) \
+DO(D2I, "Convert double on TOS to int.", 1) \ +DO(D2I, "Convert double on TOS to int.", 1) \
DO(S2I, "Convert string on TOS to int.", 1) \ +DO(S2I, "Convert string on TOS to int.", 1) \
+DO(SWAP, "Swap 2 topmost values.", 1) \ +DO(SWAP, "Swap 2 topmost values.", 1) \
+DO(POP, "Remove topmost value.", 1) \ +DO(POP, "Remove topmost value.", 1) \
DO(LOADDVAR0, "Load double from variable 0, push on TOS.", 1) \ +DO(LOADDVAR0, "Load double from variable 0, push on TOS.", 1) \
DO(LOADDVAR1, "Load double from variable 1, push on TOS.", 1) \ +DO(LOADDVAR1, "Load double from variable 1, push on TOS.", 1) \
DO(LOADDVAR2, "Load double from variable 2, push on TOS.", 1) \ +DO(LOADDVAR2, "Load double from variable 2, push on TOS.", 1) \
DO(LOADDVAR3, "Load double from variable 3, push on TOS.", 1) \ +DO(LOADDVAR3, "Load double from variable 3, push on TOS.", 1) \
DO(LOADIVAR0, "Load int from variable 0, push on TOS.", 1) \ +DO(LOADIVAR0, "Load int from variable 0, push on TOS.", 1) \
DO(LOADIVAR1, "Load int from variable 1, push on TOS.", 1) \ +DO(LOADIVAR1, "Load int from variable 1, push on TOS.", 1) \
DO(LOADIVAR2, "Load int from variable 2, push on TOS.", 1) \ +DO(LOADIVAR2, "Load int from variable 2, push on TOS.", 1) \
DO(LOADIVAR3, "Load int from variable 3, push on TOS.", 1) \ +DO(LOADIVAR3, "Load int from variable 3, push on TOS.", 1) \
DO(LOADSVAR0, "Load string from variable 0, push on TOS.", 1) \ +DO(LOADSVAR0, "Load string from variable 0, push on TOS.", 1) \
DO(LOADSVAR1, "Load string from variable 1, push on TOS.", 1) \ +DO(LOADSVAR1, "Load string from variable 1, push on TOS.", 1) \
DO(LOADSVAR2, "Load string from variable 2, push on TOS.", 1) \ +DO(LOADSVAR2, "Load string from variable 2, push on TOS.", 1) \
DO(LOADSVAR3, "Load string from variable 3, push on TOS.", 1) \ +DO(LOADSVAR3, "Load string from variable 3, push on TOS.", 1) \
DO(STOREDVAR0, "Pop TOS and store to double variable 0.", 1) \ +DO(STOREDVAR0, "Pop TOS and store to double variable 0.", 1) \
DO(STOREDVAR1, "Pop TOS and store to double variable 1.", 1) \ +DO(STOREDVAR1, "Pop TOS and store to double variable 1.", 1) \
DO(STOREDVAR2, "Pop TOS and store to double variable 2.", 1) \ +DO(STOREDVAR2, "Pop TOS and store to double variable 2.", 1) \
DO(STOREDVAR3, "Pop TOS and store to double variable 3.", 1) \ +DO(STOREDVAR3, "Pop TOS and store to double variable 3.", 1) \
DO(STOREIVAR0, "Pop TOS and store to int variable 0.", 1) \ +DO(STOREIVAR0, "Pop TOS and store to int variable 0.", 1) \
DO(STOREIVAR1, "Pop TOS and store to int variable 1.", 1) \ +DO(STOREIVAR1, "Pop TOS and store to int variable 1.", 1) \
DO(STOREIVAR2, "Pop TOS and store to int variable 2.", 1) \ +DO(STOREIVAR2, "Pop TOS and store to int variable 2.", 1) \
DO(STOREIVAR3, "Pop TOS and store to int variable 3.", 1) \ +DO(STOREIVAR3, "Pop TOS and store to int variable 3.", 1) \
DO(STORESVAR0, "Pop TOS and store to string variable 0.", 1) \ +DO(STORESVAR0, "Pop TOS and store to string variable 0.", 1) \
DO(STORESVAR1, "Pop TOS and store to string variable 1.", 1) \ +DO(STORESVAR1, "Pop TOS and store to string variable 1.", 1) \
DO(STORESVAR2, "Pop TOS and store to string variable 2.", 1) \ +DO(STORESVAR2, "Pop TOS and store to string variable 2.", 1) \
DO(STORESVAR3, "Pop TOS and store to string variable 3.", 1) \ +DO(STORESVAR3, "Pop TOS and store to string variable 3.", 1) \
DO(LOADDVAR, "Load double from variable, whose 2-byte is id inlined to insn stream, push on TOS.", 3) \ +DO(LOADDVAR, "Load double from variable, whose 2-byte is id inlined to insn stream, push on TOS.", 3) \
DO(LOADIVAR, "Load int from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \ +DO(LOADIVAR, "Load int from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \
DO(LOADSVAR, "Load string from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \ +DO(LOADSVAR, "Load string from variable, whose 2-byte id is inlined to insn stream, push on TOS.", 3) \
DO(STOREDVAR, "Pop TOS and store to double variable, whose 2-byte id is inlined to insn stream.", 3) \ +DO(STOREDVAR, "Pop TOS and store to double variable, whose 2-byte id is inlined to insn stream.", 3) \
DO(STOREIVAR, "Pop TOS and store to int variable, whose 2-byte id is inlined to insn stream.", 3) \ +DO(STOREIVAR, "Pop TOS and store to int variable, whose 2-byte id is inlined to insn stream.", 3) \
DO(STORESVAR, "Pop TOS and store to string variable, whose 2-byte id is inlined to insn stream.", 3) \ +DO(STORESVAR, "Pop TOS and store to string variable, whose 2-byte id is inlined to insn stream.", 3) \
DO(LOADCTXDVAR, "Load double from variable, whose 2-byte context and 2-byte id inlined to insn stream, push on TOS.", 5) \ +DO(LOADCTXDVAR, "Load double from variable, whose 2-byte context and 2-byte id inlined to insn stream, push on TOS.", 5) \
DO(LOADCTXIVAR, "Load int from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \ +DO(LOADCTXIVAR, "Load int from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \
DO(LOADCTXSVAR, "Load string from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \ +DO(LOADCTXSVAR, "Load string from variable, whose 2-byte context and 2-byte id is inlined to insn stream, push on TOS.", 5) \
DO(STORECTXDVAR, "Pop TOS and store to double variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ +DO(STORECTXDVAR, "Pop TOS and store to double variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \
DO(STORECTXIVAR, "Pop TOS and store to int variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ +DO(STORECTXIVAR, "Pop TOS and store to int variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \
DO(STORECTXSVAR, "Pop TOS and store to string variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \ +DO(STORECTXSVAR, "Pop TOS and store to string variable, whose 2-byte context and 2-byte id is inlined to insn stream.", 5) \
DO(DCMP, "Compare 2 topmost doubles, pushing libc-style comparator value cmp(upper, lower) as integer.", 1) \ ?+DO(DCMP, "Compare 2 topmost doubles, pushing libc-style comparator value cmp(upper, lower) as integer.", 1) \
DO(ICMP, "Compare 2 topmost ints, pushing libc-style comparator value cmp(upper, lower) as integer.", 1) \ ?+DO(ICMP, "Compare 2 topmost ints, pushing libc-style comparator value cmp(upper, lower) as integer.", 1) \
DO(JA, "Jump always, next two bytes - signed offset of jump destination.", 3) \ +DO(JA, "Jump always, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPNE, "Compare two topmost integers and jump if upper != lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPNE, "Compare two topmost integers and jump if upper != lower, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPE, "Compare two topmost integers and jump if upper == lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPE, "Compare two topmost integers and jump if upper == lower, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPG, "Compare two topmost integers and jump if upper > lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPG, "Compare two topmost integers and jump if upper > lower, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPGE, "Compare two topmost integers and jump if upper >= lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPGE, "Compare two topmost integers and jump if upper >= lower, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPL, "Compare two topmost integers and jump if upper < lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPL, "Compare two topmost integers and jump if upper < lower, next two bytes - signed offset of jump destination.", 3) \
DO(IFICMPLE, "Compare two topmost integers and jump if upper <= lower, next two bytes - signed offset of jump destination.", 3) \ +DO(IFICMPLE, "Compare two topmost integers and jump if upper <= lower, next two bytes - signed offset of jump destination.", 3) \
DO(DUMP, "Dump value on TOS, without removing it.", 1) \ +DO(DUMP, "Dump value on TOS, without removing it.", 1) \
+DO(STOP, "Stop execution.", 1) \ +DO(STOP, "Stop execution.", 1) \
DO(CALL, "Call function, next two bytes - unsigned function id.", 3) \ +DO(CALL, "Call function, next two bytes - unsigned function id.", 3) \
DO(CALLNATIVE, "Call native function, next two bytes - id of the native function.", 3) \ ?DO(CALLNATIVE, "Call native function, next two bytes - id of the native function.", 3) \
DO(RETURN, "Return to call location", 1) \ +DO(RETURN, "Return to call location", 1) \
DO(BREAK, "Breakpoint for the debugger.", 1) ?+DO(BREAK, "Breakpoint for the debugger.", 1)