diff options
Diffstat (limited to 'src/virtualmachine')
| -rw-r--r-- | src/virtualmachine/Exceptions.h | 100 | ||||
| -rw-r--r-- | src/virtualmachine/JustInTime.cpp | 1144 | ||||
| -rw-r--r-- | src/virtualmachine/Operations.cpp | 356 | ||||
| -rw-r--r-- | src/virtualmachine/Operations.inl | 60 | ||||
| -rw-r--r-- | src/virtualmachine/Syscalls.cpp | 99 | ||||
| -rw-r--r-- | src/virtualmachine/Syscalls.inl | 14 | ||||
| -rw-r--r-- | src/virtualmachine/VirtualMachine.cpp | 405 | ||||
| -rw-r--r-- | src/virtualmachine/VirtualMachine.h | 282 |
8 files changed, 0 insertions, 2460 deletions
diff --git a/src/virtualmachine/Exceptions.h b/src/virtualmachine/Exceptions.h deleted file mode 100644 index 3a25e87..0000000 --- a/src/virtualmachine/Exceptions.h +++ /dev/null @@ -1,100 +0,0 @@ -#pragma once -#include <stdexcept> -#include <cstring> -#include "Format.h" - -namespace vm -{ - class RuntimeException: public std::exception - { - char * error; - public: - RuntimeException() : error(NULL) {} - RuntimeException(char * message) : error(strdup(message)) {} - const char * what() const throw() - { - if(error) - return error; - else - return "VirtualMachine runtime exception"; - } - ~RuntimeException() throw() {}; - }; - - class StackOverflowException: public RuntimeException - { - public: - StackOverflowException() {} - const char * what() const throw() - { - return "VirtualMachine Stack overflow"; - } - ~StackOverflowException() throw() {}; - }; - - class StackUnderflowException: public RuntimeException - { - public: - StackUnderflowException() {} - const char * what() const throw() - { - return "VirtualMachine Stack underflow"; - } - ~StackUnderflowException() throw() {}; - }; - - class AccessViolationException: public RuntimeException - { - int address; - char * _what; - public: - AccessViolationException(int address = 0) : address(address) - { - _what = strdup(std::string("VirtualMachine Access violation at "+format::NumberToString<int>(address)).c_str()); - } - const char * what() const throw() - { - if(address) - return _what; - return "VirtualMachine Access violation"; - } - ~AccessViolationException() throw() {}; - }; - - class JITException: public RuntimeException - { - char * _what; - public: - JITException(const char * what2) - { - _what = strdup(what2); - } - const char * what() const throw() - { - return _what; - } - ~JITException() throw() {}; - }; - - class OutOfMemoryException: public RuntimeException - { - public: - OutOfMemoryException() {} - const char * what() const throw() - { - return "VirtualMachine Out of memory"; - } - ~OutOfMemoryException() throw() {}; - }; - - class InvalidProgramException: public RuntimeException - { - public: - InvalidProgramException() {} - const char * what() const throw() - { - return "Could not load program"; - } - ~InvalidProgramException() throw() {}; - }; -} diff --git a/src/virtualmachine/JustInTime.cpp b/src/virtualmachine/JustInTime.cpp deleted file mode 100644 index 9f6fe57..0000000 --- a/src/virtualmachine/JustInTime.cpp +++ /dev/null @@ -1,1144 +0,0 @@ -#ifdef VMJIT - -#include <cstdio> -#include "VirtualMachine.h" - -#ifdef WIN32 -#include "Windows.h" -#endif - -namespace vm -{ - #define OP(n) OP##n - /* - - eax scratch - ebx scratch - ecx scratch (required for shifts) - edx scratch (required for divisions) - esi RP - edi DP - - */ - - // TTimo: initialised the statics, this fixes a crash when entering a compiled VM - static unsigned char *buf = NULL; - static unsigned char *jused = NULL; - static int compiledOfs = 0; - static int pc = 0; - - //static int callMask = 0; // bk001213 - init - static int eDP; - static int eRP; - static int instruction, pass; - static int lastConst = 0; - static int oc0, oc1, pop0, pop1; - - static int eRamMask = 0; - static int eRomMask = 0; - static int * eInstructionPointers = NULL; - - static int eSyscallNum; - static void * eRam = NULL; - static VirtualMachine * eVM = NULL; - - static int callFromCompiledPtr = (int)VirtualMachine::callFromCompiled; - static int callSyscallPtr = (int)VirtualMachine::callSyscall; - - typedef enum - { - LAST_COMMAND_NONE = 0, - LAST_COMMAND_MOV_EDI_EAX, - LAST_COMMAND_SUB_DI_4, - LAST_COMMAND_SUB_DI_8, - } ELastCommand; - - static ELastCommand LastCommand; - - void VirtualMachine::callSyscall() - { - //throw RuntimeException("Turd"); - - /*VirtualMachine * savedVM; - int * callOpStack2; - - savedVM = eVM; - callOpStack2 = (int*)eOpStack; - - // save the stack to allow recursive VM entry - eVM->DP = eDP - 4; - *(int *)((byte *)eVM->ram + eDP + 4) = eSyscallNum; - //VM_LogSyscalls( (int *)((byte *)currentVM->dataBase + programStack + 4) ); - *(callOpStack2+1) = eVM->syscall( *(int *)((unsigned char *)eVM->ram + eDP + 4) ); - - eVM = savedVM;*/ - } - - void VirtualMachine::callFromCompiled() - { - /*__asm__("doAsmCall: \n\t" \ - " movl (%%edi),%%eax \n\t" \ - " subl $4,%%edi \n\t" \ - " orl %%eax,%%eax \n\t" \ - " jl systemCall \n\t" \ - " shll $2,%%eax \n\t" \ - " addl %3,%%eax \n\t" \ - " call *(%%eax) \n\t" \ - " movl (%%edi),%%eax \n\t" \ - " andl %5, %%eax \n\t" \ - " jmp doret \n\t" \ - "systemCall: \n\t" \ - " negl %%eax \n\t" \ - " decl %%eax \n\t" \ - " movl %%eax,%0 \n\t" \ - " movl %%esi,%1 \n\t" \ - " movl %%edi,%2 \n\t" \ - " pushl %%ecx \n\t" \ - " pushl %%esi \n\t" \ - " pushl %%edi \n\t" \ - " call *%4 \n\t" \ - " popl %%edi \n\t" \ - " popl %%esi \n\t" \ - " popl %%ecx \n\t" \ - " addl $4,%%edi \n\t" \ - "doret: \n\t" \ - " ret \n\t" \ - : "=rm" (eSyscallNum), "=rm" (eDP), "=rm" (eOpStack) \ - : "rm" (eInstructionPointers), "r" (callSyscall), "m" (eRomMask) \ - : "ax", "di", "si", "cx" \ - );*/ - //" call *%4 \n\t" - - //" negl %%eax \n\t" - // " decl %%eax \n\t" - __asm__ volatile ("doAsmCall: \n\t" \ - " movl (%%edi),%%eax \n\t" \ - " subl $4,%%edi \n\t" \ - " orl %%eax,%%eax \n\t" \ - " jl systemCall \n\t" \ - " shll $2,%%eax \n\t" \ - " addl %3,%%eax \n\t" \ - " call *(%%eax) \n\t" \ - " movl (%%edi),%%eax \n\t" \ - " andl %5, %%eax \n\t" \ - " ret \n\t" \ - "systemCall: \n\t" \ - " movl %%eax,%0 \n\t" \ - " movl %%esi,%1 \n\t" \ - " movl %%edi,%2 \n\t" \ - " pushl %%ecx \n\t" \ - " pushl %%esi \n\t" \ - " pushl %%edi \n\t" \ - : "=rm" (eSyscallNum), "=rm" (eRP), "=rm" (eDP) \ - : "rm" (eInstructionPointers), "r" (callSyscall), "m" (eRomMask) \ - : "ax", "di", "si", "cx" \ - ); - //printf("Syscall: %d\n", eSyscallNum); - //throw RuntimeException("Turd"); - - eVM->DP = eDP-((int)eRam); - eVM->syscall(eSyscallNum); - eDP = eVM->DP+((int)eRam)-4; - - //" addl $4,%edi \n\t" - // " ret \n\t" - __asm__ volatile ("popl %edi \n\t" \ - " popl %esi \n\t" \ - " popl %ecx \n\t" \ - "doret: \n\t" \ - ); - } - - int VirtualMachine::CallCompiled(int address) - { - //int stack[1024]; - //int stack[100]; - int programStack; - int stackOnEntry; - unsigned char * image; - void * entryPoint; - int * oldInstructionPointers; - void * oldDataStack; - - oldDataStack = eRam; - oldInstructionPointers = eInstructionPointers; - - eVM = this; - eInstructionPointers = instructionPointers; - - eRomMask = romMask; - eRamMask = ramMask; - - // we might be called recursively, so this might not be the very top - eDP = ((int)ram)+DP; - stackOnEntry = DP; - - // set up the stack frame - image = (unsigned char *)ram;//vm->dataBase; - - eDP -= 48; - - //*(int *)&image[ programStack + 44] = args[9]; - //*(int *)&image[ programStack + 40] = args[8]; - //*(int *)&image[ programStack + 36] = args[7]; - //*(int *)&image[ programStack + 32] = args[6]; - //*(int *)&image[ programStack + 28] = args[5]; - //*(int *)&image[ programStack + 24] = args[4]; - //*(int *)&image[ programStack + 20] = args[3]; - //*(int *)&image[ programStack + 16] = args[2]; - //*(int *)&image[ programStack + 12] = args[1]; - //*(int *)&image[ programStack + 8 ] = args[0]; - //*(int *)&image[ programStack + 4 ] = 0; // return stack - //*(int *)&image[ programStack ] = -1; // will terminate the loop on return - - // off we go into generated code... - entryPoint = compiledRom;//0;//vm->codeBase; - eRam = ram+dataStack; - - #if defined(_MSC_VER) - __asm { - pushad - mov esi, DP; - mov edi, opStack - call entryPoint - mov DP, esi - mov opStack, edi - popad - } - #else - { - static int memDP; - static int memRP; - static void *memEntryPoint; - - memDP = DP+((int)ram); - memRP = RP; - memEntryPoint = entryPoint; - - __asm__(" pushal \r\n" \ - " movl %0,%%esi \r\n" \ - " movl %1,%%edi \r\n" \ - " call *%2 \r\n" \ - " movl %%esi,%0 \r\n" \ - " movl %%edi,%1 \r\n" \ - " popal \r\n" \ - : "=m" (memRP), "=m" (memDP) \ - : "m" (memEntryPoint), "0" (memRP), "1" (memDP) \ - : "si", "di" \ - ); - - DP = memDP-((int)ram); - RP = memRP; - } - #endif - - if ( eRam != ram+dataStack ) { - throw RuntimeException("opStack corrupted in compiled code"); - } - if ( DP != stackOnEntry+4 ) { - printf("DP: %d, stackOnEntry: %d\n", DP, stackOnEntry); - throw RuntimeException("programStack corrupted in compiled code"); - } - - DP = stackOnEntry; - - // in case we were recursively called by another vm - eInstructionPointers = oldInstructionPointers; - eRam = oldDataStack; - - return 0;//*(int *)eOpStack; - } - - bool VirtualMachine::Compile() - { - Instruction op; - int maxLength; - int v; - int i; - bool opt; - - // allocate a very large temp buffer, we will shrink it later - maxLength = romSize * 8; - buf = new unsigned char[maxLength]; - jused = new unsigned char[romSize + 2]; - instructionPointers = new int[romSize]; - std::fill(jused, jused+romSize+2, 0); - - for(pass=0; pass<2; pass++) { - oc0 = -23423; - oc1 = -234354; - pop0 = -43435; - pop1 = -545455; - - // translate all instructions - pc = 0; - instruction = 0; - compiledOfs = 0; - - LastCommand = LAST_COMMAND_NONE; - - while (instruction < romSize) - { - if (compiledOfs > maxLength - 16) - { - throw JITException("Compile: maxLength exceeded"); - } - - instructionPointers[instruction] = compiledOfs; - instruction++; - - if (pc > romSize) - { - throw JITException("Compile: program counter run off the edge"); - } - - op = rom[pc]; - pc++; - switch ( op.Operation ) - { - case 0: - break; - case OP(BREAK): - emitInstruction( "CC" ); // int 3 - break; - case OP(ENTER): - //emitInstruction( "CC" ); // int 3 - emitInstruction( "81 EE" ); // sub esi, 0x12345678 - emit4( constant4() ); - break; - case OP(CONST): - if (rom[pc].Operation == OP(LOAD4)) - { - emitAddEDI4(); - emitInstruction( "BB" ); // mov ebx, 0x12345678 - emit4( (constant4()&ramMask) + (int)ram); - emitInstruction( "8B 03" ); // mov eax, dword ptr [ebx] - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - pc++; // OP(LOAD4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(LOAD2)) - { - emitAddEDI4(); - emitInstruction( "BB" ); // mov ebx, 0x12345678 - emit4( (constant4()&ramMask) + (int)ram); - emitInstruction( "0F B7 03" ); // movzx eax, word ptr [ebx] - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - pc++; // OP(LOAD4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(LOAD1)) - { - emitAddEDI4(); - emitInstruction( "BB" ); // mov ebx, 0x12345678 - emit4( (constant4()&ramMask) + (int)ram); - emitInstruction( "0F B6 03" ); // movzx eax, byte ptr [ebx] - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - pc++; // OP(LOAD4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(STORE4)) - { - opt = emitMovEBXEDI((ramMask & ~3)); - emitInstruction( "B8" ); // mov eax, 0x12345678 - emit4( constant4() ); - // if (!opt) { - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask & ~3 ); - // } - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - pc++; // OP(STORE4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(STORE2)) - { - opt = emitMovEBXEDI((ramMask & ~1)); - emitInstruction( "B8" ); // mov eax, 0x12345678 - emit4( constant4() ); - // if (!opt) { - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask & ~1 ); - // } - emitInstruction( "66 89 83" ); // mov word ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - pc++; // OP(STORE4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(STORE1)) - { - opt = emitMovEBXEDI(ramMask); - emitInstruction( "B8" ); // mov eax, 0x12345678 - emit4( constant4() ); - // if (!opt) { - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask ); - // } - emitInstruction( "88 83" ); // mov byte ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - pc++; // OP(STORE4) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(ADD)) - { - emitInstruction( "81 07" ); // add dword ptr [edi], 0x1234567 - emit4( constant4() ); - pc++; // OP(ADD) - instruction += 1; - break; - } - if (rom[pc].Operation == OP(SUB)) - { - emitInstruction( "81 2F" ); // sub dword ptr [edi], 0x1234567 - emit4( constant4() ); - pc++; // OP(ADD) - instruction += 1; - break; - } - emitAddEDI4(); - emitInstruction( "C7 07" ); // mov dword ptr [edi], 0x12345678 - lastConst = constant4(); - emit4( lastConst ); - if (rom[pc].Operation == OP(JUMP)) - { - jused[lastConst] = 1; - } - break; - case OP(LOCAL): - emitAddEDI4(); - emitInstruction( "8D 86" ); // lea eax, [0x12345678 + esi] - oc0 = oc1; - oc1 = constant4(); - emit4( oc1 ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - case OP(ARG): - emitMovEAXEDI(); // mov eax,dword ptr [edi] - emitInstruction( "89 86" ); // mov dword ptr [esi+ram],eax - // FIXME: range check - emit4( constant1() + (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(CALL): - emitInstruction("C7 86"); // mov dword ptr [esi+ram],0x12345678 - emit4((int)ram); - emit4(pc); - emitInstruction("FF 15"); // call callFromCompiled - emit4((int)&callFromCompiledPtr); - break; - case OP(PUSH): - emitAddEDI4(); - break; - case OP(POP): - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(LEAVE): - v = constant4(); - emitInstruction( "81 C6" ); // add esi, 0x12345678 - emit4( v ); - emitInstruction( "C3" ); // ret - break; - case OP(LOAD4): - if (rom[pc].Operation == OP(CONST) && rom[pc+1].Operation == OP(ADD) && rom[pc+2].Operation == OP(STORE4)) - { - if (oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) - { - compiledOfs -= 11; - instructionPointers[ instruction-1 ] = compiledOfs; - } - pc++; // OP(CONST) - v = constant4(); - emitMovEBXEDI(ramMask); - if (v == 1 && oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) - { - emitInstruction( "FF 83"); // inc dword ptr [ebx + 0x12345678] - emit4( (int)ram ); - } - else - { - emitInstruction( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678] - emit4( (int)ram ); - emitInstruction( "05" ); // add eax, const - emit4( v ); - if (oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) - { - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - } - else - { - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "8B 1F" ); // mov ebx, dword ptr [edi] - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - } - } - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - pc++; // OP(ADD) - pc++; // OP(STORE) - instruction += 3; - break; - } - - if (rom[pc].Operation == OP(CONST) && rom[pc+1].Operation == OP(SUB) && rom[pc+2].Operation == OP(STORE4)) - { - if (oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) { - compiledOfs -= 11; - instructionPointers[ instruction-1 ] = compiledOfs; - } - emitMovEBXEDI(ramMask); - emitInstruction( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678] - emit4( (int)ram ); - pc++; // OP(CONST) - v = constant4(); - if (v == 1 && oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) - { - emitInstruction( "FF 8B"); // dec dword ptr [ebx + 0x12345678] - emit4( (int)ram ); - } - else - { - emitInstruction( "2D" ); // sub eax, const - emit4( v ); - if (oc0 == oc1 && pop0 == OP(LOCAL) && pop1 == OP(LOCAL)) - { - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - } - else - { - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "8B 1F" ); // mov ebx, dword ptr [edi] - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - } - } - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - pc++; // OP(SUB) - pc++; // OP(STORE) - instruction += 3; - break; - } - - if (buf[compiledOfs-2] == 0x89 && buf[compiledOfs-1] == 0x07) - { - compiledOfs -= 2; - instructionPointers[ instruction-1 ] = compiledOfs; - emitInstruction( "8B 80"); // mov eax, dword ptr [eax + 0x1234567] - emit4( (int)ram ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - } - emitMovEBXEDI(ramMask); - emitInstruction( "8B 83" ); // mov eax, dword ptr [ebx + 0x12345678] - emit4( (int)ram ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - case OP(LOAD2): - emitMovEBXEDI(ramMask); - emitInstruction( "0F B7 83" ); // movzx eax, word ptr [ebx + 0x12345678] - emit4( (int)ram ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - case OP(LOAD1): - emitMovEBXEDI(ramMask); - emitInstruction( "0F B6 83" ); // movzx eax, byte ptr [ebx + 0x12345678] - emit4( (int)ram ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - case OP(STORE4): - emitMovEAXEDI(); - emitInstruction( "8B 5F FC" ); // mov ebx, dword ptr [edi-4] - // if (pop1 != OP(CALL)) { - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask & ~3 ); - // } - emitInstruction( "89 83" ); // mov dword ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - break; - case OP(STORE2): - emitMovEAXEDI(); - emitInstruction( "8B 5F FC" ); // mov ebx, dword ptr [edi-4] - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask & ~1 ); - emitInstruction( "66 89 83" ); // mov word ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - break; - case OP(STORE1): - emitMovEAXEDI(); - emitInstruction( "8B 5F FC" ); // mov ebx, dword ptr [edi-4] - // emitInstruction( "81 E3" ); // and ebx, 0x12345678 - // emit4( ramMask ); - emitInstruction( "88 83" ); // mov byte ptr [ebx+0x12345678], eax - emit4( (int)ram ); - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - break; - - case OP(EQ): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "75 06" ); // jne +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(NE): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "74 06" ); // je +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LTI): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "7D 06" ); // jnl +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LEI): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "7F 06" ); // jnle +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GTI): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "7E 06" ); // jng +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GEI): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "7C 06" ); // jnge +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LTU): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "73 06" ); // jnb +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LEU): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "77 06" ); // jnbe +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GTU): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "76 06" ); // jna +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GEU): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "8B 47 04" ); // mov eax, dword ptr [edi+4] - emitInstruction( "3B 47 08" ); // cmp eax, dword ptr [edi+8] - emitInstruction( "72 06" ); // jnae +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(EQF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 40" ); // test ah,0x40 - emitInstruction( "74 06" ); // je +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(NEF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 40" ); // test ah,0x40 - emitInstruction( "75 06" ); // jne +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LTF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 01" ); // test ah,0x01 - emitInstruction( "74 06" ); // je +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(LEF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 41" ); // test ah,0x41 - emitInstruction( "74 06" ); // je +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GTF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 41" ); // test ah,0x41 - emitInstruction( "75 06" ); // jne +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(GEF): - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - emitInstruction( "D9 47 04" ); // fld dword ptr [edi+4] - emitInstruction( "D8 5F 08" ); // fcomp dword ptr [edi+8] - emitInstruction( "DF E0" ); // fnstsw ax - emitInstruction( "F6 C4 01" ); // test ah,0x01 - emitInstruction( "75 06" ); // jne +6 - emitInstruction( "FF 25" ); // jmp [0x12345678] - v = constant4(); - jused[v] = 1; - emit4( (int)instructionPointers + v*4 ); - break; - case OP(NEGI): - emitInstruction( "F7 1F" ); // neg dword ptr [edi] - break; - case OP(ADD): - emitMovEAXEDI(); // mov eax, dword ptr [edi] - emitInstruction( "01 47 FC" ); // add dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(SUB): - emitMovEAXEDI(); // mov eax, dword ptr [edi] - emitInstruction( "29 47 FC" ); // sub dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(DIVI): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "99" ); // cdq - emitInstruction( "F7 3F" ); // idiv dword ptr [edi] - emitInstruction( "89 47 FC" ); // mov dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(DIVU): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "33 D2" ); // xor edx, edx - emitInstruction( "F7 37" ); // div dword ptr [edi] - emitInstruction( "89 47 FC" ); // mov dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(MODI): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "99" ); // cdq - emitInstruction( "F7 3F" ); // idiv dword ptr [edi] - emitInstruction( "89 57 FC" ); // mov dword ptr [edi-4],edx - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(MODU): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "33 D2" ); // xor edx, edx - emitInstruction( "F7 37" ); // div dword ptr [edi] - emitInstruction( "89 57 FC" ); // mov dword ptr [edi-4],edx - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(MULI): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "F7 2F" ); // imul dword ptr [edi] - emitInstruction( "89 47 FC" ); // mov dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(MULU): - emitInstruction( "8B 47 FC" ); // mov eax,dword ptr [edi-4] - emitInstruction( "F7 27" ); // mul dword ptr [edi] - emitInstruction( "89 47 FC" ); // mov dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(BAND): - emitMovEAXEDI(); // mov eax, dword ptr [edi] - emitInstruction( "21 47 FC" ); // and dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(BOR): - emitMovEAXEDI(); // mov eax, dword ptr [edi] - emitInstruction( "09 47 FC" ); // or dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(BXOR): - emitMovEAXEDI(); // mov eax, dword ptr [edi] - emitInstruction( "31 47 FC" ); // xor dword ptr [edi-4],eax - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(BCOM): - emitInstruction( "F7 17" ); // not dword ptr [edi] - break; - case OP(LSH): - emitInstruction( "8B 0F" ); // mov ecx, dword ptr [edi] - emitInstruction( "D3 67 FC" ); // shl dword ptr [edi-4], cl - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(RSHI): - emitInstruction( "8B 0F" ); // mov ecx, dword ptr [edi] - emitInstruction( "D3 7F FC" ); // sar dword ptr [edi-4], cl - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(RSHU): - emitInstruction( "8B 0F" ); // mov ecx, dword ptr [edi] - emitInstruction( "D3 6F FC" ); // shr dword ptr [edi-4], cl - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(NEGF): - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "D9 E0" ); // fchs - emitInstruction( "D9 1F" ); // fstp dword ptr [edi] - break; - case OP(ADDF): - emitInstruction( "D9 47 FC" ); // fld dword ptr [edi-4] - emitInstruction( "D8 07" ); // fadd dword ptr [edi] - emitInstruction( "D9 5F FC" ); // fstp dword ptr [edi-4] - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - break; - case OP(SUBF): - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "D8 67 04" ); // fsub dword ptr [edi+4] - emitInstruction( "D9 1F" ); // fstp dword ptr [edi] - break; - case OP(DIVF): - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "D8 77 04" ); // fdiv dword ptr [edi+4] - emitInstruction( "D9 1F" ); // fstp dword ptr [edi] - break; - case OP(MULF): - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "D8 4f 04" ); // fmul dword ptr [edi+4] - emitInstruction( "D9 1F" ); // fstp dword ptr [edi] - break; - case OP(CVIF): - emitInstruction( "DB 07" ); // fild dword ptr [edi] - emitInstruction( "D9 1F" ); // fstp dword ptr [edi] - break; - case OP(CVFI): - #ifndef FTOL_PTR // WHENHELLISFROZENOVER // bk001213 - was used in 1.17 - // not IEEE complient, but simple and fast - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "DB 1F" ); // fistp dword ptr [edi] - #else // FTOL_PTR - // call the library conversion function - emitInstruction( "D9 07" ); // fld dword ptr [edi] - emitInstruction( "FF 15" ); // call ftolPtr - emit4( (int)&ftolPtr ); - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - #endif - break; - case OP(SEX8): - emitInstruction( "0F BE 07" ); // movsx eax, byte ptr [edi] - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - case OP(SEX16): - emitInstruction( "0F BF 07" ); // movsx eax, word ptr [edi] - emitCommand(LAST_COMMAND_MOV_EDI_EAX); // mov dword ptr [edi], eax - break; - - case OP(BLOCK_COPY): - // FIXME: range check - emitInstruction( "56" ); // push esi - emitInstruction( "57" ); // push edi - emitInstruction( "8B 37" ); // mov esi,[edi] - emitInstruction( "8B 7F FC" ); // mov edi,[edi-4] - emitInstruction( "B9" ); // mov ecx,0x12345678 - emit4( constant4() >> 2 ); - emitInstruction( "B8" ); // mov eax, ramMask - emit4( ramMask ); - emitInstruction( "BB" ); // mov ebx, ram - emit4( (int)ram ); - emitInstruction( "23 F0" ); // and esi, eax - emitInstruction( "03 F3" ); // add esi, ebx - emitInstruction( "23 F8" ); // and edi, eax - emitInstruction( "03 FB" ); // add edi, ebx - emitInstruction( "F3 A5" ); // rep movsd - emitInstruction( "5F" ); // pop edi - emitInstruction( "5E" ); // pop esi - emitCommand(LAST_COMMAND_SUB_DI_8); // sub edi, 8 - break; - - case OP(JUMP): - emitCommand(LAST_COMMAND_SUB_DI_4); // sub edi, 4 - emitInstruction( "8B 47 04" ); // mov eax,dword ptr [edi+4] - // FIXME: range check - emitInstruction( "FF 24 85" ); // jmp dword ptr [instructionPointers + eax * 4] - emit4( (int)instructionPointers ); - break; - default: - throw JITException("Compile: bad opcode"); - } - pop0 = pop1; - pop1 = op.Operation; - } - } - - // copy to an exact size buffer on the hunk - //codeLength = compiledOfs; - //codeBase = Hunk_Alloc( compiledOfs, h_low ); - - //Com_Memcpy( codeBase, buf, compiledOfs ); - - compiledRom = new char[compiledOfs]; - std::copy(buf, buf+compiledOfs, compiledRom); - compiledRomSize = compiledOfs; - compiledRomMask = compiledOfs; - - delete[] buf; - delete[] jused; - - //printf( "VM file %s compiled to %i bytes of code\n", name, compiledOfs); - - // offset all the instruction pointers for the new location - for ( i = 0 ; i < /*header->instructionCount*/ romSize ; i++ ) { - instructionPointers[i] += (int)rom; - } - -#ifdef WIN32 - VirtualProtect(compiledRom, compiledRomSize, PAGE_EXECUTE, NULL); -#endif - #if 0 // ndef _WIN32 - // Must make the newly generated code executable - { - int r; - unsigned long addr; - int psize = getpagesize(); - - addr = ((int)codeBase & ~(psize-1)) - psize; - - r = mprotect((char*)addr, codeLength + (int)codeBase - addr + psize, - PROT_READ | PROT_WRITE | PROT_EXEC ); - - if (r < 0) - Com_Error( ERR_FATAL, "mprotect failed to change PROT_EXEC" ); - } - #endif - return true; - - } - - int VirtualMachine::constant4() - { - int v; - - v = rom[pc-1].Parameter.int4;// | (rom[pc-1].Parameter<<8) | (rom[pc-1].Parameter<<16) | (rom[pc-1].Parameter<<24); - return v; - } - - int VirtualMachine::constant1() - { - int v; - - v = rom[pc-1].Parameter.uint1; - return v; - } - - void VirtualMachine::emit1(int v) - { - buf[compiledOfs] = v; - compiledOfs++; - - LastCommand = LAST_COMMAND_NONE; - } - - void VirtualMachine::emit4(int v) - { - emit1(v & 255); - emit1((v >> 8) & 255); - emit1((v >> 16) & 255); - emit1((v >> 24) & 255); - } - - void VirtualMachine::emitInstruction(const char *string) - { - int c1, c2; - int v; - - while (true) - { - c1 = string[0]; - c2 = string[1]; - - v = (hex( c1 ) << 4) | hex(c2); - emit1( v ); - - if (!string[2]) - { - break; - } - string += 3; - } - } - - void VirtualMachine::emitCommand(int command_) - { - ELastCommand command = (ELastCommand)command_; - switch(command) - { - case LAST_COMMAND_MOV_EDI_EAX: - emitInstruction( "89 07" ); // mov dword ptr [edi], eax - break; - case LAST_COMMAND_SUB_DI_4: - emitInstruction( "83 EF 04" ); // sub edi, 4 - break; - case LAST_COMMAND_SUB_DI_8: - emitInstruction( "83 EF 08" ); // sub edi, 8 - break; - default: - break; - } - LastCommand = command; - } - - void VirtualMachine::emitAddEDI4() - { - if (LastCommand == LAST_COMMAND_SUB_DI_4 && jused[instruction-1] == 0) - { // sub di,4 - compiledOfs -= 3; - instructionPointers[ instruction-1 ] = compiledOfs; - return; - } - if (LastCommand == LAST_COMMAND_SUB_DI_8 && jused[instruction-1] == 0) - { // sub di,8 - compiledOfs -= 3; - instructionPointers[ instruction-1 ] = compiledOfs; - emitInstruction( "83 EF 04" ); // sub edi,4 - return; - } - emitInstruction( "83 C7 04" ); // add edi,4 - } - - void VirtualMachine::emitMovEAXEDI() - { - if (LastCommand == LAST_COMMAND_MOV_EDI_EAX) - { // mov [edi], eax - compiledOfs -= 2; - instructionPointers[ instruction-1 ] = compiledOfs; - return; - } - if (pop1 == OP(DIVI) || pop1 == OP(DIVU) || pop1 == OP(MULI) || pop1 == OP(MULU) || pop1 == OP(STORE4) || pop1 == OP(STORE2) || pop1 == OP(STORE1) ) - { - return; - } - if (pop1 == OP(CONST) && buf[compiledOfs-6] == 0xC7 && buf[compiledOfs-5] == 0x07) - { // mov edi, 0x123456 - compiledOfs -= 6; - instructionPointers[ instruction-1 ] = compiledOfs; - emitInstruction( "B8" ); // mov eax, 0x12345678 - emit4( lastConst ); - return; - } - emitInstruction( "8B 07" ); // mov eax, dword ptr [edi] - } - - bool VirtualMachine::emitMovEBXEDI(int andit) - { - if (LastCommand == LAST_COMMAND_MOV_EDI_EAX) - { // mov [edi], eax - compiledOfs -= 2; - instructionPointers[ instruction-1 ] = compiledOfs; - emitInstruction( "8B D8"); // mov bx, eax - return false; - } - if (pop1 == OP(DIVI) || pop1 == OP(DIVU) || pop1 == OP(MULI) || pop1 == OP(MULU) || pop1 == OP(STORE4) || pop1 == OP(STORE2) || pop1 == OP(STORE1) ) - { - emitInstruction( "8B D8"); // mov bx, eax - return false; - } - if (pop1 == OP(CONST) && buf[compiledOfs-6] == 0xC7 && buf[compiledOfs-5] == 0x07 ) - { // mov edi, 0x123456 - compiledOfs -= 6; - instructionPointers[ instruction-1 ] = compiledOfs; - emitInstruction( "BB" ); // mov ebx, 0x12345678 - if (andit) { - emit4( lastConst & andit ); - } else { - emit4( lastConst ); - } - return true; - } - - emitInstruction( "8B 1F" ); // mov ebx, dword ptr [edi] - return false; - } - - int VirtualMachine::hex(int c) - { - if (c >= 'a' && c <= 'f') - return 10 + c - 'a'; - if (c >= 'A' && c <= 'F') - return 10 + c - 'A'; - if (c >= '0' && c <= '9') - return c - '0'; - - throw JITException("hex: bad character"); - - return 0; - } - - #undef OP -} - -#endif diff --git a/src/virtualmachine/Operations.cpp b/src/virtualmachine/Operations.cpp deleted file mode 100644 index 0c998a8..0000000 --- a/src/virtualmachine/Operations.cpp +++ /dev/null @@ -1,356 +0,0 @@ -#include "VirtualMachine.h" - -namespace vm -{ - #define OPDEF(n) &VirtualMachine::Op##n, - OperationFunction VirtualMachine::operations[] = - { - #include "Operations.inl" - }; - #undef OPDEF - - #define OPDEF(n) int VirtualMachine::Op##n(word parameter) - - #define R0 (r[0]) - #define R1 (r[1]) - #define R2 (r[2]) - - - OPDEF(UNDEF) - { - /* Die horribly. */ - throw RuntimeException(); - return -1; - } - - OPDEF(IGNORE) - { - /* NOP */ - throw RuntimeException(); - return 0; - } - - OPDEF(BREAK) - { - /* Usage never spotted. */ - /* Die horribly? */ - throw RuntimeException(); - return -1; - } - - /* - Stack on entering... - - no locals: ENTER 8 - 1 words locals: ENTER 16 - 2 words locals: ENTER 20 - 3 words locals: ENTER 24 - etc. - - address of argument: - ADDRFP4 v => OP_LOCAL (16 + currentLocals + currentArgs + v) - address of local: - ADDRLP4 v => OP_LOCAL (8 + currentArgs + v) - - RP [ ] ??? (oldPC?) - [ ] ??? - [ ] \ - ... > locals (args marshalling) - [ ] / - [ ] \ - ... > locals - [ ] / (ADDRLP4 v => OP_LOCAL (8 + currentArgs + v)) - (oldRP?) [ ] ??? - [ ] ??? - [ ] (my args?) - ... - [ ] - */ - - OPDEF(ENTER) /* ??? */ - { - while (parameter.int4 > (2 * sizeof(word))) - { - RPush<int4_t>(0); /* init zero */ - parameter.int4 -= sizeof(word); - } - RPush(Pop()); //Program Counter - RPush<int4_t>(0); //Unknown - return 0; - } - - OPDEF(LEAVE) /* ??? */ - { - RPop(); //Unknown - parameter.int4 -= sizeof(word); - PC = RPop<int4_t>(); //Program counter - parameter.int4 -= sizeof(word); - while (parameter.int4 > 0) - { - RPop(); - parameter.int4 -= sizeof(word); - } - return 0; - } - - OPDEF(CALL) /* Call subroutine. */ - { - R0 = Pop(); - Push<int4_t>(PC); - PC = R0.int4; - return 0; - } - - OPDEF(PUSH) /* [DP] <- 0; DP++ */ - { - Push(0); - return 0; - } - - OPDEF(POP) /* DP-- */ - { - Pop(); - return 0; - } - - OPDEF(CONST) /* [DP] <- parm; DP++ */ - { - Push(parameter); - return 0; - } - - OPDEF(LOCAL) /* [DP] <- [RP-n] */ - { - Push<int4_t>(RP + parameter.int4); - return 0; - } - - OPDEF(JUMP) /* PC <- [DP] */ - { - PC = Pop<int4_t>(); - return 0; - } - - #define CMP(type, op) \ - { \ - R0 = Pop(); \ - cm = (Pop<type##_t>() op R0.type); \ - if (cm) \ - PC = parameter.uint4; \ - return 0; \ - } - - OPDEF(EQ) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, ==) - - OPDEF(NE) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, !=) - - OPDEF(LTI) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, <) - - OPDEF(LEI) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, <=) - - OPDEF(GTI) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, >) - - OPDEF(GEI) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(int4, >=) - - OPDEF(LTU) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(uint4, <) - - OPDEF(LEU) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(uint4, <=) - - OPDEF(GTU) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(uint4, >) - - OPDEF(GEU) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(uint4, >=) - - OPDEF(EQF) /* if [DP] == [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, ==) - - OPDEF(NEF) /* if [DP] != [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, !=) - - OPDEF(LTF) /* if [DP] < [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, <) - - OPDEF(LEF) /* if [DP] <= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, <=) - - OPDEF(GTF) /* if [DP] > [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, >) - - OPDEF(GEF) /* if [DP] >= [DP-1] then PC <- parm; DP <- DP-2 */ - CMP(float4, >=) - - - OPDEF(LOAD1) /* [DP] <- [[DP]] */ - { - Push<uint1_t>(Get<uint1_t>(Pop<uint4_t>())); - return 0; - } - - OPDEF(LOAD2) /* [DP] <- [[DP]] */ - { - Push<uint2_t>(Get<uint2_t>(Pop<uint4_t>())); - return 0; - } - - OPDEF(LOAD4) /* [DP] <- [[DP]] */ - { - Push<uint4_t>(Get<uint4_t>(Pop<uint4_t>())); - return 0; - } - - OPDEF(STORE1) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set<uint1_t>(Pop<uint4_t>(), Pop<uint1_t>()); - return 0; - } - - OPDEF(STORE2) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set<uint2_t>(Pop<uint4_t>(), Pop<uint2_t>()); - return 0; - } - - OPDEF(STORE4) /* [DP-1] <- [DP]; DP <- DP-2 */ - { - Set<uint4_t>(Pop<uint4_t>(), Pop<uint4_t>()); - return 0; - } - - OPDEF(ARG) /* Marshal TOS to to-call argument list */ - { - Marshal(parameter.uint1, Pop()); - return 0; - } - - OPDEF(BLOCK_COPY) /* XXX */ - { - R1 = Pop(); - R0 = Pop(); - if(R0.int4 >= 0 && R0.int4 + parameter.int4 < ramSize && R1.int4 >= 0 && R1.int4 + parameter.int4 < ramSize) - memcpy(ram + R0.int4, ram + R1.int4, parameter.int4); - else - throw AccessViolationException(); - return -1; - } - - OPDEF(SEX8) /* Sign-extend 8-bit */ - { - R0 = Pop(); - if(R0.uint4 & 0x80) - R0.uint4 |= 0xFFFFFF80; - Push(R0); - return 0; - } - - OPDEF(SEX16) /* Sign-extend 16-bit */ - { - R0 = Pop(); - if(R0.uint4 & 0x8000) - R0.uint4 |= 0xFFFF8000; - Push(R0); - return 0; - } - - #define UNOP(type, op) \ - { \ - Push<type##_t>(op Pop<type##_t>()); \ - return 0; \ - } - - #define BINOP(type, op) \ - { \ - R0 = Pop(); \ - Push<type##_t>(Pop<type##_t>() op R0.type); \ - return 0; \ - } - - OPDEF(NEGI) /* [DP] <- -[DP] */ - UNOP(int4, -) - - OPDEF(ADD) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */ - BINOP(int4, +) - - OPDEF(SUB) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */ - BINOP(int4, -) - - OPDEF(DIVI) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */ - BINOP(int4, /) - - OPDEF(DIVU) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */ - BINOP(uint4, /) - - OPDEF(MODI) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */ - BINOP(int4, %) - - OPDEF(MODU) /* [DP-1] <- [DP-1] % [DP]; DP <- DP-1 */ - BINOP(uint4, %) - - OPDEF(MULI) /* [DP-1] <- [DP-1] * [DP]; DP <- DP-1 */ - BINOP(int4, *) - - OPDEF(MULU) /* [DP-1] <- [DP-1] * [DP]; DP <- OP-1 */ - BINOP(uint4, *) - - OPDEF(BAND) /* [DP-1] <- [DP-1] & [DP]; DP <- DP-1 */ - BINOP(uint4, &) - - OPDEF(BOR) /* [DP-1] <- [DP-1] | [DP]; DP <- DP-1 */ - BINOP(uint4, |) - - OPDEF(BXOR) /* [DP-1] <- [DP-1] ^ [DP]; DP <- DP-1 */ - BINOP(uint4, ^) - - OPDEF(BCOM) /* [DP] <- ~[DP] */ - UNOP(uint4, ~) - - OPDEF(LSH) /* [DP-1] <- [DP-1] << [DP]; DP <- DP-1 */ - BINOP(uint4, <<) - - OPDEF(RSHI) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */ - { - R1.int4 = Pop<int4_t>(); - R0.int4 = Pop<int4_t>(); - R2.int4 = R0.int4 >> R1.int4; - Push(R2); - return 0; - } - - OPDEF(RSHU) /* [DP-1] <- [DP-1] >> [DP]; DP <- DP-1 */ - BINOP(uint4, >>) - - OPDEF(NEGF) /* [DP] <- -[DP] */ - UNOP(float4, -) - - OPDEF(ADDF) /* [DP-1] <- [DP-1] + [DP]; DP <- DP-1 */ - BINOP(float4, +) - - OPDEF(SUBF) /* [DP-1] <- [DP-1] - [DP]; DP <- DP-1 */ - BINOP(float4, -) - - OPDEF(DIVF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */ - BINOP(float4, /) - - OPDEF(MULF) /* [DP-1] <- [DP-1] / [DP]; DP <- DP-1 */ - BINOP(float4, *) - - OPDEF(CVIF) /* [DP] <- [DP] */ - { - Push<float4_t>(Pop<int4_t>()); - return 0; - } - - OPDEF(CVFI) /* [DP] <- [DP] */ - { - Push<int4_t>(Pop<float4_t>()); - return 0; - } -} diff --git a/src/virtualmachine/Operations.inl b/src/virtualmachine/Operations.inl deleted file mode 100644 index a1d4b43..0000000 --- a/src/virtualmachine/Operations.inl +++ /dev/null @@ -1,60 +0,0 @@ -OPDEF(UNDEF) -OPDEF(IGNORE) /* no-op */ -OPDEF(BREAK) /* ??? */ -OPDEF(ENTER) /* Begin subroutine. */ -OPDEF(LEAVE) /* End subroutine. */ -OPDEF(CALL) /* Call subroutine. */ -OPDEF(PUSH) /* push to stack. */ -OPDEF(POP) /* discard top-of-stack. */ -OPDEF(CONST) /* load constant to stack. */ -OPDEF(LOCAL) /* get local variable. */ -OPDEF(JUMP) /* unconditional jump. */ -OPDEF(EQ) /* compare integers, jump if equal. */ -OPDEF(NE) /* compare integers, jump if not equal. */ -OPDEF(LTI) /* compare integers, jump if less-than. */ -OPDEF(LEI) /* compare integers, jump if less-than-or-equal. */ -OPDEF(GTI) /* compare integers, jump if greater-than. */ -OPDEF(GEI) /* compare integers, jump if greater-than-or-equal. */ -OPDEF(LTU) /* compare unsigned integers, jump if less-than */ -OPDEF(LEU) /* compare unsigned integers, jump if less-than-or-equal */ -OPDEF(GTU) /* compare unsigned integers, jump if greater-than */ -OPDEF(GEU) /* compare unsigned integers, jump if greater-than-or-equal */ -OPDEF(EQF) /* compare floats, jump if equal */ -OPDEF(NEF) /* compare floats, jump if not-equal */ -OPDEF(LTF) /* compare floats, jump if less-than */ -OPDEF(LEF) /* compare floats, jump if less-than-or-equal */ -OPDEF(GTF) /* compare floats, jump if greater-than */ -OPDEF(GEF) /* compare floats, jump if greater-than-or-equal */ -OPDEF(LOAD1) /* load 1-byte from memory */ -OPDEF(LOAD2) /* load 2-byte from memory */ -OPDEF(LOAD4) /* load 4-byte from memory */ -OPDEF(STORE1) /* store 1-byte to memory */ -OPDEF(STORE2) /* store 2-byte to memory */ -OPDEF(STORE4) /* store 4-byte to memory */ -OPDEF(ARG) /* marshal argument */ -OPDEF(BLOCK_COPY) /* block copy... */ -OPDEF(SEX8) /* Pedophilia */ -OPDEF(SEX16) /* Sign-Extend 16-bit */ -OPDEF(NEGI) /* Negate integer. */ -OPDEF(ADD) /* Add integers (two's complement). */ -OPDEF(SUB) /* Subtract integers (two's complement). */ -OPDEF(DIVI) /* Divide signed integers. */ -OPDEF(DIVU) /* Divide unsigned integers. */ -OPDEF(MODI) /* Modulus (signed). */ -OPDEF(MODU) /* Modulus (unsigned). */ -OPDEF(MULI) /* Multiply signed integers. */ -OPDEF(MULU) /* Multiply unsigned integers. */ -OPDEF(BAND) /* Bitwise AND */ -OPDEF(BOR) /* Bitwise OR */ -OPDEF(BXOR) /* Bitwise eXclusive-OR */ -OPDEF(BCOM) /* Bitwise COMplement */ -OPDEF(LSH) /* Left-shift */ -OPDEF(RSHI) /* Right-shift (algebraic; preserve sign) */ -OPDEF(RSHU) /* Right-shift (bitwise; ignore sign) */ -OPDEF(NEGF) /* Negate float */ -OPDEF(ADDF) /* Add floats */ -OPDEF(SUBF) /* Subtract floats */ -OPDEF(DIVF) /* Divide floats */ -OPDEF(MULF) /* Multiply floats */ -OPDEF(CVIF) /* Convert to integer from float */ -OPDEF(CVFI) /* Convert to float from integer */
\ No newline at end of file diff --git a/src/virtualmachine/Syscalls.cpp b/src/virtualmachine/Syscalls.cpp deleted file mode 100644 index e4ca7ca..0000000 --- a/src/virtualmachine/Syscalls.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include <cstdio> -#include <cstdlib> -#include <cmath> -#include "VirtualMachine.h" -#include "simulation/Simulation.h" -#include "graphics/Renderer.h" - -namespace vm -{ - #define ARG(n) (Get(RP + ((2 + n) * sizeof(word)))) - - #define TRAPDEF(f) int VirtualMachine::trap##f() - - TRAPDEF(sin) - { - Push<float4_t>(sin(ARG(0).float4)); - return 0; - } - - TRAPDEF(cos) - { - Push<float4_t>(cos(ARG(0).float4)); - return 0; - } - - TRAPDEF(atan2) - { - Push<float4_t>(atan2(ARG(0).float4, ARG(1).float4)); - return 0; - } - - TRAPDEF(sqrt) - { - Push<float4_t>(sqrt(ARG(0).float4)); - return 0; - } - - TRAPDEF(floor) - { - Push<float4_t>(floor(ARG(0).float4)); - return 0; - } - - TRAPDEF(ceil) - { - Push<float4_t>(ceil(ARG(0).float4)); - return 0; - } - - - TRAPDEF(print) - { - char *text; - text = (char*)(ram) + ARG(0).int4; - printf("%s", text); - return 0; - } - - - TRAPDEF(error) - { - char *msg; - msg = (char*)(ram) + ARG(0).int4; - printf("%s", msg); - End(); - return 0; - } - - - TRAPDEF(partCreate) - { - Push<int4_t>(sim->create_part(ARG(0).int4, ARG(1).int4, ARG(2).int4, ARG(3).int4)); - return 0; - } - - TRAPDEF(partChangeType) - { - sim->part_change_type(ARG(0).int4, ARG(1).int4, ARG(2).int4, ARG(3).int4); - return 0; - } - - TRAPDEF(pmapData) - { - Push<int4_t>(sim->pmap[ARG(1).int4][ARG(0).int4]); - return 0; - } - - TRAPDEF(deletePart) - { - sim->delete_part(ARG(0).int4, ARG(1).int4); - return 0; - } - - TRAPDEF(killPart) - { - sim->kill_part(ARG(0).int4); - return 0; - } -} diff --git a/src/virtualmachine/Syscalls.inl b/src/virtualmachine/Syscalls.inl deleted file mode 100644 index 75455c1..0000000 --- a/src/virtualmachine/Syscalls.inl +++ /dev/null @@ -1,14 +0,0 @@ -TRAPDEF(-1, sin) -TRAPDEF(-2, cos) -TRAPDEF(-3, atan2) -TRAPDEF(-4, sqrt) -TRAPDEF(-5, floor) -TRAPDEF(-6, ceil) - -TRAPDEF(-7, error) -TRAPDEF(-8, print) -TRAPDEF(-9, partCreate) -TRAPDEF(-10, partChangeType) -TRAPDEF(-11, pmapData) -TRAPDEF(-12, deletePart) -TRAPDEF(-13, killPart) diff --git a/src/virtualmachine/VirtualMachine.cpp b/src/virtualmachine/VirtualMachine.cpp deleted file mode 100644 index a657f3c..0000000 --- a/src/virtualmachine/VirtualMachine.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include <string> -#include <cstring> -#include <stdio.h> -#include <stdlib.h> -#include "VirtualMachine.h" - -namespace vm -{ - - VirtualMachine::VirtualMachine(int hunkMbytes): - bigEndian(false), - hunk(NULL), - hunkSize(1048576), - hunkFree(0), - rom(NULL), - romSize(0), - ram(NULL), - ramSize(0), - dataStack(0), - returnStack(0), - DP(0), /* Datastack pointer. */ - RP(0), /* Return stack pointer. */ - PC(0), - cm(0), - cycles(0), - sim(NULL), - ren(NULL) - { - hunk = new char[hunkSize]; - std::fill(hunk, hunk+hunkSize, 0); - } - - VirtualMachine::~VirtualMachine() - { - delete[] hunk; - } - - #define DEBUGTRACE(args, ...) printf(args); - - int VirtualMachine::opcodeParameterSize(int opcode) - { - #define OP(n) OP##n - switch (opcode) - { - case OP(ENTER): - case OP(LEAVE): - case OP(LOCAL): - case OP(EQ): - case OP(NE): - case OP(LTI): - case OP(LEI): - case OP(GTI): - case OP(GEI): - case OP(LTU): - case OP(LEU): - case OP(GTU): - case OP(GEU): - case OP(EQF): - case OP(NEF): - case OP(LTF): - case OP(LEF): - case OP(GTF): - case OP(GEF): - case OP(CONST): - case OP(BLOCK_COPY): - return sizeof(uint4_t); - break; - case OP(ARG): - return sizeof(uint1_t); - break; - } - return 0; - #undef OP - } - - /* Read one octet from file. */ - int VirtualMachine::readByte(std::istream & input) - { - int o; - o = input.get(); - if (o < 0) o = 0; /* EOF (hack) */ - return o; - } - - /* Read little-endian 32-bit integer from file. */ - int VirtualMachine::readInt(std::istream & input) - { - int a, b, c, d, n; - - a = readByte(input); - b = readByte(input); - c = readByte(input); - d = readByte(input); - n = (a) | (b << 8) | (c << 16) | (d << 24); - return n; - } - - int VirtualMachine::readProgram(std::istream & input) - { - qvm_header_t qvminfo; - int i, n; - uint1_t x[4]; - word w; - - DEBUGTRACE("Loading file...\n"); - qvminfo.magic = readInt(input); /* magic. */ - if (qvminfo.magic != QVM_MAGIC) - { - DEBUGTRACE("Invalid magic"); - throw InvalidProgramException(); - //q3vm_error("Does not appear to be a QVM file."); - /* XXX: option to force continue. */ - return 0; - } - DEBUGTRACE("Magic OK\n"); - /* variable-length instructions mean instruction count != code length */ - qvminfo.inscount = readInt(input); - qvminfo.codeoff = readInt(input); - qvminfo.codelen = readInt(input); - qvminfo.dataoff = readInt(input); - qvminfo.datalen = readInt(input); - qvminfo.litlen = readInt(input); - qvminfo.bsslen = readInt(input); - - /* Code segment should follow... */ - /* XXX: use fseek with SEEK_CUR? */ - DEBUGTRACE("Searching for .code @ %d from %d\n", qvminfo.codeoff, input.tellg()); - - // rom = (q3vm_rom_t*)(hunk); /* ROM-in-hunk */ - rom = (Instruction*)calloc(qvminfo.inscount, sizeof(rom[0])); - while (input.tellg() < qvminfo.codeoff) - readByte(input); - while (romSize < qvminfo.inscount) - { - n = readByte(input); - w.int4 = 0; - if ((i = opcodeParameterSize(n))) - { - x[0] = x[1] = x[2] = x[3] = 0; - input.readsome((char*)x, i); - w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); - } - rom[romSize].Operation = n; - rom[romSize].Parameter = w; - romSize++; - } - DEBUGTRACE("After loading code: at %d, should be %d\n", input.tellg(), qvminfo.codeoff + qvminfo.codelen); - - /* Then data segment. */ - // ram = hunk + ((romlen + 3) & ~3); /* RAM-in-hunk */ - ram = hunk; - DEBUGTRACE("Searching for .data @ %d from %d\n", qvminfo.dataoff, input.tellg()); - while (input.tellg() < qvminfo.dataoff) - readByte(input); - for (n = 0; n < (qvminfo.datalen / sizeof(uint1_t)); n++) - { - i = input.readsome((char*)x, sizeof(x)); - w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); - *((word*)(ram + ramSize)) = w; - ramSize += sizeof(word); - } - - /* lit segment follows data segment. */ - /* Assembler should have already padded properly. */ - DEBUGTRACE("Loading .lit\n"); - for (n = 0; n < (qvminfo.litlen / sizeof(uint1_t)); n++) - { - i = input.readsome((char*)x, sizeof(x)); - memcpy(&(w.uint1), &x, sizeof(x)); /* no byte-swapping. */ - *((word*)(ram + ramSize)) = w; - ramSize += sizeof(word); - } - /* bss segment. */ - DEBUGTRACE("Allocating .bss %d (%X) bytes\n", qvminfo.bsslen, qvminfo.bsslen); - /* huge empty chunk. */ - ramSize += qvminfo.bsslen; - - hunkFree = hunkSize - ((ramSize * sizeof(uint1_t)) + 4); - - DEBUGTRACE("VM hunk has %d of %d bytes free (RAM = %d B).\n", hunkFree, hunkSize, ramSize); - if (ramSize > hunkSize) - { - throw OutOfMemoryException(); - return 0; - } - - /* set up stack. */ - { - int stacksize = 0x10000; - dataStack = ramSize - (stacksize / 2); - returnStack = ramSize; - //returnStack = dataStack+4; - RP = returnStack; - DP = dataStack; - } - - /* set up PC for return-to-termination. */ - PC = romSize + 1; - - ramMask = ramSize; - - return 1; - } - - int VirtualMachine::LoadProgram(std::vector<char> data) - { - /*class vectorwrapbuf : public std::basic_streambuf<char, std::char_traits<char> > - { - public: - vectorwrapbuf(std::vector<char> &vec) { - setg(vec.data(), vec.data(), vec.data() + vec.size()); - } - }; - vectorwrapbuf databuf(data); - std::istream is(&databuf); - return readProgram(is);*/ - std::stringstream ss(std::string(data.begin(), data.end())); - return readProgram((std::istream &)ss); - } - - int VirtualMachine::LoadProgram(char * filename) - { - /*FILE * qvmfile = fopen(filename, "rb"); - qvm_header_t qvminfo; - int i, n; - uint1_t x[4]; - word w; - - DEBUGTRACE("Loading file...\n"); - qvminfo.magic = readInt(qvmfile); - if (qvminfo.magic != QVM_MAGIC) - { - DEBUGTRACE("Invalid magic"); - return 0; - } - DEBUGTRACE("Magic OK\n"); - - qvminfo.inscount = readInt(qvmfile); - qvminfo.codeoff = readInt(qvmfile); - qvminfo.codelen = readInt(qvmfile); - qvminfo.dataoff = readInt(qvmfile); - qvminfo.datalen = readInt(qvmfile); - qvminfo.litlen = readInt(qvmfile); - qvminfo.bsslen = readInt(qvmfile); - - - DEBUGTRACE("Searching for .code @ %d from %d\n", qvminfo.codeoff, ftell(qvmfile)); - - rom = (Instruction*)calloc(qvminfo.inscount, sizeof(rom[0])); - while (ftell(qvmfile) < qvminfo.codeoff) - readByte(qvmfile); - while (romSize < qvminfo.inscount) - { - n = readByte(qvmfile); - w.int4 = 0; - if ((i = opcodeParameterSize(n))) - { - x[0] = x[1] = x[2] = x[3] = 0; - fread(&x, 1, i, qvmfile); - w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); - } - rom[romSize].Operation = n; - rom[romSize].Parameter = w; - romSize++; - } - DEBUGTRACE("After loading code: at %d, should be %d\n", ftell(qvmfile), qvminfo.codeoff + qvminfo.codelen); - - - ram = hunk; - DEBUGTRACE("Searching for .data @ %d from %d\n", qvminfo.dataoff, ftell(qvmfile)); - while (ftell(qvmfile) < qvminfo.dataoff) - readByte(qvmfile); - for (n = 0; n < (qvminfo.datalen / sizeof(uint1_t)); n++) - { - i = fread(&x, 1, sizeof(x), qvmfile); - w.uint4 = (x[0]) | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); - *((word*)(ram + ramSize)) = w; - ramSize += sizeof(word); - } - - - DEBUGTRACE("Loading .lit\n"); - for (n = 0; n < (qvminfo.litlen / sizeof(uint1_t)); n++) - { - i = fread(&x, 1, sizeof(x), qvmfile); - memcpy(&(w.uint1), &x, sizeof(x)); - *((word*)(ram + ramSize)) = w; - ramSize += sizeof(word); - } - - DEBUGTRACE("Allocating .bss %d (%X) bytes\n", qvminfo.bsslen, qvminfo.bsslen); - ramSize += qvminfo.bsslen; - - hunkFree = hunkSize - ((ramSize * sizeof(uint1_t)) + 4); - - DEBUGTRACE("VM hunk has %d of %d bytes free (RAM = %d B).\n", hunkFree, hunkSize, ramSize); - if (ramSize > hunkSize) - { - throw OutOfMemoryException(); - return 0; - } - - - { - int stacksize = 0x10000; - dataStack = ramSize - (stacksize / 2); - //returnStack = ramSize; - returnStack = dataStack+4; - RP = returnStack; - DP = dataStack; - } - - - PC = romSize + 1; - - ramMask = ramSize; - - return 1;*/ - return 0; //temporary, something has to be returned for now - } - - void VirtualMachine::End() - { - PC = romSize+1; - } - - int VirtualMachine::CallInterpreted(int address) - { - word w; - int i, argCount = 0; - - /* Set up call. */ - OpPUSH(w); - DEBUGTRACE("Starting with PC=%d, DP=%d, RP=%d to %d\n", PC, DP, RP, address); - w.int4 = (argCount + 2) * sizeof(word); - OpENTER(w); - i = 8; - /**w.int4 = arg0; Marshal(i, w); i += 4; - w.int4 = arg1; Marshal(i, w); i += 4; - w.int4 = arg2; Marshal(i, w); i += 4; - w.int4 = arg3; Marshal(i, w); i += 4; - w.int4 = arg4; Marshal(i, w); i += 4; - w.int4 = arg5; Marshal(i, w); i += 4; - w.int4 = arg6; Marshal(i, w); i += 4; - w.int4 = arg7; Marshal(i, w); i += 4; - w.int4 = arg8; Marshal(i, w); i += 4; - w.int4 = arg9; Marshal(i, w); i += 4; - w.int4 = arg10; Marshal(i, w); i += 4; - w.int4 = arg11; Marshal(i, w); i += 4; - w.int4 = arg12; Marshal(i, w); i += 4;*/ - w.int4 = address; - Push(w); - OpCALL(w); - DEBUGTRACE("Upon running PC=%d, DP=%d, RP=%d\n", PC, DP, RP); - Run(); - DEBUGTRACE("At finish PC=%d, DP=%d, RP=%d\n", PC, DP, RP); - w.int4 = (argCount + 2) * sizeof(word); - OpLEAVE(w); - OpPOP(w); - PC = romSize + 1; - return 0; - } - - int VirtualMachine::Run() - { - bool running = true; - int operation; - word parameter; - while(running) - { - cycles++; - if(PC > romSize) - { - running = false; - continue; - } - if (PC < 0) - { - syscall(PC); - continue; - } - operation = rom[PC].Operation; - parameter = rom[PC].Parameter; - PC++; - (this->*operations[operation])(parameter); - } - return 1; - } - - - - int VirtualMachine::syscall(int trap) - { - PC = Pop<int4_t>(); - - switch (trap) - { - #define TRAPDEF(n, f) case n: trap##f(); break; - #include "Syscalls.inl" - #undef TRAPDEF - } - - return 1; - } -} diff --git a/src/virtualmachine/VirtualMachine.h b/src/virtualmachine/VirtualMachine.h deleted file mode 100644 index b295d02..0000000 --- a/src/virtualmachine/VirtualMachine.h +++ /dev/null @@ -1,282 +0,0 @@ -#pragma once - -#include "Exceptions.h" - -class Simulation; -class Renderer; - -namespace vm -{ - - class VirtualMachine; - - typedef char ram_t; - - - - typedef unsigned int uint4_t; - typedef signed int int4_t; - - typedef unsigned short uint2_t; - typedef signed short int2_t; - - typedef unsigned char uint1_t; - typedef signed char int1_t; - - typedef float float4_t; - - union word - { - uint4_t uint4; - int4_t int4; - uint2_t uint2; - int2_t int2; - uint1_t uint1; - int1_t int1; - float4_t float4; - }; - - typedef int (VirtualMachine::*OperationFunction)(word parameter); - - struct Instruction - { - int Operation; - word Parameter; - //opfunc opfunc; - }; - - enum - { - QVM_MAGIC = 0x12721444, - }; - - struct qvm_header_t - { - int magic; - /* not-entirely-RISC ISA, so instruction count != codelen */ - int inscount; /* instruction count. */ - int codeoff; /* file offset of code segment. */ - int codelen; /* length of code segment, in octets. */ - int dataoff; /* file offset of data segment. */ - int datalen; /* length of data segment, in octets. */ - int litlen; /* length of lit segment (which is embedded in data segment). */ - int bsslen; /* length of bss segment. */ - }; - - class VirtualMachine - { - - int * instructionPointers; - - bool bigEndian; /* host is big-endian (requires byte-swapping). */ - - /* Memory spaces. */ - char * hunk; /* hunk space (malloc'd). */ - int hunkSize; /* total hunk size. */ - int hunkFree; /* free pointer. */ - - /* Read-Only Memory (code). */ - Instruction * rom; - int romSize; - int romMask; - - char * compiledRom; - int compiledRomSize; - int compiledRomMask; - - /* Random-Access Memory (data). */ - ram_t *ram; - int ramSize; - int ramMask; - - int dataStack; - int returnStack; - - word r[4]; /* registers. */ - int DP; /* Datastack pointer. */ - int RP; /* Return stack pointer. */ - int PC; /* Program Counter. */ - // int AP; /* Argument pointer. (hrm...) */ - - /* various flags. */ - int cm:1; - - /* Execution time */ - int cycles; - - #define TRAPDEF(n, f) int trap##f(); - #include "Syscalls.inl" - #undef TRAPDEF - - static OperationFunction operations[]; - - - #define OPDEF(n) OP##n, - enum { - #include "Operations.inl" - }; - #undef OPDEF - - int readProgram(std::istream & input); - int readByte(std::istream & input); - int readInt(std::istream & input); - int opcodeParameterSize(int opcode); - int syscall(int programCounter); - - //Used by the JIT - #ifdef VMJIT - int constant4(); - int constant1(); - void emit1(int v); - void emit4(int v); - void emitInstruction(const char *string); - void emitCommand(int command); - void emitAddEDI4(); - void emitMovEAXEDI(); - bool emitMovEBXEDI(int andit); - static int hex(int c); - #endif -public: - #ifdef VMJIT - static void callFromCompiled(); - static void callSyscall(); - bool Compile(); - int CallCompiled(int address); - #endif - Simulation * sim; - Renderer * ren; - - #define OPDEF(n) int Op##n(word parameter); - #include "Operations.inl" - #undef OPDEF - - VirtualMachine(int hunkMbytes); - virtual ~VirtualMachine(); - - int LoadProgram(char * filename); - int LoadProgram(std::vector<char> fileData); - int Run(); - int CallInterpreted(int address); - void End(); - void Marshal(int address, word element) - { - ram_t * ptr = ram+RP+address; - if(ptr < ram || ptr > ram+ramSize - sizeof(word)) - throw AccessViolationException(RP+address); - *((word*)ptr) = element; - } - - template <typename T> T Get(int address) - { - ram_t * ptr = ram+address; - if(ptr < ram || ptr > ram+ramSize - sizeof(word)) - throw AccessViolationException(address); - return *((T*)ptr); - } - - template <typename T> void Set(int address, T value) - { - ram_t * ptr = ram+address; - if(ptr < ram || ptr > ram+ramSize - sizeof(word)) - throw AccessViolationException(address); - *((T*)ptr) = value; - } - - template <typename T> T Pop () - { - ram_t * ptr = ram+DP; - if(DP + sizeof(word) < hunkSize) - DP += sizeof(word); - else - throw StackUnderflowException(); - return *((T*)ptr); - }; - - template <typename T> T RPop () - { - ram_t * ptr = ram+RP; - if(RP + sizeof(word) < hunkSize) - RP += sizeof(word); - else - throw StackUnderflowException(); - return *((T*)ptr); - }; - - template <typename T> void Push(T value) - { - if(DP - sizeof(word) >= 0) - DP -= sizeof(word); - else - throw StackOverflowException(); - ram_t * ptr = ram+DP; - *((T*)ptr) = value; - }; - - template <typename T> void RPush(T value) - { - if(RP - sizeof(word) >= 0) - RP -= sizeof(word); - else - throw StackOverflowException(); - ram_t * ptr = ram+RP; - *((T*)ptr) = value; - }; - - word Get(int address) - { - ram_t * ptr = ram+address; - if(ptr < ram || ptr > ram+ramSize - sizeof(word)) - throw AccessViolationException(address); - return *((word*)ptr); - } - - void Set(int address, word value) - { - ram_t * ptr = ram+address; - if(ptr < ram || ptr > ram+ramSize - sizeof(word)) - throw AccessViolationException(address); - *((word*)ptr) = value; - } - - word Pop() - { - ram_t * ptr = ram+DP; - if(DP + sizeof(word) < hunkSize) - DP += sizeof(word); - else - throw StackUnderflowException(); - return *((word*)ptr); - }; - - void Push(word value) - { - if(DP - sizeof(word) >= 0) - DP -= sizeof(word); - else - throw StackOverflowException(); - ram_t * ptr = ram+DP; - *((word*)ptr) = value; - }; - - word RPop() - { - ram_t * ptr = ram+RP; - if(RP + sizeof(word) < hunkSize) - RP += sizeof(word); - else - throw StackUnderflowException(); - return *((word*)ptr); - }; - - void RPush(word value) - { - if(RP - sizeof(word) >= 0) - RP -= sizeof(word); - else - throw StackOverflowException(); - ram_t * ptr = ram+RP; - *((word*)ptr) = value; - }; - }; - -} |
