diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp index 78a9ff025..2a6aa4156 100644 --- a/src/cat/LuaScriptInterface.cpp +++ b/src/cat/LuaScriptInterface.cpp @@ -950,6 +950,20 @@ void LuaScriptInterface::initElementsAPI() } pim::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM]; +NativeUpdateFunc LuaScriptInterface::updateNativeCode[PT_NUM]; +int LuaScriptInterface::updateNative(UPDATE_FUNC_ARGS) +{ + /*void (*nativeFunction)(int, int, int) = updateNativeCode[parts[i].type];//(void(*)(int, int, int))nativeRom; + //int arg3 = CSPop().Integer; + //int arg2 = CSPop().Integer; + //int arg1 = CSPop().Integer; + //std::cout << arg1 << std::endl; + //std::cout << arg2 << std::endl; + //std::cout << arg3 << std::endl; + nativeFunction(i, x, y);*/ + updateNativeCode[parts[i].type](i, x, y); + return 0; +} int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) { @@ -959,7 +973,7 @@ int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) machine->CSPush(x); machine->CSPush(y); //machine->Call(0); - machine->CallCompiled(0); + machine->Run(0); /*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; @@ -1318,7 +1332,15 @@ int LuaScriptInterface::elements_property(lua_State * l) else if(lua_type(l, 3) == LUA_TLIGHTUSERDATA) { updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); - luacon_sim->elements[id].Update = &updateVM; + if(updateVirtualMachines[id]->IsCompiled()) + { + updateNativeCode[id] = (NativeUpdateFunc)updateVirtualMachines[id]->GetNativeEntryPoint(0); + luacon_sim->elements[id].Update = &updateNative; + } + else + { + luacon_sim->elements[id].Update = &updateVM; + } } else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3)) { @@ -1467,7 +1489,10 @@ int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim); machine->LoadProgram(programData); + +#if defined(X86) && !defined(_64BIT) machine->Compile(); +#endif lua_pushlightuserdata(l, machine); return 1; diff --git a/src/cat/LuaScriptInterface.h b/src/cat/LuaScriptInterface.h index f7b1a13d3..a6b194604 100644 --- a/src/cat/LuaScriptInterface.h +++ b/src/cat/LuaScriptInterface.h @@ -45,6 +45,8 @@ class Tool; #define LUACON_EL_MODIFIED_MENUS 0x4 class TPTScriptInterface; +class LuaScriptInterface; +typedef void (*NativeUpdateFunc)(int, int, int); class LuaScriptInterface: public CommandInterface { int luacon_mousex, luacon_mousey, luacon_mousebutton, luacon_brushx, luacon_brushy; @@ -75,6 +77,8 @@ class LuaScriptInterface: public CommandInterface //Elements static pim::VirtualMachine * updateVirtualMachines[PT_NUM]; + static NativeUpdateFunc updateNativeCode[PT_NUM]; + static int updateNative(UPDATE_FUNC_ARGS); static int updateVM(UPDATE_FUNC_ARGS); // void initElementsAPI(); diff --git a/src/pim/Machine.cpp b/src/pim/Machine.cpp index 2b917885d..da3c33836 100644 --- a/src/pim/Machine.cpp +++ b/src/pim/Machine.cpp @@ -23,7 +23,8 @@ namespace pim VirtualMachine::VirtualMachine(Simulation * simulation) : rom(NULL), ram(NULL), - sim(simulation) + sim(simulation), + nativeRom(0) { } @@ -193,7 +194,7 @@ namespace pim int argSize = 0; Instruction instruction; instruction.Opcode = programData[programPosition++]; - if(argSize = OpcodeArgSize(instruction.Opcode)) + if(argSize = opcodeArgSize(instruction.Opcode)) { if(argSize == 4 && programPosition+3 < programData.size()) { @@ -236,7 +237,7 @@ namespace pim callStack += WORDSIZE; //Since there's nothing on the stack, it shouldn't point to the item on the bottom } - int VirtualMachine::OpcodeArgSize(int opcode) + int VirtualMachine::opcodeArgSize(int opcode) { switch(opcode) { @@ -276,7 +277,7 @@ namespace pim } } - void VirtualMachine::Run() + void VirtualMachine::run() { //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; //std::string names[] = { "Load", "Store", "Constant", "Increment", "Discard", "Duplicate", "Add", "Subtract", "Multiply", "Divide", "Modulus", "Negate", "Create", "Transform", "Get", "Position", "Kill", "JumpEqual", "JumpNotEqual", "JumpGreater", "JumpGreaterEqual", "JumpLess", "JumpLessEqual", "Jump", "Return", "LocalEnter"}; @@ -423,43 +424,38 @@ namespace pim void VirtualMachine::Compile() { Native * native = new X86Native(); - std::vector executableCode = native->Compile(sim, rom, romSize); - Client::Ref().WriteFile(executableCode, "code.x"); + if(nativeRom) + delete[] nativeRom; + if(nativeStack) + delete[] nativeStack; - 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; - printf("%p\n", romAddress); - fflush(stdout); + nativeStack = new unsigned char [1024*1024]; + + std::vector executableCode = native->Compile(sim, nativeStack + (1024*512), rom, romSize); + nativeRom = new unsigned char[executableCode.size()]; + + std::copy(executableCode.begin(), executableCode.end(), nativeRom); delete native; } - void VirtualMachine::CallCompiled(std::string entryPoint) + void * VirtualMachine::GetNativeEntryPoint(std::string entryPoint) { } - void VirtualMachine::CallCompiled(int entryPoint) + void * VirtualMachine::GetNativeEntryPoint(intptr_t entryPoint) { - void (*nativeFunction)(int, int, int) = (void(*)(int, int, int))nativeRom; - int arg3 = CSPop().Integer; - int arg2 = CSPop().Integer; - int arg1 = CSPop().Integer; - //std::cout << arg1 << std::endl; - //std::cout << arg2 << std::endl; - //std::cout << arg3 << std::endl; - nativeFunction(arg1, arg2, arg3); + return nativeRom+entryPoint; } - void VirtualMachine::Call(std::string entryPoint) + void VirtualMachine::Run(std::string entryPoint) { } - void VirtualMachine::Call(int entryPoint) + void VirtualMachine::Run(int entryPoint) { programCounter = entryPoint; - Run(); + run(); } } diff --git a/src/pim/Machine.h b/src/pim/Machine.h index 489003593..727839936 100644 --- a/src/pim/Machine.h +++ b/src/pim/Machine.h @@ -59,7 +59,8 @@ namespace pim int romSize; int romMask; - intptr_t nativeRom; + unsigned char * nativeRom; + unsigned char * nativeStack; unsigned char * compiledRom; int compiledRomSize; @@ -80,16 +81,20 @@ namespace pim //Instruction * instructions; int programCounter; + void run(); + int opcodeArgSize(int opcode); public: VirtualMachine(Simulation * sim); - int OpcodeArgSize(int opcode); void LoadProgram(std::vector programData); - void Run(); void Compile(); - void CallCompiled(std::string entryPoint); - void CallCompiled(int entryPoint); - void Call(std::string entryPoint); - void Call(int entryPoint); + void * GetNativeEntryPoint(std::string entryPoint); + void * GetNativeEntryPoint(intptr_t entryPoint); + void Run(std::string entryPoint); + void Run(int entryPoint); + inline bool IsCompiled() + { + return nativeRom != 0; + } inline void PSPush(Word word) { programStack -= WORDSIZE; diff --git a/src/pim/Native.h b/src/pim/Native.h index a612124c7..3bf1d464a 100644 --- a/src/pim/Native.h +++ b/src/pim/Native.h @@ -4,8 +4,49 @@ namespace pim { class Native { + protected: + std::vector nativeRom; + void 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; + } + } + + unsigned char 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; + } + virtual void emitConstantS(short int constant) {} //Single + virtual void emitConstantD(long int constant) {} //Double + virtual void emitConstantP(intptr_t constant) {} //Pointer + virtual void emitConstantQ(long long int constant) {} //Quad + virtual void emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize) {} + virtual void emitPlaceholder(int virtualAddress) {} public: - Native() {} - virtual std::vector Compile(Simulation * sim, Instruction * rom, int romSize) {} + Native() : nativeRom() {} + virtual std::vector Compile(Simulation * sim, unsigned char * machineStack, Instruction * rom, int romSize) {} + }; } \ No newline at end of file diff --git a/src/pim/X86Native.cpp b/src/pim/X86Native.cpp index 334c4a93e..4c28b8f28 100644 --- a/src/pim/X86Native.cpp +++ b/src/pim/X86Native.cpp @@ -4,19 +4,16 @@ namespace pim { - std::vector X86Native::Compile(Simulation * sim, Instruction * rom, int romSize) + std::vector X86Native::Compile(Simulation * sim, unsigned char * machineStack, 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; - //emit("52"); //push edx - //emit("56"); //push esi + for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger - emit("BE"); //mov esi, machineStack - emit((intptr_t)esi); + emit("BE"); //mov esi, machineStack + emitConstantP((intptr_t)machineStack); while(programCounter < romSize) { @@ -29,7 +26,7 @@ namespace pim //Load value at base stack + offset into eax //emit("8B 85"); //mov eax, [ebp+offset] emit("8B 84 24"); //mov eax, [esp+offset] - emit((int) (argument.Integer)); + emitConstantP(argument.Integer); //Store value in eax onto top of program stack emit("89 06"); //mov [esi], eax break; @@ -37,23 +34,22 @@ 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 84 24"); //mov [esp+offset], eax - emit((int) (argument.Integer)); + emitConstantD(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)); + emitConstantD(argument.Integer); break; case Opcode::Increment: if(argument.Integer > 0) { emit("81 06"); //add [esi], dword ptr constant - emit((int) (argument.Integer)); + emitConstantD(argument.Integer); } else { emit("81 2E"); //sub [esi], dword ptr constant - emit((int) (-argument.Integer)); + emitConstantD(-argument.Integer); } break; case Opcode::Discard: @@ -112,10 +108,6 @@ namespace pim emit("83 C6 08"); //add esi, 8 emitCall((intptr_t)sim, (intptr_t)((void*)&Simulation::create_part), 16); emit("89 06"); //mov [esi], eax - //temp1 = PSPop(); - //temp2 = PSPop(); - //temp3 = PSPop(); - //PSPush(sim->create_part(PSPop().Integer, temp3.Integer, temp2.Integer, temp1.Integer)); break; case Opcode::Transform: //PSPop(); @@ -127,21 +119,19 @@ namespace pim intptr_t partsArray = (intptr_t)sim->pmap; emit("8B 06"); //mov eax, [esi] emit("8B 4E 04"); //mov ecx, [esi+4] - emit("81 F9"); //cmp ecx, XRES - emit((int)XRES); + emitConstantD((int)XRES); emit("7D 22"); //|--< //jge 34 emit("74 20"); //|--< //jz 32 emit("3D"); //| //cmp eax, YRES - emit((int)YRES); //| + emitConstantD((int)YRES); //| emit("7D 19"); //|--< //jge 25 emit("74 17"); //|--< //jz 23 - //| emit("69 C0"); //| //imul eax, 612 - emit((int)XRES); //| + emitConstantD((int)XRES); //| emit("01 C8"); //| //add eax, ecx emit("8B 04 85"); //| //mov eax, [eax*4+pmap] - emit((int)partsArray); //| + emitConstantP((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 @@ -153,26 +143,20 @@ namespace pim { 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); + emitConstantD((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)); + emitConstantP(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)); + emitConstantP(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 @@ -193,7 +177,7 @@ namespace pim 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); + emitConstantP(partsArray+propertyOffset); emit("89 06"); //mov [esi], eax #Copy eax onto stack } break; @@ -208,7 +192,7 @@ namespace pim 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); + emitConstantP(partsArray+propertyOffset); emit("83 C6 08"); //add esi, 8 } break; @@ -273,25 +257,22 @@ namespace pim emitPlaceholder(argument.Integer); break; case Opcode::Return: - //emit("5E"); //pop esi - //emit("5A"); //pop edx emit("C3"); //ret break; case Opcode::Leave: - //emit("81 C7"); //add edi, constant emit("81 C4"); //add esp, constant - emit(argument.Integer); + emitConstantD(argument.Integer); break; case Opcode::LocalEnter: - //emit("81 EF"); //sub edi constant emit("81 EC"); //sub esp constant - emit(argument.Integer); + emitConstantD(argument.Integer); break; } //std::cout << programStack << std::endl; programCounter++; } + for(int i = 0; i < 8; i++) { emit("90"); } //nop, helps find the code in memory with a debugger for(std::map::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter) { @@ -315,39 +296,27 @@ namespace pim void X86Native::emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize) { - //emit("B9"); //mov ecx, instancePointer - emit("68"); //push instancePointer - emit((int) objectPtr); +#ifdef _MSC_VER + //MSVC puts the instance pointer in ecx, not on the stack + emit("B9"); //mov ecx, instancePointer + emitConstantP(objectPtr); emit("B8"); //mov eax, functionAddress - emit((int)functionAddress); + emitConstantP(functionAddress); emit("FF D0"); //call eax emit("81 C4"); //add esp, stacksize - emit((int)stackSize+sizeof(intptr_t)); + emitConstantD(stackSize); +#else + emit("68"); //push instancePointer + emitConstantP(objectPtr); + emit("B8"); //mov eax, functionAddress + emitConstantP(functionAddress); + emit("FF D0"); //call eax + emit("81 C4"); //add esp, stacksize + emitConstantD(stackSize+sizeof(intptr_t)); +#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) + void X86Native::emitConstantD(long int constant) { nativeRom.push_back(constant & 0xFF); nativeRom.push_back((constant >> 8) & 0xFF); @@ -355,15 +324,9 @@ namespace pim nativeRom.push_back((constant >> 24) & 0xFF); } - unsigned char X86Native::hex(char c) + void X86Native::emitConstantP(intptr_t constant) { - 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; + emitConstantD(constant); } } \ No newline at end of file diff --git a/src/pim/X86Native.h b/src/pim/X86Native.h index a78db0658..616aca3c7 100644 --- a/src/pim/X86Native.h +++ b/src/pim/X86Native.h @@ -7,15 +7,13 @@ namespace pim class X86Native : public Native { public: - X86Native() : Native(), nativeRom() {} - virtual std::vector 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, int stackSize); - void emitPlaceholder(int virtualAddress); - unsigned char hex(char c); - std::vector nativeRom; + X86Native() : Native() {} + virtual std::vector Compile(Simulation * sim, unsigned char * machineStack, Instruction * rom, int romSize); + protected: + virtual void emitConstantD(long int constant); + virtual void emitConstantP(intptr_t constant); + virtual void emitCall(intptr_t objectPtr, intptr_t functionAddress, int stackSize); + virtual void emitPlaceholder(int virtualAddress); std::map virtualToNative; std::map placeholders; };