Working X86 JIT compilation/execution

This commit is contained in:
Simon Robertshaw 2013-01-30 18:11:06 +00:00
parent c4e5e82fec
commit ca7c0d777b
6 changed files with 142 additions and 48 deletions

View File

@ -958,7 +958,8 @@ int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS)
machine->CSPush(i);
machine->CSPush(x);
machine->CSPush(y);
machine->Call(0);
//machine->Call(0);
machine->CallCompiled(0);
/*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type];

View File

@ -417,13 +417,13 @@ namespace pim
void VirtualMachine::Compile()
{
Native * native = new X86Native();
std::vector<unsigned char> executableCode = native->Compile(rom, romSize);
std::vector<unsigned char> executableCode = native->Compile(sim, rom, romSize);
Client::Ref().WriteFile(executableCode, "code.x");
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);
nativeRom = (intptr_t)romAddress;
delete native;
}
@ -435,12 +435,15 @@ namespace pim
void VirtualMachine::CallCompiled(int entryPoint)
{
void (*nativeFunction)(int, int, int) = (void(*)(int, int, int))nativeRom;
int arg3 = CSPop().Integer;
int arg2 = CSPop().Integer;
int arg1 = CSPop().Integer;
nativeFunction(arg1, arg2, arg3);
}
void VirtualMachine::Call(std::string entryPoint)
{
}
void VirtualMachine::Call(int entryPoint)

View File

@ -59,6 +59,8 @@ namespace pim
int romSize;
int romMask;
intptr_t nativeRom;
unsigned char * compiledRom;
int compiledRomSize;

View File

@ -6,6 +6,6 @@ namespace pim
{
public:
Native() {}
virtual std::vector<unsigned char> Compile(Instruction * rom, int romSize) {}
virtual std::vector<unsigned char> Compile(Simulation * sim, Instruction * rom, int romSize) {}
};
}

View File

@ -1,22 +1,32 @@
#include "Opcodes.h"
#include "X86Native.h"
#include "simulation/Simulation.h"
namespace pim
{
std::vector<unsigned char> X86Native::Compile(Instruction * rom, int romSize)
std::vector<unsigned char> X86Native::Compile(Simulation * sim, Instruction * rom, int romSize)
{
#if defined(X86) && !defined(_64BIT)
int programCounter = 0;
nativeRom.clear();
unsigned char * esi = new unsigned char[1024*1024];//malloc(1024*1024);
esi += 512;
//int * esi = malloc(1024*1024);
emit("BE"); //mov esi, machineStack
emit((intptr_t)esi);
emit("81 C4"); //add esp, 4
emit(4);
while(programCounter < romSize)
{
Word argument = rom[programCounter].Parameter;
virtualToNative[programCounter] = nativeRom.size();
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("8B 85"); //mov eax, [ebp+offset]
emit("8B 84 24"); //mov eax, [esp+offset]
emit((int) (argument.Integer));
//Store value in eax onto top of program stack
emit("89 06"); //mov [esi], eax
@ -25,7 +35,8 @@ namespace pim
//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("89 85"); //mov [ebp+offset], eax
emit("89 84 24"); //mov [esp+offset], eax
emit((int) (argument.Integer));
emit("83 C6 04"); //add esi, 4
break;
@ -35,8 +46,13 @@ namespace pim
emit((int) (argument.Integer));
break;
case Opcode::Increment:
emit("81 06"); //add [esi], dword ptr constant
emit((int) (argument.Integer));
if(argument.Integer > 0) {
emit("81 06"); //add [esi], dword ptr constant
emit((int) (argument.Integer));
} else {
emit("81 2E"); //sub [esi], dword ptr constant
emit((int) (-argument.Integer));
}
break;
case Opcode::Discard:
emit("83 C6 04"); //add esi, 4
@ -83,6 +99,7 @@ namespace pim
emit("F7 1E"); //neg [esi]
break;
case Opcode::Create:
emitCall((intptr_t)sim, (intptr_t)((void*)&Simulation::create_part));
//temp1 = PSPop();
//temp2 = PSPop();
//temp3 = PSPop();
@ -103,20 +120,29 @@ namespace pim
//}
//PSPush(temp>>8);
{
int propertyOffset = argument.Integer;
int partsArray = 0;
intptr_t partsArray = (intptr_t)sim->pmap;
emit("8B 06"); //mov eax, [esi]
//mov ecx, [esi+4]
emit("8B 4E 04"); //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
emit("81 F9"); //cmp ecx, XRES
emit((int)XRES);
emit("7D 22"); //|--< //jge 34
emit("74 20"); //|--< //jz 32
emit("3D"); //| //cmp eax, YRES
emit((int)YRES); //|
emit("7D 19"); //|--< //jge 25
emit("74 17"); //|--< //jz 23
//|
emit("69 C0"); //| //imul eax, 612
emit((int)XRES); //|
emit("01 C8"); //| //add eax, ecx
emit("8B 04 85"); //| //mov eax, [eax*4+pmap]
emit((int)partsArray); //|
emit("C1 F8 08"); //| //sar eax, 8
emit("89 46 04"); //| //mov [esi+4], eax #Copy eax onto stack
emit("EB 07"); //| |-< //jmp +7
emit("C7 46 04 FF FF FF FF"); //L-+-> //mov [esi+4], -1
emit("83 C6 04"); // L-> //add esi, 4
}
break;
case Opcode::Position:
@ -129,6 +155,34 @@ namespace pim
//}
//PSPush((int)sim->parts[temp1.Integer].x);
//PSPush((int)sim->parts[temp1.Integer].y);
{
intptr_t partsArray = (intptr_t)sim->parts;
emit("8B 06"); //mov eax, [esi] #Load index from stack
emit("3D"); //cmp eax, NPART
emit((int)NPART);
emit("7D 23"); //|--< //jge 31
emit("74 21"); //|--< //jz 29
//|
emit("C1 E0 03"); //| //sal eax, 3 #Shift index left (multiply by 8)
emit("8D 14 C5 00 00 00 00"); //| //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+xOffset+partsArray] #Copy value at index+baseAddress+propertyOffset into eax
emit("D9 81"); //| //fld [ecx+xOffset+partsArray]
emit(partsArray+offsetof(Particle, x));
emit("DB 1E"); //| //fistp [esi]
//emit("89 06"); //| //mov [esi], eax #Copy eax onto stack
//emit("89 81"); //| //mov eax, [ecx+yOffset+partsArray] #Copy value at index+baseAddress+propertyOffset into eax
emit("D9 81"); //| //fld [ecx+xOffset+partsArray]
emit(partsArray+offsetof(Particle, y));
emit("DB 5E FC"); //| //fistp [esi-4], eax #Copy eax onto stack
//emit("89 46 FC"); //| //mov [esi-4], eax #Copy eax onto stack
emit("EB 0D"); //| |-< //jmp +13
emit("C7 06 FF FF FF FF"); //L-+-> //mov [esi], -1
emit("C7 46 FC FF FF FF FF"); // | //mov [esi-4] -1
emit("83 EE 04"); // L-> //sub esi, 4
}
break;
case Opcode::Kill:
//sim->kill_part(PSPop().Integer);
@ -136,11 +190,11 @@ namespace pim
break;
case Opcode::LoadProperty:
{
int propertyOffset = argument.Integer;
int partsArray = 0;
intptr_t propertyOffset = argument.Integer;
intptr_t partsArray = (intptr_t)sim->parts;
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("8D 14 C5 00 00 00 00"); //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
@ -150,11 +204,11 @@ namespace pim
break;
case Opcode::StoreProperty:
{
int propertyOffset = argument.Integer;
int partsArray = 0;
intptr_t propertyOffset = argument.Integer;
intptr_t partsArray = (intptr_t)sim->parts;
emit("8B 06"); //mov eax, [esi]
emit("C1 E0 03"); //sal eax, 3
emit("8D 14 C5"); //lea edx, [eax*8]
emit("8D 14 C5 00 00 00 00"); //lea edx, [eax*8]
emit("89 D1"); //mov ecx, edx
emit("29 C1"); //sub ecx, eax
emit("8B 46 04"); //mov eax, [esi+4]
@ -167,52 +221,53 @@ namespace pim
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);
emit("75 05"); //jne 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
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);
emit("74 05"); //je 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
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);
emit("7E 05"); //jng 8
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
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);
emit("7C 05"); //jnge +6
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
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);
emit("7D 05"); //jnl +6
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
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);
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::Jump:
//programCounter = argument.Integer-1;
emit("E9"); //jmp [0x12345678]
emitPlaceholder(argument.Integer);
break;
case Opcode::Return:
emit("81 C7"); //add edi, constant
@ -226,11 +281,39 @@ namespace pim
//std::cout << programStack << std::endl;
programCounter++;
}
emit("81 EC"); //sub esp, 4
emit(4);
emit("C9"); //leave
emit("C3"); //ret
for(std::map<int, int>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter)
{
std::pair<int, int> placeholder = *iter;
int newNativeAddress = virtualToNative[placeholder.second]-placeholder.first-4;
nativeRom[placeholder.first] = newNativeAddress & 0xFF;
nativeRom[placeholder.first+1] = (newNativeAddress >> 8) & 0xFF;
nativeRom[placeholder.first+2] = (newNativeAddress >> 16) & 0xFF;
nativeRom[placeholder.first+3] = (newNativeAddress >> 24) & 0xFF;
}
//std::cout << "CS: " << callStack << " PS: " << programStack << std::endl;
return nativeRom;
#endif
}
void X86Native::emitPlaceholder(int virtualAddress)
{
placeholders[nativeRom.size()] = virtualAddress;
emit((int)0);
}
void X86Native::emitCall(intptr_t objectPtr, intptr_t functionAddress)
{
emit("B9"); //mov ecx, instancePointer
emit((int) objectPtr);
emit("A1"); //mov eax, functionAddress
emit((int)functionAddress);
emit("FF D0"); //call eax
}
void X86Native::emit(std::string opcode)
{
unsigned char c1, c2;

View File

@ -1,4 +1,5 @@
#include <vector>
#include <map>
#include "Native.h"
namespace pim
@ -7,11 +8,15 @@ namespace pim
{
public:
X86Native() : Native(), nativeRom() {}
virtual std::vector<unsigned char> Compile(Instruction * rom, int romSize);
virtual std::vector<unsigned char> Compile(Simulation * sim, Instruction * rom, int romSize);
private:
void emit(std::string opcode);
void emit(int constant);
void emitCall(intptr_t objectPtr, intptr_t functionAddress);
void emitPlaceholder(int virtualAddress);
unsigned char hex(char c);
std::vector<unsigned char> nativeRom;
std::map<int, int> virtualToNative;
std::map<int, int> placeholders;
};
}