Work on X86 native compiler

This commit is contained in:
Simon Robertshaw 2013-01-28 00:08:22 +00:00
parent 486d26e40b
commit c4e5e82fec
6 changed files with 313 additions and 198 deletions

View File

@ -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;

View File

@ -1,9 +1,11 @@
//Virtual machine
#include <iostream>
#include <fstream>
#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<unsigned char> 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));
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);
//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));
//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)

View File

@ -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);

11
src/pim/Native.h Normal file
View File

@ -0,0 +1,11 @@
#include "Machine.h"
namespace pim
{
class Native
{
public:
Native() {}
virtual std::vector<unsigned char> Compile(Instruction * rom, int romSize) {}
};
}

275
src/pim/X86Native.cpp Normal file
View File

@ -0,0 +1,275 @@
#include "Opcodes.h"
#include "X86Native.h"
namespace pim
{
std::vector<unsigned char> 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;
}
}

17
src/pim/X86Native.h Normal file
View File

@ -0,0 +1,17 @@
#include <vector>
#include "Native.h"
namespace pim
{
class X86Native : public Native
{
public:
X86Native() : Native(), nativeRom() {}
virtual std::vector<unsigned char> Compile(Instruction * rom, int romSize);
private:
void emit(std::string opcode);
void emit(int constant);
unsigned char hex(char c);
std::vector<unsigned char> nativeRom;
};
}