void timer_print(const char *what, uint64_t usec) { #if DEBUG > 1 uint64_t a = usec / 1e6; uint64_t b = usec - a * 1e6; __debug_print("TIMER", "%s: %11u.%06u\n", what, (unsigned int)a, (unsigned int)b); #endif }
/* * VM_Execute * * Description: the VM f****r */ void VM_Execute(vm_object_file_t * vm_obj, char * data, int entry) { #ifdef DEBUG_VM freopen("c:/stdout.txt", "w+", stdout); #endif long int i;//instruction pointer; long int bp;//base (stack level) pointer long int num;//data offset char * code;//bytecode pointer #define __i i #define __num num #define __code code long int opcode;//current opcode(instruction) long int curr_proc;//current procedure long int old_num;//temporary copy of 'num' static int callers_stack[512]; static int callers_stack_level = 0; #define CALLER_PUSH(n) callers_stack[callers_stack_level++] = n #define CALLER_POP(n) n = callers_stack[--callers_stack_level] code = vm_obj->code; curr_proc = entry; if ( curr_proc < 0 ) return; i = vm_obj->proc_index[curr_proc]; bp = vm_obj->stack_start; bframe.bp = bp + vm_obj->proc_sizes[curr_proc]; bframe.data = data; while ( 1 ) { opcode = code[i++]; if ( (opcode & (LOCAL-1)) < PUSHI ) { //get the general argument //(could be anything: constant, address, field offset in record ) num = *(int *)(code + i); //save it for later (in case it's a "by ref" record) old_num = num; //check to see if it's a local variable //if it is, add the local stack level //note: "by ref" vars will also take the if if ( (opcode & LOCAL) == LOCAL ) num += bp; //check to seek if it's a "by ref" value if ( (opcode & FORMAL ) == FORMAL ) { //a "by ref" value stores only an offset, so make "num" //the value of the real variable witch it initially pointed to ! num = *(int*)(data + num - old_num); //we needed to substract old_num from the address just in case //num originally was a field offset //now add old_num again (this time we need the field offset) num += old_num; //note: for ordinary vars. old_num will be 0 so will //get some redundancy } switch ( opcode & (LOCAL-1) ) { case PUSHIV: //case PUSHFV: __debug_print("pushv", code[i+4]) __asm mov edx, dword ptr [data] __asm add edx, dword ptr __num __asm push dword ptr [edx] break; case aPUSHIV: //case aPUSHFV: __debug_print("_pushv", code[i+4]) __asm pop eax __asm add dword ptr __num, eax __asm mov edx, dword ptr [data] __asm add edx, dword ptr __num __asm push dword ptr [edx] break; case PUSHSV: __debug_print("pushsv", code[i+4]) __asm mov ecx, dword ptr __code __asm add ecx, dword ptr __i __asm push dword ptr __num //offset __asm push dword ptr [ecx+5] //strlen __asm add dword ptr __i, 4 break; case aPUSHSV: __debug_print("_pushsv", code[i+4]) __asm mov ecx, dword ptr __code __asm add ecx, dword ptr __i __asm pop eax __asm add dword ptr __num, eax __asm push dword ptr __num //offset __asm push dword ptr [ecx+5] //strlen __asm add dword ptr __i, 4 break; case PUSHA: __debug_print("pusha", num) __asm push dword ptr __num break; case aPUSHA: __debug_print("_pusha", num) __asm pop eax __asm add dword ptr __num, eax __asm push dword ptr __num break; case POPI: //case POPF: //case POPA: __debug_print("pop", code[i+4]) __asm mov edx, dword ptr [data] __asm add edx, dword ptr __num __asm pop eax __asm mov dword ptr [edx], eax break; case aPOPI: //case aPOPF: //case aPOPA: __debug_print("_pop", code[i+4]) __asm mov edx, dword ptr [data] __asm add edx, dword ptr __num __asm pop eax __asm pop ebx __asm mov dword ptr [edx+ebx], eax break; case POPS: __debug_print("pops", code[i+4]) __asm mov ecx, dword ptr [esp] //pop ecx __asm mov eax, dword ptr [esp+4] //pop eax __asm mov edx, dword ptr [data] __asm lea esi, dword ptr [edx+eax] __asm mov eax, dword ptr __num __asm lea edi, dword ptr [edx+eax] __asm cld __asm rep movsb __asm add esp, 8 //clean the stack __asm add dword ptr __i, 4 break; case aPOPS: __debug_print("_pops", code[i+4]) __asm mov eax, dword ptr [esp+8] __asm add dword ptr __num, eax __asm mov ecx, dword ptr [esp] //pop ecx __asm mov eax, dword ptr [esp+4] //pop eax __asm mov edx, dword ptr [data] __asm lea esi, dword ptr [edx+eax] __asm mov eax, dword ptr __num __asm lea edi, dword ptr [edx+eax] __asm cld __asm rep movsb __asm add esp, 12 //clean the stack __asm add dword ptr __i, 4 break; default: return; } i += 5; } else switch ( opcode & (LOCAL-1) )