From c4e5e82fec528099f269300479ed6840ca8a33ab Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Mon, 28 Jan 2013 00:08:22 +0000 Subject: [PATCH] Work on X86 native compiler --- src/cat/LuaScriptInterface.cpp | 1 + src/pim/Machine.cpp | 204 ++---------------------- src/pim/Machine.h | 3 - src/pim/Native.h | 11 ++ src/pim/X86Native.cpp | 275 +++++++++++++++++++++++++++++++++ src/pim/X86Native.h | 17 ++ 6 files changed, 313 insertions(+), 198 deletions(-) create mode 100644 src/pim/Native.h create mode 100644 src/pim/X86Native.cpp create mode 100644 src/pim/X86Native.h diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp index e4bf3c244..8d513f113 100644 --- a/src/cat/LuaScriptInterface.cpp +++ b/src/cat/LuaScriptInterface.cpp @@ -1466,6 +1466,7 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim); machine->LoadProgram(programData); + machine->Compile(); lua_pushlightuserdata(l, machine); return 1; diff --git a/src/pim/Machine.cpp b/src/pim/Machine.cpp index a954d31dc..06e3cd80a 100644 --- a/src/pim/Machine.cpp +++ b/src/pim/Machine.cpp @@ -1,9 +1,11 @@ //Virtual machine #include +#include #include "Machine.h" #include "Opcodes.h" #include "simulation/Simulation.h" +#include "X86Native.h" namespace pim { /*unsigned char * rom; @@ -414,204 +416,16 @@ namespace pim void VirtualMachine::Compile() { - while(programCounter < romSize) - { - Word argument = rom[programCounter].Parameter; - switch(rom[programCounter].Opcode) - { - case Opcode::Load: - emit("83 EF 04"); //sub edi 4 + Native * native = new X86Native(); + std::vector executableCode = native->Compile(rom, romSize); + Client::Ref().WriteFile(executableCode, "code.x"); - //Load value at base stack + offset into eax - emit("8B 85"); //mov eax [ebp+ram+offset] - emit((intptr_t) (ram - argument.Integer)); - - //Store value in eax onto top of program stack - emit("89 07"); //mov [edi], eax - emit((intptr_t) (ram)); - break; - case Opcode::Store: - //Load value on top of the program stack into eax - emit("8B 07"); //mov eax [edi] - emit((intptr_t) (ram)); + unsigned char * romAddress = new unsigned char[executableCode.size()+8]; + std::fill(romAddress, romAddress+executableCode.size()+8, 0x90); //Fill with NOP for debugging + std::copy(executableCode.begin(), executableCode.end(), romAddress+4); - //Load value in eax onto top of program stack - emit("89 85"); //mov [ebp+ram+offset], eax - emit((intptr_t) (ram - argument.Integer)); - - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Constant: - emit("83 EF 04"); //sub edi 4 - - emit("C7 07"); //mov [edi] constant - emit((int) (argument.Integer)); - break; - case Opcode::Increment: - emit("81 07"); //add [edi] constant - emit((int) (argument.Integer)); - break; - case Opcode::Discard: - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Duplicate: - //Copy value on stack into register - emit("8B 07"); //mov eax [edi] - //Adjust program stack pointer - emit("83 EF 04"); //sub edi 4 - //Move value in eax into program stack - emit("89 07"); //mov [edi], eax - break; - case Opcode::Add: - emit("8B 07"); //mov eax [edi] - emit("01 47 04"); //add [edi+4] eax - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Subtract: - emit("8B 07"); //mov eax [edi] - emit("29 47 04"); //sub [edi+4] eax - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Multiply: - emit("8B 47 04"); //mov eax [edi+4] - emit("F7 2F"); //imul [edi] - emit("89 47 04"); //mov [edi+4] eax - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Divide: - emit("8B 47 04");//mov eax [edi+4] - emit("99"); //cdq - emit("F7 3F"); //idiv [edi] - emit("89 47 04"); //mov [edi+4] eax - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Modulus: - emit("8B 47 04"); // mov eax [edi+4] - emit("99"); // cdq - emit("F7 3F"); // idiv [edi] - emit("89 57 04"); // mov [edi+4] edx - emit("83 C7 04"); //add edi 4 - break; - case Opcode::Negate: - emit("F7 1F"); //neg [edi] - break; - case Opcode::Create: - //temp1 = PSPop(); - //temp2 = PSPop(); - //temp3 = PSPop(); - //PSPush(sim->create_part(PSPop().Integer, temp3.Integer, temp2.Integer, temp1.Integer)); - break; - case Opcode::Transform: - //PSPop(); - //PSPop(); - //PSPush((Word)-1); - break; - case Opcode::Get: - //temp1 = PSPop(); - //temp2 = PSPop(); - //if(temp1.Integer < 0 || temp1.Integer >= YRES || temp2.Integer < 0 || temp2.Integer >= XRES || !(temp = sim->pmap[temp1.Integer][temp2.Integer])) - //{ - // PSPush(-1); - // break; - //} - //PSPush(temp>>8); - break; - case Opcode::Position: - //temp1 = PSPop(); - //if(temp1.Integer < 0 || temp1.Integer >= NPART || !sim->parts[temp1.Integer].type) - //{ - // PSPush(-1); - // PSPush(-1); - // break; - //} - //PSPush((int)sim->parts[temp1.Integer].x); - //PSPush((int)sim->parts[temp1.Integer].y); - break; - case Opcode::Kill: - //sim->kill_part(PSPop().Integer); - //PSPush((Word)0); - break; - case Opcode::LoadProperty: - //PSPush(PPROP(PSPop().Integer, argument.Integer)); - break; - case Opcode::StoreProperty: - //temp1 = PSPop(); - //PPROP(temp1.Integer, argument.Integer) = PSPop(); - break; - case Opcode::JumpEqual: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("75 06"); //jne +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::JumpNotEqual: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("74 06"); //je +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::JumpGreater: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("7E 06"); //jng +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::JumpGreaterEqual: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("7C 06"); //jnge +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::JumpLess: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("7D 06"); //jnl +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::JumpLessEqual: - emit("83 C7 04"); //add edi 8 - emit("8B 47 FC"); //mov eax, dword ptr [edi-4] - emit("3B 47 F7"); //cmp eax, dword ptr [edi-8] - emit("7F 06"); //jnle +6 - emit("FF 25"); //jmp [0x12345678] - emit(0); - break; - case Opcode::Jump: - //programCounter = argument.Integer-1; - break; - case Opcode::Return: - emit("81 C6"); //add esi constant - emit(argument.Integer); - break; - case Opcode::LocalEnter: - emit("81 EE"); //sub esi constant - emit(argument.Integer); - break; - } - //std::cout << programStack << std::endl; - programCounter++; - } - //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; - } - - void VirtualMachine::emit(std::string opcode) - { - - } - - void VirtualMachine::emit(int constant) - { + delete native; } void VirtualMachine::CallCompiled(std::string entryPoint) diff --git a/src/pim/Machine.h b/src/pim/Machine.h index 3bf1131d0..2bff28c2f 100644 --- a/src/pim/Machine.h +++ b/src/pim/Machine.h @@ -78,9 +78,6 @@ namespace pim //Instruction * instructions; int programCounter; - - void emit(std::string opcode); - void emit(int constant); public: VirtualMachine(Simulation * sim); int OpcodeArgSize(int opcode); diff --git a/src/pim/Native.h b/src/pim/Native.h new file mode 100644 index 000000000..ecd7a095b --- /dev/null +++ b/src/pim/Native.h @@ -0,0 +1,11 @@ +#include "Machine.h" + +namespace pim +{ + class Native + { + public: + Native() {} + virtual std::vector Compile(Instruction * rom, int romSize) {} + }; +} \ No newline at end of file diff --git a/src/pim/X86Native.cpp b/src/pim/X86Native.cpp new file mode 100644 index 000000000..ef7d84309 --- /dev/null +++ b/src/pim/X86Native.cpp @@ -0,0 +1,275 @@ +#include "Opcodes.h" +#include "X86Native.h" + +namespace pim +{ + std::vector X86Native::Compile(Instruction * rom, int romSize) + { + #if defined(X86) && !defined(_64BIT) + int programCounter = 0; + nativeRom.clear(); + while(programCounter < romSize) + { + Word argument = rom[programCounter].Parameter; + switch(rom[programCounter].Opcode) + { + case Opcode::Load: + emit("83 EE 04"); //sub esi, 4 + //Load value at base stack + offset into eax + emit("8B 85"); //mov eax, [ebp+offset] + emit((int) (argument.Integer)); + //Store value in eax onto top of program stack + emit("89 06"); //mov [esi], eax + break; + case Opcode::Store: + //Load value on top of the program stack into eax + emit("8B 06"); //mov eax, [esi] + //Load value in eax into memory + emit("89 85"); //mov [ebp+offset], eax + emit((int) (argument.Integer)); + emit("83 C6 04"); //add esi, 4 + break; + case Opcode::Constant: + emit("83 EE 04"); //sub esi, 4 + emit("C7 06"); //mov [esi], dword ptr constant + emit((int) (argument.Integer)); + break; + case Opcode::Increment: + emit("81 06"); //add [esi], dword ptr constant + emit((int) (argument.Integer)); + break; + case Opcode::Discard: + emit("83 C6 04"); //add esi, 4 + break; + case Opcode::Duplicate: + //Copy value on stack into register + emit("8B 06"); //mov eax, [esi] + //Adjust program stack pointer + emit("83 EE 04"); //sub esi, 4 + //Move value in eax into program stack + emit("89 06"); //mov [esi], eax + break; + case Opcode::Add: + emit("8B 06"); //mov eax, [esi] + emit("83 C6 04"); //add esi, 4 + emit("01 06"); //add [esi], eax + break; + case Opcode::Subtract: + emit("8B 06"); //mov eax, [esi] + emit("83 C6 04"); //add esi, 4 + emit("29 06"); //sub [esi], eax + break; + case Opcode::Multiply: + emit("8B 46 04"); //mov eax, [esi+4] + emit("F7 2E"); //imul [esi] + emit("83 C6 04"); //add esi, 4 + emit("89 06"); //mov [esi], eax + break; + case Opcode::Divide: + emit("8B 46 04"); //mov eax [esi+4] + emit("99"); //cdq + emit("F7 3E"); //idiv [esi] + emit("83 C6 04"); //add esi, 4 + emit("89 06"); //mov [esi], eax + break; + case Opcode::Modulus: + emit("8B 46 04"); //mov eax [esi+4] + emit("99"); //cdq + emit("F7 3E"); //idiv [esi] + emit("83 C6 04"); //add esi, 4 + emit("89 16"); //mov [esi], edx + break; + case Opcode::Negate: + emit("F7 1E"); //neg [esi] + break; + case Opcode::Create: + //temp1 = PSPop(); + //temp2 = PSPop(); + //temp3 = PSPop(); + //PSPush(sim->create_part(PSPop().Integer, temp3.Integer, temp2.Integer, temp1.Integer)); + break; + case Opcode::Transform: + //PSPop(); + //PSPop(); + //PSPush((Word)-1); + break; + case Opcode::Get: + //temp1 = PSPop(); + //temp2 = PSPop(); + //if(temp1.Integer < 0 || temp1.Integer >= YRES || temp2.Integer < 0 || temp2.Integer >= XRES || !(temp = sim->pmap[temp1.Integer][temp2.Integer])) + //{ + // PSPush(-1); + // break; + //} + //PSPush(temp>>8); + { + int propertyOffset = argument.Integer; + int partsArray = 0; + emit("8B 06"); //mov eax, [esi] + //mov ecx, [esi+4] + + //and eax, 348 + //and ecx, 612 + + //imul eax, 612, eax + emit("8B 46 04"); //add eax, ecx + emit("8B 81"); //mov eax, [eax*4+pmap] + //sar eax, 8 + emit("89 06"); //mov [esi+4], eax #Copy eax onto stack + emit("83 C6 08"); //add esi, 4 + } + break; + case Opcode::Position: + //temp1 = PSPop(); + //if(temp1.Integer < 0 || temp1.Integer >= NPART || !sim->parts[temp1.Integer].type) + //{ + // PSPush(-1); + // PSPush(-1); + // break; + //} + //PSPush((int)sim->parts[temp1.Integer].x); + //PSPush((int)sim->parts[temp1.Integer].y); + break; + case Opcode::Kill: + //sim->kill_part(PSPop().Integer); + //PSPush((Word)0); + break; + case Opcode::LoadProperty: + { + int propertyOffset = argument.Integer; + int partsArray = 0; + emit("8B 06"); //mov eax, [esi] #Load index from stack + emit("C1 E0 03"); //sal eax, 3 #Shift index left (multiply by 8) + emit("8D 14 C5"); //lea edx, [eax*8] #Mutiply by 8 again and copy into edx //Size of 56 is represented by (1*(8^2))-(1*8) + emit("89 D1"); //mov ecx, edx + emit("29 C1"); //sub ecx, eax #Subtract index*8^2 by index*8 to get the index*56 + emit("8B 81"); //mov eax, [ecx+propertyOffset+partsArray] #Copy value at index+baseAddress+propertyOffset into eax + emit(partsArray+propertyOffset); + emit("89 06"); //mov [esi], eax #Copy eax onto stack + } + break; + case Opcode::StoreProperty: + { + int propertyOffset = argument.Integer; + int partsArray = 0; + emit("8B 06"); //mov eax, [esi] + emit("C1 E0 03"); //sal eax, 3 + emit("8D 14 C5"); //lea edx, [eax*8] + emit("89 D1"); //mov ecx, edx + emit("29 C1"); //sub ecx, eax + emit("8B 46 04"); //mov eax, [esi+4] + emit("89 81"); //mov [ecx+propertyOffset+partsArray], eax + emit(partsArray+propertyOffset); + emit("83 C6 08"); //add esi, 8 + } + break; + case Opcode::JumpEqual: + emit("83 C6 08"); //add esi, 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("75 08"); //jne 8 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::JumpNotEqual: + emit("83 C6 04"); //add esi, 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("74 08"); //je 8 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::JumpGreater: + emit("83 C6 08"); //add esi 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("7E 08"); //jng 8 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::JumpGreaterEqual: + emit("83 C6 08"); //add esi 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("7C 08"); //jnge +6 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::JumpLess: + emit("83 C6 08"); //add esi 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("7D 08"); //jnl +6 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::JumpLessEqual: + emit("83 C6 08"); //add esi 8 + emit("8B 46 FC"); //mov eax, [esi-4] + emit("3B 46 F8"); //cmp eax, [esi-8] + emit("7F 08"); //jnle +6 + emit("E9 01"); //jmp [0x12345678] + emit((int)0); + break; + case Opcode::Jump: + //programCounter = argument.Integer-1; + break; + case Opcode::Return: + emit("81 C7"); //add edi, constant + emit(argument.Integer); + break; + case Opcode::LocalEnter: + emit("81 EF"); //sub edi constant + emit(argument.Integer); + break; + } + //std::cout << programStack << std::endl; + programCounter++; + } + //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; + return nativeRom; + #endif + } + + void X86Native::emit(std::string opcode) + { + unsigned char c1, c2; + unsigned char v; + const char * string = opcode.c_str(); + + while (true) + { + c1 = string[0]; + c2 = string[1]; + + v = (hex( c1 ) << 4) | hex(c2); + nativeRom.push_back(v); + + if (!string[2]) + { + break; + } + string += 3; + } + } + + void X86Native::emit(int constant) + { + nativeRom.push_back(constant & 0xFF); + nativeRom.push_back((constant >> 8) & 0xFF); + nativeRom.push_back((constant >> 16) & 0xFF); + nativeRom.push_back((constant >> 24) & 0xFF); + } + + unsigned char X86Native::hex(char 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'; + return 0; + } + +} \ No newline at end of file diff --git a/src/pim/X86Native.h b/src/pim/X86Native.h new file mode 100644 index 000000000..ac48807e9 --- /dev/null +++ b/src/pim/X86Native.h @@ -0,0 +1,17 @@ +#include +#include "Native.h" + +namespace pim +{ + class X86Native : public Native + { + public: + X86Native() : Native(), nativeRom() {} + virtual std::vector Compile(Instruction * rom, int romSize); + private: + void emit(std::string opcode); + void emit(int constant); + unsigned char hex(char c); + std::vector nativeRom; + }; +} \ No newline at end of file