diff options
Diffstat (limited to 'src')
32 files changed, 187 insertions, 5307 deletions
diff --git a/src/PowderToySDL.cpp b/src/PowderToySDL.cpp index 74cbb51..7f1a883 100644 --- a/src/PowderToySDL.cpp +++ b/src/PowderToySDL.cpp @@ -104,6 +104,8 @@ void ClipboardPush(char * text) #endif } +void EventProcess(SDL_Event event); + char * ClipboardPull() { #ifdef MACOSX @@ -135,7 +137,6 @@ char * ClipboardPull() Atom type; int format, result; unsigned long len, bytesLeft; - std::list<SDL_Event> evlist; // if there arrive any events while fetching keyboard XConvertSelection(sdl_wminfo.info.x11.display, XA_CLIPBOARD, XA_UTF8_STRING, XA_CLIPBOARD, sdl_wminfo.info.x11.window, CurrentTime); XFlush(sdl_wminfo.info.x11.display); sdl_wminfo.info.x11.unlock_func(); @@ -148,13 +149,11 @@ char * ClipboardPull() XEvent xevent = event.syswm.msg->event.xevent; if (xevent.type == SelectionNotify && xevent.xselection.requestor == sdl_wminfo.info.x11.window) break; - evlist.push_back(event); + else + EventProcess(event); } - } - for (std::list<SDL_Event>::iterator iter = evlist.begin(), end = evlist.end(); iter != end; iter++) - { - SDL_Event event = *iter; - SDL_PushEvent(&event); // replay the missed events + else + EventProcess(event); } sdl_wminfo.info.x11.lock_func(); XGetWindowProperty(sdl_wminfo.info.x11.display, sdl_wminfo.info.x11.window, XA_CLIPBOARD, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytesLeft, &data); @@ -171,7 +170,14 @@ char * ClipboardPull() text = strdup((const char*) data); XFree(data); } + else + { + printf("Failed to pull from clipboard\n"); + return mystrdup("?"); + } } + else + return mystrdup(""); XDeleteProperty(sdl_wminfo.info.x11.display, sdl_wminfo.info.x11.window, XA_CLIPBOARD); } sdl_wminfo.info.x11.unlock_func(); @@ -425,6 +431,113 @@ unsigned int lastTick = 0; float fps = 0, delta = 1.0f, inputScale = 1.0f; ui::Engine * engine = NULL; float currentWidth, currentHeight; + +void EventProcess(SDL_Event event) +{ + switch (event.type) + { + case SDL_QUIT: + if (engine->GetFastQuit() || engine->CloseWindow()) + engine->Exit(); + break; + case SDL_KEYDOWN: + engine->onKeyPress(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod&KEY_MOD_SHIFT, event.key.keysym.mod&KEY_MOD_CONTROL, event.key.keysym.mod&KEY_MOD_ALT); + break; + case SDL_KEYUP: + engine->onKeyRelease(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod&KEY_MOD_SHIFT, event.key.keysym.mod&KEY_MOD_CONTROL, event.key.keysym.mod&KEY_MOD_ALT); + break; + case SDL_MOUSEMOTION: + engine->onMouseMove(event.motion.x*inputScale, event.motion.y*inputScale); + break; + case SDL_MOUSEBUTTONDOWN: + if(event.button.button == SDL_BUTTON_WHEELUP) + { + engine->onMouseWheel(event.motion.x*inputScale, event.motion.y*inputScale, 1); + } + else if (event.button.button == SDL_BUTTON_WHEELDOWN) + { + engine->onMouseWheel(event.motion.x*inputScale, event.motion.y*inputScale, -1); + } + else + { + engine->onMouseClick(event.motion.x*inputScale, event.motion.y*inputScale, event.button.button); + } + break; + case SDL_MOUSEBUTTONUP: + if(event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) + engine->onMouseUnclick(event.motion.x*inputScale, event.motion.y*inputScale, event.button.button); + break; +#ifdef OGLI + case SDL_VIDEORESIZE: + { + float ratio = float(XRES+BARSIZE) / float(YRES+MENUSIZE); + float width = event.resize.w; + float height = width/ratio; + + sdl_scrn = SDL_SetVideoMode(event.resize.w, height, 32, SDL_OPENGL | SDL_RESIZABLE); + + glViewport(0, 0, width, height); + engine->g->Reset(); + //glScaled(width/currentWidth, height/currentHeight, 1.0f); + + currentWidth = width; + currentHeight = height; + inputScale = float(XRES+BARSIZE)/currentWidth; + + glLineWidth(currentWidth/float(XRES+BARSIZE)); + if(sdl_scrn == NULL) + { + std::cerr << "Oh bugger" << std::endl; + } + break; + } +#endif +#if defined (USE_SDL) && defined(LIN) && defined(SDL_VIDEO_DRIVER_X11) + case SDL_SYSWMEVENT: + if (event.syswm.msg->subsystem != SDL_SYSWM_X11) + break; + sdl_wminfo.info.x11.lock_func(); + XEvent xe = event.syswm.msg->event.xevent; + if (xe.type==SelectionClear) + { + if (clipboardText != NULL) { + free(clipboardText); + clipboardText = NULL; + } + } + else if (xe.type==SelectionRequest) + { + XEvent xr; + xr.xselection.type = SelectionNotify; + xr.xselection.requestor = xe.xselectionrequest.requestor; + xr.xselection.selection = xe.xselectionrequest.selection; + xr.xselection.target = xe.xselectionrequest.target; + xr.xselection.property = xe.xselectionrequest.property; + xr.xselection.time = xe.xselectionrequest.time; + if (xe.xselectionrequest.target==XA_TARGETS) + { + // send list of supported formats + Atom targets[] = {XA_TARGETS, XA_STRING, XA_UTF8_STRING}; + xr.xselection.property = xe.xselectionrequest.property; + XChangeProperty(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, xe.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char*)targets, (int)(sizeof(targets)/sizeof(Atom))); + } + // TODO: Supporting more targets would be nice + else if ((xe.xselectionrequest.target==XA_STRING || xe.xselectionrequest.target==XA_UTF8_STRING) && clipboardText) + { + XChangeProperty(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, xe.xselectionrequest.property, xe.xselectionrequest.target, 8, PropModeReplace, (unsigned char*)clipboardText, strlen(clipboardText)+1); + } + else + { + // refuse clipboard request + xr.xselection.property = None; + } + XSendEvent(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, 0, 0, &xr); + } + sdl_wminfo.info.x11.unlock_func(); +#endif + } +} + void EngineProcess() { int frameStart = SDL_GetTicks(); @@ -437,109 +550,7 @@ void EngineProcess() event.type = 0; while (SDL_PollEvent(&event)) { - switch (event.type) - { - case SDL_QUIT: - if (engine->GetFastQuit() || engine->CloseWindow()) - engine->Exit(); - break; - case SDL_KEYDOWN: - engine->onKeyPress(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod&KEY_MOD_SHIFT, event.key.keysym.mod&KEY_MOD_CONTROL, event.key.keysym.mod&KEY_MOD_ALT); - break; - case SDL_KEYUP: - engine->onKeyRelease(event.key.keysym.sym, event.key.keysym.unicode, event.key.keysym.mod&KEY_MOD_SHIFT, event.key.keysym.mod&KEY_MOD_CONTROL, event.key.keysym.mod&KEY_MOD_ALT); - break; - case SDL_MOUSEMOTION: - engine->onMouseMove(event.motion.x*inputScale, event.motion.y*inputScale); - break; - case SDL_MOUSEBUTTONDOWN: - if(event.button.button == SDL_BUTTON_WHEELUP) - { - engine->onMouseWheel(event.motion.x*inputScale, event.motion.y*inputScale, 1); - } - else if (event.button.button == SDL_BUTTON_WHEELDOWN) - { - engine->onMouseWheel(event.motion.x*inputScale, event.motion.y*inputScale, -1); - } - else - { - engine->onMouseClick(event.motion.x*inputScale, event.motion.y*inputScale, event.button.button); - } - break; - case SDL_MOUSEBUTTONUP: - if(event.button.button != SDL_BUTTON_WHEELUP && event.button.button != SDL_BUTTON_WHEELDOWN) - engine->onMouseUnclick(event.motion.x*inputScale, event.motion.y*inputScale, event.button.button); - break; -#ifdef OGLI - case SDL_VIDEORESIZE: - { - float ratio = float(XRES+BARSIZE) / float(YRES+MENUSIZE); - float width = event.resize.w; - float height = width/ratio; - - sdl_scrn = SDL_SetVideoMode(event.resize.w, height, 32, SDL_OPENGL | SDL_RESIZABLE); - - glViewport(0, 0, width, height); - engine->g->Reset(); - //glScaled(width/currentWidth, height/currentHeight, 1.0f); - - currentWidth = width; - currentHeight = height; - inputScale = float(XRES+BARSIZE)/currentWidth; - - glLineWidth(currentWidth/float(XRES+BARSIZE)); - if(sdl_scrn == NULL) - { - std::cerr << "Oh bugger" << std::endl; - } - break; - } -#endif -#if defined (USE_SDL) && defined(LIN) && defined(SDL_VIDEO_DRIVER_X11) - case SDL_SYSWMEVENT: - if (event.syswm.msg->subsystem != SDL_SYSWM_X11) - break; - sdl_wminfo.info.x11.lock_func(); - XEvent xe = event.syswm.msg->event.xevent; - if (xe.type==SelectionClear) - { - if (clipboardText != NULL) { - free(clipboardText); - clipboardText = NULL; - } - } - else if (xe.type==SelectionRequest) - { - XEvent xr; - xr.xselection.type = SelectionNotify; - xr.xselection.requestor = xe.xselectionrequest.requestor; - xr.xselection.selection = xe.xselectionrequest.selection; - xr.xselection.target = xe.xselectionrequest.target; - xr.xselection.property = xe.xselectionrequest.property; - xr.xselection.time = xe.xselectionrequest.time; - if (xe.xselectionrequest.target==XA_TARGETS) - { - // send list of supported formats - Atom targets[] = {XA_TARGETS, XA_STRING}; - xr.xselection.property = xe.xselectionrequest.property; - XChangeProperty(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, xe.xselectionrequest.property, XA_ATOM, 32, PropModeReplace, (unsigned char*)targets, (int)(sizeof(targets)/sizeof(Atom))); - } - // TODO: Supporting more targets would be nice - else if (xe.xselectionrequest.target==XA_STRING && clipboardText) - { - XChangeProperty(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, xe.xselectionrequest.property, xe.xselectionrequest.target, 8, PropModeReplace, (unsigned char*)clipboardText, strlen(clipboardText)+1); - } - else - { - // refuse clipboard request - xr.xselection.property = None; - } - XSendEvent(sdl_wminfo.info.x11.display, xe.xselectionrequest.requestor, 0, 0, &xr); - } - sdl_wminfo.info.x11.unlock_func(); - continue; -#endif - } + EventProcess(event); event.type = 0; //Clear last event } if(engine->Broken()) { engine->UnBreak(); break; } diff --git a/src/cat/LuaScriptInterface.cpp b/src/cat/LuaScriptInterface.cpp index d1319f7..d0b3b61 100644 --- a/src/cat/LuaScriptInterface.cpp +++ b/src/cat/LuaScriptInterface.cpp @@ -23,10 +23,6 @@ #include "client/HTTP.h" #include "PowderToy.h" -//#include "virtualmachine/VirtualMachine.h" -#include "pim/Parser.h" -#include "pim/Machine.h" - #include "LuaBit.h" #include "LuaWindow.h" @@ -118,7 +114,6 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m): initInterfaceAPI(); initRendererAPI(); initElementsAPI(); - initVirtualMachineAPI(); initGraphicsAPI(); initFileSystemAPI(); @@ -484,6 +479,7 @@ void LuaScriptInterface::initSimulationAPI() {"waterEqualization", simulation_waterEqualisation}, {"ambientAirTemp", simulation_ambientAirTemp}, {"elementCount", simulation_elementCount}, + {"can_move", simulation_canMove}, {"parts", simulation_parts}, {"pmap", simulation_pmap}, {"neighbours", simulation_neighbours}, @@ -1235,13 +1231,11 @@ int LuaScriptInterface::simulation_decoBox(lua_State * l) int y1 = luaL_optint(l,2,-1); int x2 = luaL_optint(l,3,-1); int y2 = luaL_optint(l,4,-1); - int rx = luaL_optint(l,5,5); - int ry = luaL_optint(l,6,5); - int r = luaL_optint(l,7,255); - int g = luaL_optint(l,8,255); - int b = luaL_optint(l,9,255); - int a = luaL_optint(l,10,255); - int tool = luaL_optint(l,11,0); + int r = luaL_optint(l,5,255); + int g = luaL_optint(l,6,255); + int b = luaL_optint(l,7,255); + int a = luaL_optint(l,8,255); + int tool = luaL_optint(l,9,0); luacon_sim->ApplyDecorationBox(x1, y1, x2, y2, r, g, b, a, tool); return 0; @@ -1508,6 +1502,27 @@ int LuaScriptInterface::simulation_elementCount(lua_State * l) return 1; } +int LuaScriptInterface::simulation_canMove(lua_State * l) +{ + int movingElement = luaL_checkint(l, 1); + int destinationElement = luaL_checkint(l, 2); + if (movingElement < 0 || movingElement >= PT_NUM) + return luaL_error(l, "Invalid element ID (%d)", movingElement); + if (destinationElement < 0 || destinationElement >= PT_NUM) + return luaL_error(l, "Invalid element ID (%d)", destinationElement); + + if (lua_gettop(l) < 3) + { + lua_pushnumber(l, luacon_sim->can_move[movingElement][destinationElement]); + return 1; + } + else + { + luacon_sim->can_move[movingElement][destinationElement] = luaL_checkint(l, 3); + return 0; + } +} + int PartsClosure(lua_State * l) { int i = lua_tointeger(l, lua_upvalueindex(1)); @@ -1873,49 +1888,6 @@ void LuaScriptInterface::initElementsAPI() } } -pim::VirtualMachine * LuaScriptInterface::updateVirtualMachines[PT_NUM]; - -int LuaScriptInterface::updateVM(UPDATE_FUNC_ARGS) -{ - pim::VirtualMachine * machine = updateVirtualMachines[parts[i].type]; - - machine->CSPush(i); - machine->CSPush(x); - machine->CSPush(y); - machine->Call(0); - - - /*vm::VirtualMachine * vMachine = updateVirtualMachines[parts[i].type]; - - vm::word w; - int argAddr = 0, argCount = 5; - vMachine->sim = sim; - - vMachine->OpPUSH(w); //Pointless null in stack - w.int4 = (argCount + 2) * sizeof(vm::word); - vMachine->OpENTER(w); - argAddr = 8; - - //Arguments - w.int4 = i; vMachine->Marshal(argAddr, w); argAddr += 4; - w.int4 = x; vMachine->Marshal(argAddr, w); argAddr += 4; - w.int4 = y; vMachine->Marshal(argAddr, w); argAddr += 4; - w.int4 = nt; vMachine->Marshal(argAddr, w); argAddr += 4; - w.int4 = surround_space; vMachine->Marshal(argAddr, w); argAddr += 4; - - w.int4 = 0; - vMachine->Push(w); - - vMachine->OpCALL(w); - vMachine->Run(); - w.int4 = (argCount + 2) * sizeof(vm::word); - vMachine->OpLEAVE(w); - vMachine->OpPOP(w); //Pop pointless null - vMachine->End();*/ - - return 0; -} - int LuaScriptInterface::elements_loadDefault(lua_State * l) { int args = lua_gettop(l); @@ -2238,11 +2210,6 @@ int LuaScriptInterface::elements_property(lua_State * l) else lua_el_mode[id] = 1; } - else if(lua_type(l, 3) == LUA_TLIGHTUSERDATA) - { - updateVirtualMachines[id] = (pim::VirtualMachine*)lua_touserdata(l, 3); - luacon_sim->elements[id].Update = &updateVM; - } else if(lua_type(l, 3) == LUA_TBOOLEAN && !lua_toboolean(l, 3)) { lua_el_func[id] = 0; @@ -2347,52 +2314,6 @@ int LuaScriptInterface::elements_free(lua_State * l) return 0; } -void LuaScriptInterface::initVirtualMachineAPI() -{ - //Methods - struct luaL_reg vmAPIMethods [] = { - {"loadProgram", virtualMachine_loadProgram}, - {NULL, NULL} - }; - luaL_register(l, "virtualMachine", vmAPIMethods); - - //elem shortcut - lua_getglobal(l, "virtualMachine"); - lua_setglobal(l, "vm"); -} - -int LuaScriptInterface::virtualMachine_loadProgram(lua_State * l) -{ - /*luaL_checktype(l, 1, LUA_TSTRING); - - vm::VirtualMachine * newVM = new vm::VirtualMachine(1); - try - { - const char * tempString = lua_tostring(l, 1); - int tempStringLength = lua_strlen(l, 1); - std::vector<char> programData(tempString, tempString+tempStringLength); - newVM->LoadProgram(programData); - } - catch(std::exception & e) - { - return luaL_error(l, "Unable to load program"); - } - lua_pushlightuserdata(l, newVM);*/ - std::string programSource(lua_tostring(l, 1)); - std::stringstream input(programSource); - - - pim::compiler::Parser * parser = new pim::compiler::Parser(input); - - std::vector<unsigned char> programData = parser->Compile(); - - pim::VirtualMachine * machine = new pim::VirtualMachine(luacon_sim); - machine->LoadProgram(programData); - - lua_pushlightuserdata(l, machine); - return 1; -} - void LuaScriptInterface::initGraphicsAPI() { //Methods diff --git a/src/cat/LuaScriptInterface.h b/src/cat/LuaScriptInterface.h index eda6832..b99d18c 100644 --- a/src/cat/LuaScriptInterface.h +++ b/src/cat/LuaScriptInterface.h @@ -16,10 +16,6 @@ namespace ui class Window; } -namespace pim -{ - class VirtualMachine; -} class Tool; //Because lua only has bindings for C, we're going to have to go outside "outside" the LuaScriptInterface, this means we can only have one instance :( @@ -101,6 +97,7 @@ class LuaScriptInterface: public CommandInterface static int simulation_waterEqualisation(lua_State * l); static int simulation_ambientAirTemp(lua_State * l); static int simulation_elementCount(lua_State * l); + static int simulation_canMove(lua_State * l); static int simulation_parts(lua_State * l); static int simulation_pmap(lua_State * l); static int simulation_neighbours(lua_State * l); @@ -115,9 +112,6 @@ class LuaScriptInterface: public CommandInterface static int renderer_debugHUD(lua_State * l); //Elements - static pim::VirtualMachine * updateVirtualMachines[PT_NUM]; - static int updateVM(UPDATE_FUNC_ARGS); - // void initElementsAPI(); static int elements_allocate(lua_State * l); static int elements_element(lua_State * l); @@ -132,10 +126,6 @@ class LuaScriptInterface: public CommandInterface static int interface_addComponent(lua_State * l); static int interface_removeComponent(lua_State * l); - //VM - void initVirtualMachineAPI(); - static int virtualMachine_loadProgram(lua_State * l); - void initGraphicsAPI(); static int graphics_textSize(lua_State * l); static int graphics_drawText(lua_State * l); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index 41dc248..4f434ac 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -1347,8 +1347,15 @@ void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool c->ShowConsole(); break; case 'p': + case KEY_F2: screenshot(); break; + case KEY_F3: + SetDebugHUD(!GetDebugHUD()); + break; + case KEY_F5: + c->ReloadSim(); + break; case 'r': if (ctrl) c->ReloadSim(); diff --git a/src/gui/interface/Keys.h b/src/gui/interface/Keys.h index c42a894..b74042f 100644 --- a/src/gui/interface/Keys.h +++ b/src/gui/interface/Keys.h @@ -45,6 +45,9 @@ #define KEY_w SDLK_w #define KEY_F1 SDLK_F1 +#define KEY_F2 SDLK_F2 +#define KEY_F3 SDLK_F3 +#define KEY_F5 SDLK_F5 #define BUTTON_LEFT SDL_BUTTON_LEFT #define BUTTON_MIDDLE SDL_BUTTON_MIDDLE @@ -83,5 +86,8 @@ #define KEY_w 25 #define KEY_F1 26 +#define KEY_F2 27 +#define KEY_F3 28 +#define KEY_F5 29 #endif diff --git a/src/pim/Generator.cpp b/src/pim/Generator.cpp deleted file mode 100644 index 3292c8a..0000000 --- a/src/pim/Generator.cpp +++ /dev/null @@ -1,518 +0,0 @@ -//Code generator for bytecode -#include <sstream> -#include <fstream> -#include "Format.h" -#include "Generator.h" -#include "Opcodes.h" -namespace pim -{ - namespace compiler - { - Generator::Generator() : - output(std::cout), - labelCounter(0), - programCounter(0) - { - - } - - void Generator::defineLabel(std::string label) - { - Label newLabel; - newLabel.Name = label; - newLabel.Position = programCounter;//program.size(); - labelPositions.push_back(newLabel); - } - - void Generator::writeOpcode(int opcode) - { - programCounter++; - program.push_back(opcode); - } - - void Generator::writeConstant(std::string constant) - { - writeConstant(format::StringToNumber<int>(constant)); - } - - void Generator::writeConstant(int constant) - { - program.push_back(constant & 0xFF); - program.push_back((constant>>8) & 0xFF); - program.push_back((constant>>16) & 0xFF); - program.push_back((constant>>24) & 0xFF); - } - - void Generator::writeConstantPlaceholder(std::string label) - { - placeholders.push_back(Placeholder(program.size(), label)); - program.push_back(0); - program.push_back(0); - program.push_back(0); - program.push_back(0); - } - - void Generator::writeConstantPlaceholder(int * value) - { - valuePlaceholders.push_back(ValuePlaceholder(program.size(), value)); - program.push_back(0); - program.push_back(0); - program.push_back(0); - program.push_back(0); - } - - void Generator::writeConstantPropertyPlaceholder(std::string property) - { - propertyPlaceholders.push_back(PropertyPlaceholder(program.size(), property)); - program.push_back(0); - program.push_back(0); - program.push_back(0); - program.push_back(0); - } - - void Generator::writeConstantMacroPlaceholder(std::string macro) - { - macroPlaceholders.push_back(MacroPlaceholder(program.size(), macro)); - program.push_back(0); - program.push_back(0); - program.push_back(0); - program.push_back(0); - } - - std::vector<unsigned char> Generator::Finish() - { - //All compile time labels, macros, etc - for(std::vector<Placeholder>::iterator iter = placeholders.begin(), end = placeholders.end(); iter != end; ++iter) - { - bool found = false; - Placeholder cPosition = *iter; - for(std::vector<Label>::iterator iter2 = labelPositions.begin(), end2 = labelPositions.end(); iter2 != end2; ++iter2) - { - Label cLabel = *iter2; - if(cPosition.second == cLabel.Name) - { - std::cout << "Setting placeholder at " << cPosition.first << " with " << cLabel.Position << " for" << cPosition.second << std::endl; - found = true; - program[cPosition.first] = cLabel.Position & 0xFF; - program[cPosition.first+1] = (cLabel.Position >> 8) & 0xFF; - program[cPosition.first+2] = (cLabel.Position >> 16) & 0xFF; - program[cPosition.first+3] = (cLabel.Position >> 24) & 0xFF; - break; - } - } - if(!found) - throw SymbolNotFoundException(cPosition.second); - } - - for(std::vector<ValuePlaceholder>::iterator iter = valuePlaceholders.begin(), end = valuePlaceholders.end(); iter != end; ++iter) - { - ValuePlaceholder cPosition = *iter; - int value = *cPosition.second; - - std::cout << "Setting value placeholder at " << cPosition.first << " with " << value << std::endl; - - - program[cPosition.first] = value & 0xFF; - program[cPosition.first+1] = (value >> 8) & 0xFF; - program[cPosition.first+2] = (value >> 16) & 0xFF; - program[cPosition.first+3] = (value >> 24) & 0xFF; - } - - //Build file - int macroSizePos, propSizePos, codeSizePos, macroSize = 0, propSize = 0, codeSize = program.size(); - std::vector<unsigned char> file; - file.push_back('P'); - file.push_back('V'); - file.push_back('M'); - file.push_back('1'); - - - macroSizePos = file.size(); - file.push_back(0); - file.push_back(0); - file.push_back(0); - file.push_back(0); - - propSizePos = file.size(); - file.push_back(0); - file.push_back(0); - file.push_back(0); - file.push_back(0); - - codeSizePos = file.size(); - file.push_back(0); - file.push_back(0); - file.push_back(0); - file.push_back(0); - - //Macros - for(std::vector<MacroPlaceholder>::iterator iter = macroPlaceholders.begin(), end = macroPlaceholders.end(); iter != end; ++iter) - { - MacroPlaceholder cPosition = *iter; - int position = cPosition.first; - - file.push_back(position & 0xFF); - file.push_back((position >> 8) & 0xFF); - file.push_back((position >> 16) & 0xFF); - file.push_back((position >> 24) & 0xFF); - macroSize += 4; - - file.push_back(cPosition.second.length()); - macroSize += 1; - file.insert(file.end(), cPosition.second.begin(), cPosition.second.end()); - macroSize += cPosition.second.length(); - } - - file[macroSizePos] = macroSize & 0xFF; - file[macroSizePos+1] = (macroSize >> 8) & 0xFF; - file[macroSizePos+2] = (macroSize >> 16) & 0xFF; - file[macroSizePos+3] = (macroSize >> 24) & 0xFF; - - - //Macros - for(std::vector<PropertyPlaceholder>::iterator iter = propertyPlaceholders.begin(), end = propertyPlaceholders.end(); iter != end; ++iter) - { - PropertyPlaceholder cPosition = *iter; - int position = cPosition.first; - - file.push_back(position & 0xFF); - file.push_back((position >> 8) & 0xFF); - file.push_back((position >> 16) & 0xFF); - file.push_back((position >> 24) & 0xFF); - propSize += 4; - - file.push_back(cPosition.second.length()); - propSize += 1; - file.insert(file.end(), cPosition.second.begin(), cPosition.second.end()); - propSize += cPosition.second.length(); - } - - file[propSizePos] = propSize & 0xFF; - file[propSizePos+1] = (propSize >> 8) & 0xFF; - file[propSizePos+2] = (propSize >> 16) & 0xFF; - file[propSizePos+3] = (propSize >> 24) & 0xFF; - - file.insert(file.end(), program.begin(), program.end()); - - file[codeSizePos] = codeSize & 0xFF; - file[codeSizePos+1] = (codeSize >> 8) & 0xFF; - file[codeSizePos+2] = (codeSize >> 16) & 0xFF; - file[codeSizePos+3] = (codeSize >> 24) & 0xFF; - - std::ofstream newFile("test.pvm"); - for(std::vector<unsigned char>::iterator iter = file.begin(), end = file.end(); iter != end; ++iter) - { - newFile.put(*iter); - } - newFile.close(); - - return file; - } - - std::string Generator::UniqueLabel(std::string prefix) - { - std::stringstream label; - label << prefix; - label << "_"; - label << labelCounter; - label << "_"; - return label.str(); - } - - void Generator::PushScope(std::string label) - { - scopes.push(currentScope); - Scope * prevScope = currentScope; - currentScope = new Scope(); - defineLabel(label); - - output << "." << label << std::endl; - } - - void Generator::PushLocalScope(std::string label) - { - scopes.push(currentScope); - Scope * prevScope = currentScope; - currentScope = new Scope(); - currentScope->Definitions.insert(currentScope->Definitions.begin(), prevScope->Definitions.begin(), prevScope->Definitions.end()); - currentScope->FrameSize = prevScope->FrameSize; - defineLabel(label); - - output << "." << label << std::endl; - } - - void Generator::PopScope() - { - - writeOpcode(Opcode::Return); - writeConstant(currentScope->LocalFrameSize); - - output << "return " << currentScope->LocalFrameSize << std::endl; - - currentScope = scopes.top(); - scopes.pop(); - } - - void Generator::ScopeLabel(std::string label) - { - //defineLabelwriteOpcode("." << label); - defineLabel(label); - - output << "." << label << std::endl; - } - - void Generator::LocalEnter() - { - writeOpcode(Opcode::LocalEnter); - writeConstantPlaceholder(&(currentScope->LocalFrameSize)); - - output << "enter " << "#" << std::endl; - } - - void Generator::ScopeVariableType(int type) - { - variableType = type; - } - - void Generator::ScopeVariable(std::string label) - { - currentScope->Definitions.push_back(Definition(label, variableType, currentScope->FrameSize)); - currentScope->FrameSize += 4; - currentScope->LocalFrameSize += 4; - - output << "#declare " << label << " " << currentScope->FrameSize-4 << std::endl; - } - - void Generator::PushVariableAddress(std::string label) - { - //writeOpcode("address"); << " " << currentScope->GetDefinition(label).StackPosition - } - - void Generator::LoadVariable(std::string label) - { - writeOpcode(Opcode::Load); - writeConstant(currentScope->GetDefinition(label).StackPosition); - - output << "load " << label << std::endl; - } - - void Generator::StoreVariable(std::string label) - { - writeOpcode(Opcode::Store); - writeConstant(currentScope->GetDefinition(label).StackPosition); - - output << "store " << label << std::endl; - } - - void Generator::RTConstant(std::string name) - { - writeOpcode(Opcode::Constant); - writeConstantMacroPlaceholder(name); - - output << "const " << name << std::endl; - } - - void Generator::Constant(std::string constant) - { - writeOpcode(Opcode::Constant); - writeConstant(constant); - - output << "const " << constant << std::endl; - - } - - void Generator::Increment(std::string constant) - { - writeOpcode(Opcode::Increment); - writeConstant(constant); - - output << "inc " << constant << std::endl; - } - - void Generator::Discard() - { - writeOpcode(Opcode::Discard); - - output << "discard" << std::endl; - } - - void Generator::Duplicate() - { - writeOpcode(Opcode::Duplicate); - - output << "duplicate" << std::endl; - } - - void Generator::Add() - { - writeOpcode(Opcode::Add); - - output << "add" << std::endl; - } - - void Generator::Subtract() - { - writeOpcode(Opcode::Subtract); - - output << "sub" << std::endl; - } - - void Generator::Multiply() - { - writeOpcode(Opcode::Multiply); - - output << "mul" << std::endl; - } - - void Generator::Divide() - { - writeOpcode(Opcode::Divide); - - output << "div" << std::endl; - } - - void Generator::Modulus() - { - writeOpcode(Opcode::Modulus); - - output << "add" << std::endl; - } - - void Generator::Negate() - { - writeOpcode(Opcode::Negate); - - output << "neg" << std::endl; - } - - void Generator::CreateParticle() - { - writeOpcode(Opcode::Create); - - output << "create" << std::endl; - } - - void Generator::TransformParticle() - { - writeOpcode(Opcode::Transform); - - output << "transform" << std::endl; - } - - void Generator::GetParticle() - { - writeOpcode(Opcode::Get); - - output << "getpart" << std::endl; - } - - void Generator::GetPosition() - { - writeOpcode(Opcode::Position); - - output << "getpos" << std::endl; - } - - void Generator::KillParticle() - { - writeOpcode(Opcode::Kill); - - output << "kill" << std::endl; - } - - void Generator::LoadProperty(std::string property) - { - writeOpcode(Opcode::LoadProperty); - writeConstantPropertyPlaceholder(property); - - output << "loadprop " << property << std::endl; - } - - void Generator::StoreProperty(std::string property) - { - writeOpcode(Opcode::StoreProperty); - writeConstantPropertyPlaceholder(property); - - output << "storeprop " << property << std::endl; - } - - void Generator::IntegerToDecimal() - { - - } - - void Generator::DecimalToInteger() - { - - } - - - void Generator::JumpEqual(std::string label) - { - writeOpcode(Opcode::JumpEqual); - writeConstantPlaceholder(label); - - output << "jumpe " << label << std::endl; - } - - void Generator::JumpNotEqual(std::string label) - { - writeOpcode(Opcode::JumpNotEqual); - writeConstantPlaceholder(label); - - output << "jumpne " << label << std::endl; - } - - void Generator::JumpGreater(std::string label) - { - writeOpcode(Opcode::JumpGreater); - writeConstantPlaceholder(label); - - output << "jumpg " << label << std::endl; - } - - void Generator::JumpGreaterEqual(std::string label) - { - writeOpcode(Opcode::JumpGreaterEqual); - writeConstantPlaceholder(label); - - output << "jumpge " << label << std::endl; - } - - void Generator::JumpLess(std::string label) - { - writeOpcode(Opcode::JumpLess); - writeConstantPlaceholder(label); - - output << "jumpl " << label << std::endl; - } - - void Generator::JumpLessEqual(std::string label) - { - writeOpcode(Opcode::JumpLessEqual); - writeConstantPlaceholder(label); - - output << "jumple " << label << std::endl; - } - - void Generator::Jump(std::string label) - { - writeOpcode(Opcode::Jump); - writeConstantPlaceholder(label); - - output << "jump " << label << std::endl; - } - - - void Generator::Call(int arguments, std::string label) - { - - } - - void Generator::Return() - { - - } - - } -} diff --git a/src/pim/Generator.h b/src/pim/Generator.h deleted file mode 100644 index 4dd2cfe..0000000 --- a/src/pim/Generator.h +++ /dev/null @@ -1,178 +0,0 @@ -#pragma once - -#include <cstring> -#include <vector> -#include <stack> -#include <iostream> -#include "Token.h" -namespace pim -{ - namespace compiler - { - class VariableNotFoundException: public std::exception - { - char * error; - public: - VariableNotFoundException(std::string variable) { - error = strdup(std::string("Could not find the variable \""+variable+"\" in the current scope").c_str()); - } - const char * what() const throw() - { - return error; - } - ~VariableNotFoundException() throw() {}; - }; - - class SymbolNotFoundException: public std::exception - { - char * error; - public: - SymbolNotFoundException(std::string variable) { - error = strdup(std::string("Could not find the symbol \""+variable+"\".").c_str()); - } - const char * what() const throw() - { - return error; - } - ~SymbolNotFoundException() throw() {}; - }; - class Type - { - enum { Integer = Token::IntegerSymbol, Decimal = Token::DecimalSymbol }; - }; - class Definition - { - public: - std::string Name; - int Type; - int StackPosition; - Definition(std::string name, int type, int position) : - Type(type), - Name(name), - StackPosition(position) - { - - } - }; - - struct Label - { - std::string Name; - int Position; - }; - - class Scope - { - public: - std::vector<Definition> Definitions; - std::vector<Label> Labels; - int FrameSize; - int LocalFrameSize; - Scope(): - FrameSize(0), - LocalFrameSize(0) - { - - } - Definition GetDefinition(std::string name) - { - for(std::vector<Definition>::iterator iter = Definitions.begin(), end = Definitions.end(); iter != end; ++iter) - { - if((*iter).Name == name) - return *iter; - } - throw VariableNotFoundException(name); - } - }; - - class Generator - { - int variableType; - std::stack<Scope*> scopes; - Scope * currentScope; - std::ostream & output; - int labelCounter; - int programCounter; - - typedef std::pair<int, std::string> Placeholder; - std::vector<Placeholder> placeholders; - - typedef std::pair<int, int*> ValuePlaceholder; - std::vector<ValuePlaceholder> valuePlaceholders; - - typedef std::pair<int, std::string> PropertyPlaceholder; - std::vector<PropertyPlaceholder> propertyPlaceholders; - - typedef std::pair<int, std::string> MacroPlaceholder; - std::vector<MacroPlaceholder> macroPlaceholders; - - std::vector<Label> labelPositions; - - std::vector<unsigned char> program; - - void defineLabel(std::string label); - void writeOpcode(int opcode); - void writeConstant(std::string constant); - void writeConstant(int constant); - void writeConstantPlaceholder(std::string label); - void writeConstantPlaceholder(int * value); - void writeConstantMacroPlaceholder(std::string macro); - void writeConstantPropertyPlaceholder(std::string property); - - public: - Generator(); - - std::vector<unsigned char> Finish(); - - std::string UniqueLabel(std::string prefix); - - void PushScope(std::string label); - void PushLocalScope(std::string label); - void LocalEnter(); - void PopScope(); - - void ScopeLabel(std::string label); - void ScopeVariableType(int type); - void ScopeVariable(std::string label); - - void PushVariableAddress(std::string label); -// void Store(); - void LoadVariable(std::string label); - void StoreVariable(std::string label); - - void Duplicate(); - void Discard(); - void RTConstant(std::string name); - void Constant(std::string constant); - void Increment(std::string constant); - void Add(); - void Subtract(); - void Multiply(); - void Divide(); - void Modulus(); - void Negate(); - - void TransformParticle(); - void CreateParticle(); - void GetParticle(); - void GetPosition(); - void KillParticle(); - void LoadProperty(std::string property); - void StoreProperty(std::string property); - - void IntegerToDecimal(); - void DecimalToInteger(); - - void JumpEqual(std::string label); - void JumpNotEqual(std::string label); - void JumpGreater(std::string label); - void JumpGreaterEqual(std::string label); - void JumpLess(std::string label); - void JumpLessEqual(std::string label); - void Jump(std::string label); - - void Call(int arguments, std::string label); - void Return(); - }; - } -} diff --git a/src/pim/Machine.cpp b/src/pim/Machine.cpp deleted file mode 100644 index a954d31..0000000 --- a/src/pim/Machine.cpp +++ /dev/null @@ -1,637 +0,0 @@ -//Virtual machine - -#include <iostream> -#include "Machine.h" -#include "Opcodes.h" -#include "simulation/Simulation.h" -namespace pim -{ - /*unsigned char * rom; - int romSize; - int romMask; - - unsigned char * ram; - int ramSize; - int ramMask; - - int programStack; - int callStack;*/ - - VirtualMachine::VirtualMachine(Simulation * simulation) : - rom(NULL), - ram(NULL), - sim(simulation) - { - - } - - void VirtualMachine::LoadProgram(std::vector<unsigned char> fileData) - { - int lastBit = 0; - - if(!(fileData[0] == 'P' && fileData[1] == 'V' && fileData[2] == 'M' && fileData[3] == '1' && fileData.size() >= 16)) - { - throw InvalidProgramException(); - } - - int macroSize = 0, propSize = 0, codeSize = 0; - macroSize = fileData[4]; - macroSize |= fileData[5] << 8; - macroSize |= fileData[6] << 16; - macroSize |= fileData[7] << 24; - - propSize = fileData[8]; - propSize |= fileData[9] << 8; - propSize |= fileData[10] << 16; - propSize |= fileData[11] << 24; - - codeSize = fileData[12]; - codeSize |= fileData[13] << 8; - codeSize |= fileData[14] << 16; - codeSize |= fileData[15] << 24; - - if(fileData.size() < 16 + macroSize + propSize + codeSize) - { - throw InvalidProgramException(); - } - - //std::vector<std::pair<int, int> > insertions; - - int macroOffset = 16; - int propOffset = macroOffset+macroSize; - int codeOffset = propOffset+propSize; - - - int filePosition = macroOffset; - while(filePosition + 4 < macroSize + macroOffset) - { - std::string macro; - int macroPosition; - int macroValue; - - macroPosition = fileData[filePosition++]; - macroPosition |= fileData[filePosition++] << 8; - macroPosition |= fileData[filePosition++] << 16; - macroPosition |= fileData[filePosition++] << 24; - - int stringLength = fileData[filePosition++]; - if(filePosition + stringLength > macroSize + macroOffset) - { - throw InvalidProgramException(); - } - - macro.insert(macro.begin(), fileData.begin()+filePosition, fileData.begin()+filePosition+stringLength); - filePosition += stringLength; - - bool resolved = false; - for(int i = 0; i < PT_NUM; i++) - { - if(sim->elements[i].Enabled && sim->elements[i].Identifier == macro) - { - macroValue = i; - resolved = true; - } - } - if(!resolved) - { - throw UnresolvedValueException(macro); - } - - if(macroPosition + 3 >= codeSize) - { - throw InvalidProgramException(); - } - - std::cout << "Macro insertion [" << macro << "] at " << macroPosition << " with " << macroValue << std::endl; - - fileData[codeOffset+macroPosition] = macroValue & 0xFF; - fileData[codeOffset+macroPosition+1] = (macroValue >> 8) & 0xFF; - fileData[codeOffset+macroPosition+2] = (macroValue >> 16) & 0xFF; - fileData[codeOffset+macroPosition+3] = (macroValue >> 24) & 0xFF; - //insertions.push_back(std::pair<int, int>(macroPosition, macroValue)); - } - - filePosition = propOffset; - while(filePosition + 4 < propSize + propOffset) - { - std::string prop; - int propPosition; - int propValue; - - propPosition = fileData[filePosition++]; - propPosition |= fileData[filePosition++] << 8; - propPosition |= fileData[filePosition++] << 16; - propPosition |= fileData[filePosition++] << 24; - - int stringLength = fileData[filePosition++]; - if(filePosition + stringLength > propSize + propOffset) - { - throw InvalidProgramException(); - } - - prop.insert(prop.begin(), fileData.begin()+filePosition, fileData.begin()+filePosition+stringLength); - filePosition += stringLength; - - bool resolved = false; - - std::vector<StructProperty> properties = Particle::GetProperties(); - for(std::vector<StructProperty>::iterator iter = properties.begin(), end = properties.end(); iter != end; ++iter) - { - StructProperty property = *iter; - std::cout << property.Offset << std::endl; - if(property.Name == prop && - (property.Type == StructProperty::ParticleType || - property.Type == StructProperty::Colour || - property.Type == StructProperty::Integer || - property.Type == StructProperty::UInteger || - property.Type == StructProperty::Float) - ) - { - propValue = property.Offset; - resolved = true; - break; - } - } - if(!resolved) - { - throw UnresolvedValueException(prop); - } - - if(propPosition + 3 >= codeSize) - { - throw InvalidProgramException(); - } - - std::cout << "Property insertion [" << prop << "] at " << propPosition << " with " << propValue << std::endl; - - fileData[codeOffset+propPosition] = propValue & 0xFF; - fileData[codeOffset+propPosition+1] = (propValue >> 8) & 0xFF; - fileData[codeOffset+propPosition+2] = (propValue >> 16) & 0xFF; - fileData[codeOffset+propPosition+3] = (propValue >> 24) & 0xFF; - //insertions.push_back(std::pair<int, int>(macroPosition, macroValue)); - } - - std::vector<unsigned char> programData; - programData.insert(programData.begin(), fileData.begin()+codeOffset, fileData.begin()+codeOffset+codeSize); - - romSize = programData.size(); - - for (lastBit = 0; romSize > (1 << lastBit); lastBit++ ) { } - romSize = 1 << lastBit; - romMask = romSize - 1; - - rom = new Instruction[romSize]; - - int pc = 0; - int programPosition = 0; - - while(programPosition < programData.size()) - { - int argSize = 0; - Instruction instruction; - instruction.Opcode = programData[programPosition++]; - if(argSize = OpcodeArgSize(instruction.Opcode)) - { - if(argSize == 4 && programPosition+3 < programData.size()) - { - int tempInt = 0; - tempInt |= programData[programPosition]; - tempInt |= programData[programPosition+1] << 8; - tempInt |= programData[programPosition+2] << 16; - tempInt |= programData[programPosition+3] << 24; - - - std::cout << "Got integer " << tempInt << std::endl; - - if(instruction.Opcode == Opcode::LoadProperty || instruction.Opcode == Opcode::StoreProperty) - { - if(tempInt > offsetof(Particle, dcolour)) - throw InvalidProgramException(); - } - - instruction.Parameter.Integer = tempInt; - - programPosition += 4; - } - } - else - { - instruction.Parameter.Integer = 0; - } - rom[pc++] = instruction; - } - romSize = pc; - - ramSize = 1024; - ramMask = ramSize - 1; - - ram = new unsigned char[ramSize]; - programStack = ramSize-1; - callStack = ramSize-260; - - framePointer = callStack; - callStack += WORDSIZE; //Since there's nothing on the stack, it shouldn't point to the item on the bottom - } - - int VirtualMachine::OpcodeArgSize(int opcode) - { - switch(opcode) - { - case Opcode::Load: - case Opcode::Store: - case Opcode::Constant: - case Opcode::Increment: - case Opcode::JumpEqual: - case Opcode::JumpNotEqual: - case Opcode::JumpGreater: - case Opcode::JumpGreaterEqual: - case Opcode::JumpLess: - case Opcode::JumpLessEqual: - case Opcode::Jump: - case Opcode::Return: - case Opcode::LocalEnter: - case Opcode::LoadProperty: - case Opcode::StoreProperty: - return 4; - case Opcode::Discard: - case Opcode::Duplicate: - case Opcode::Add: - case Opcode::Subtract: - case Opcode::Multiply: - case Opcode::Divide: - case Opcode::Modulus: - case Opcode::Negate: - case Opcode::Create: - case Opcode::Transform: - case Opcode::Get: - case Opcode::Position: - case Opcode::Kill: - return 0; - } - } - - 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"}; - - Word temp1; - Word temp2; - Word temp3; - Word temp4; - int temp; - while(programCounter < romSize) - { - Word argument = rom[programCounter].Parameter; - //std::cerr << programCounter << "\t" << names[rom[programCounter].Opcode] << "\t" << argument.Integer << std::endl;//"\t"; - switch(rom[programCounter].Opcode) - { - case Opcode::Load: - PSPush(CSA(argument.Integer)); - break; - case Opcode::Store: - CSA(argument.Integer) = PSPop(); - break; - case Opcode::Constant: - PSPush(argument); - break; - case Opcode::Increment: - PS().Integer += argument.Integer; - break; - case Opcode::Discard: - programStack += WORDSIZE; - break; - case Opcode::Duplicate: - PSPush(PS()); - break; - case Opcode::Add: - PSPush(PSPop().Integer + PSPop().Integer); - break; - case Opcode::Subtract: - temp1 = PSPop(); - PSPush(PSPop().Integer - temp1.Integer); - break; - case Opcode::Multiply: - PSPush(PSPop().Integer * PSPop().Integer); - break; - case Opcode::Divide: - temp1 = PSPop(); - PSPush(PSPop().Integer / temp1.Integer); - break; - case Opcode::Modulus: - temp1 = PSPop(); - PSPush(PSPop().Integer % temp1.Integer); - break; - case Opcode::Negate: - PS().Integer = -PS().Integer; - 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: - if(PSPop().Integer == PSPop().Integer) - programCounter = argument.Integer-1; - break; - case Opcode::JumpNotEqual: - if(PSPop().Integer != PSPop().Integer) - programCounter = argument.Integer-1; - break; - case Opcode::JumpGreater: - temp1 = PSPop(); - if(PSPop().Integer > temp1.Integer) - programCounter = argument.Integer-1; - break; - case Opcode::JumpGreaterEqual: - temp1 = PSPop(); - if(PSPop().Integer >= temp1.Integer) - programCounter = argument.Integer-1; - break; - case Opcode::JumpLess: - temp1 = PSPop(); - if(PSPop().Integer < temp1.Integer) - programCounter = argument.Integer-1; - break; - case Opcode::JumpLessEqual: - temp1 = PSPop(); - if(PSPop().Integer <= temp1.Integer) - programCounter = argument.Integer-1; - break; - case Opcode::Jump: - programCounter = argument.Integer-1; - break; - case Opcode::Return: - callStack += argument.Integer; - break; - case Opcode::LocalEnter: - callStack -= argument.Integer; - break; - } - //std::cout << programStack << std::endl; - programCounter++; - } - //std::cout << "CS: " << callStack << " PS: " << programStack << std::endl; - } - - 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 - - //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)); - - //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) - { - - } - - void VirtualMachine::CallCompiled(std::string entryPoint) - { - - } - - void VirtualMachine::CallCompiled(int entryPoint) - { - - } - - void VirtualMachine::Call(std::string entryPoint) - { - - } - - void VirtualMachine::Call(int entryPoint) - { - programCounter = entryPoint; - Run(); - } -} diff --git a/src/pim/Machine.h b/src/pim/Machine.h deleted file mode 100644 index 0cbac4c..0000000 --- a/src/pim/Machine.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include <vector> -#include <string> -#include <cstring> - -class Simulation; -namespace pim -{ - union Word - { - int Integer; - float Decimal; - - Word(int integer) : Integer(integer) {} - Word(float decimal) : Decimal(decimal) {} - Word() {} - }; - struct Instruction - { - int Opcode; - Word Parameter; - }; - class InvalidProgramException: public std::exception - { - public: - InvalidProgramException() { } - const char * what() const throw() - { - return "Invalid program"; - } - ~InvalidProgramException() throw() {}; - }; - class UnresolvedValueException: public std::exception - { - char * error; - public: - UnresolvedValueException(std::string value) { - error = strdup(std::string("Unresolved value: " + value).c_str()); - } - const char * what() const throw() - { - return error; - } - ~UnresolvedValueException() throw() {}; - }; - class VirtualMachine - { - - #define WORDSIZE 4 - - //#define OPDEF(name) void op##name(int parameter); - //#include "Opcodes.inl" - //#undef OPDEF - - Simulation * sim; - - Instruction * rom; - int romSize; - int romMask; - - unsigned char * compiledRom; - int compiledRomSize; - - unsigned char * ram; - int ramSize; - int ramMask; - - #define CSA(argument) (*((Word*)&ram[framePointer-argument])) - #define CS() (*((Word*)&ram[callStack])) - #define PS() (*((Word*)&ram[programStack])) - #define PPROP(index, property) (*((Word*)(((char*)&sim->parts[(index)])+property))) - - int programStack; //Points to the item on top of the Program Stack - int callStack; //Points to the item on top of the call stack - int framePointer; //Points to the bottom (first item) on the current frame of the call stack - - //Instruction * instructions; - - int programCounter; - - void emit(std::string opcode); - void emit(int constant); - public: - VirtualMachine(Simulation * sim); - int OpcodeArgSize(int opcode); - void LoadProgram(std::vector<unsigned char> programData); - void Run(); - void Compile(); - void CallCompiled(std::string entryPoint); - void CallCompiled(int entryPoint); - void Call(std::string entryPoint); - void Call(int entryPoint); - inline void PSPush(Word word) - { - programStack -= WORDSIZE; - PS() = word; - } - - inline Word PSPop() - { - Word word = PS(); - programStack += WORDSIZE; - return word; - } - - inline void CSPush(Word word) - { - callStack -= WORDSIZE; - CS() = word; - } - - inline Word CSPop() - { - Word word = CS(); - callStack += WORDSIZE; - return word; - } - }; -} diff --git a/src/pim/Opcodes.h b/src/pim/Opcodes.h deleted file mode 100644 index a701e97..0000000 --- a/src/pim/Opcodes.h +++ /dev/null @@ -1,12 +0,0 @@ -namespace pim -{ - struct Opcode - { - enum - { - #define OPDEF(name) name, - #include "Opcodes.inl" - #undef OPDEF - }; - }; -} diff --git a/src/pim/Opcodes.inl b/src/pim/Opcodes.inl deleted file mode 100644 index 4b28294..0000000 --- a/src/pim/Opcodes.inl +++ /dev/null @@ -1,28 +0,0 @@ -OPDEF(Load) -OPDEF(Store) -OPDEF(Constant) -OPDEF(Increment) -OPDEF(Discard) -OPDEF(Duplicate) -OPDEF(Add) -OPDEF(Subtract) -OPDEF(Multiply) -OPDEF(Divide) -OPDEF(Modulus) -OPDEF(Negate) -OPDEF(Create) -OPDEF(Transform) -OPDEF(Get) -OPDEF(Position) -OPDEF(Kill) -OPDEF(LoadProperty) -OPDEF(StoreProperty) -OPDEF(JumpEqual) -OPDEF(JumpNotEqual) -OPDEF(JumpGreater) -OPDEF(JumpGreaterEqual) -OPDEF(JumpLess) -OPDEF(JumpLessEqual) -OPDEF(Jump) -OPDEF(Return) -OPDEF(LocalEnter)
\ No newline at end of file diff --git a/src/pim/Parser.cpp b/src/pim/Parser.cpp deleted file mode 100644 index 0165141..0000000 --- a/src/pim/Parser.cpp +++ /dev/null @@ -1,653 +0,0 @@ -//Syntax analyser -#include "Parser.h" -#include "Format.h" -namespace pim -{ - namespace compiler - { - Parser::Parser(std::stringstream & source_) : - source(source_) - { - scanner = new Scanner(source); - generator = new Generator(); - - token = scanner->NextToken(); - - } - - std::vector<unsigned char> Parser::Compile() - { - program(); - return generator->Finish(); - } - - /* - <program> ::= <function list> - */ - void Parser::program() - { - functionList(); - } - - /* - <function list> ::= <function> | <function> <function list> - */ - void Parser::functionList() - { - function(); - while(look(Token::FunctionSymbol)) - function(); - } - - /* - <function> ::= function identifier ( <declaration list> ) <block> end - */ - void Parser::function() - { - std::string functionName; - - expect(Token::FunctionSymbol); - - functionName = token.Source; - //generator->ScopeLabel(functionName); //Function name - generator->PushScope(functionName); - expect(Token::Identifier); - - expect(Token::LeftBracket); - if(!accept(Token::RightBracket)) - { - argumentList(); - expect(Token::RightBracket); - } - block(); - expect(Token::EndSymbol); - generator->Return(); - - generator->PopScope(); - } - - /* - <function call> ::= identifier ( <expression list> ) - */ - void Parser::functionCall() - { - std::string functionName; - - functionName = token.Source; - expect(Token::Identifier); - expect(Token::LeftBracket); - expressionList(); - expect(Token::RightBracket); - //generator->Call(functionName); - } - - /* - <block> ::= <declaration list> <statement list> - */ - void Parser::block() - { - if(look(Token::IntegerSymbol) || look(Token::DecimalSymbol) || look(Token::ParticleSymbol)) - declarationList(); - statementList(); - } - - /* - <argument list> ::= <argument> | <argument> , <argument list> - */ - void Parser::argumentList() - { - argument(); - while(accept(Token::CommaSymbol)) - argument(); - } - - /* - <argument> ::= integer identifier | decimal identifier | particle identifier - */ - void Parser::argument() - { - generator->ScopeVariableType(token.Symbol); - if(!accept(Token::IntegerSymbol)) - if(!accept(Token::DecimalSymbol)) - if(!accept(Token::ParticleSymbol)) - throw ParserExpectException(token, "type name"); - generator->ScopeVariable(token.Source); - expect(Token::Identifier); - } - - /* - <declaration list> ::= <declaration> | <declaration> , <declaration list> - */ - void Parser::declarationList() - { - declaration(); - while(accept(Token::CommaSymbol)) - declaration(); - } - - /* - <declaration> ::= integer <identifier list> | decimal <identifier list> | particle <identifier list> - */ - void Parser::declaration() - { - generator->ScopeVariableType(token.Symbol); - if(!accept(Token::IntegerSymbol)) - if(!accept(Token::DecimalSymbol)) - if(!accept(Token::ParticleSymbol)) - throw ParserExpectException(token, "type name"); - identifierList(); - } - - /* - <identifier list> ::= identifier | identifier , <identifier list> - */ - void Parser::identifierList() - { - generator->ScopeVariable(token.Source); - expect(Token::Identifier); - while(accept(Token::CommaSymbol)) - { - generator->ScopeVariable(token.Source); - expect(Token::Identifier); - } - } - - /* - <statement list> ::= <statement> | <statement> <statement list> - */ - void Parser::statementList() - { - statement(); - while(!look(Token::EndSymbol) && !look(Token::ElseIfSymbol)) - statement(); - } - - /* - <statement> ::= <neighbour statement> | <if statement> | <assignment statement> | <function call> | <particle action> | break | continue - */ - void Parser::statement() - { - //generator->Begin(NonTerminal::Statement); - if(look(Token::NeighbourSymbol)) - { - neighbourStatement(); - } - else if(look(Token::IfSymbol)) - { - ifStatement(); - } - else if(look(Token::CreateSymbol) || look(Token::KillSymbol) || look(Token::GetSymbol) || look(Token::TransformSymbol)) - { - particleAction(); - generator->Discard(); - } - else if(look(Token::BreakSymbol)) - { - expect(Token::BreakSymbol); - generator->Jump(breakLabel); - } - else if(look(Token::ContinueSymbol)) - { - expect(Token::ContinueSymbol); - generator->Jump(continueLabel); - } - else if(look(Token::Identifier)) - { - assigmentStatement(); - } - //generator->End(NonTerminal::Statement); - } - - /* - <particle action> ::= <kill statement> | <create statement> | <transform statement> - */ - void Parser::particleAction() - { - if(look(Token::KillSymbol)) - { - killStatement(); - } - else if(look(Token::CreateSymbol)) - { - createStatement(); - } - else if(look(Token::TransformSymbol)) - { - transformStatement(); - } - - } - - /* - <kill statement> ::= kill ( <expression> ) - */ - void Parser::killStatement() - { - expect(Token::KillSymbol); - expect(Token::LeftBracket); - expression(); - expect(Token::RightBracket); - generator->KillParticle(); - } - - /* - <create statement> ::= create ( <expression>, <expression>, <expression>, <expression> ) - */ - void Parser::createStatement() - { - expect(Token::CreateSymbol); - expect(Token::LeftBracket); - expression(); - expect(Token::CommaSymbol); - expression(); - expect(Token::CommaSymbol); - expression(); - expect(Token::CommaSymbol); - expression(); - expect(Token::RightBracket); - generator->CreateParticle(); - } - - /* - <transform statement> ::= transform ( <expression>, <expression> ) - */ - void Parser::transformStatement() - { - expect(Token::TransformSymbol); - expect(Token::LeftBracket); - expression(); - expect(Token::CommaSymbol); - expression(); - expect(Token::RightBracket); - generator->TransformParticle(); - } - - /* - <get statement> ::= get ( <expression>, <expression> ) - */ - void Parser::getStatement() - { - expect(Token::GetSymbol); - expect(Token::LeftBracket); - expression(); - expect(Token::CommaSymbol); - expression(); - expect(Token::RightBracket); - generator->GetParticle(); - } - - /* - <neighbour statement> ::= neighbour identifier for <expression> do <block> end | neighbour identifier for <expression>, <expression> do <block> end - */ - void Parser::neighbourStatement() - { - std::string neighbourVariable; - std::string loopLabel = generator->UniqueLabel("neighbour"); - std::string xVar = loopLabel+"X"; - std::string xMin = loopLabel+"minX"; - std::string xMax = loopLabel+"maxX"; - std::string yVar = loopLabel+"Y"; - std::string yMax = loopLabel+"maxY"; - breakLabel = loopLabel+"End"; - continueLabel = loopLabel+"Next"; - - expect(Token::NeighbourSymbol); - - generator->PushLocalScope(loopLabel+"Start"); - neighbourVariable = token.Source; - expect(Token::Identifier); - generator->ScopeVariableType(Token::IntegerConstant); - generator->ScopeVariable(neighbourVariable); - generator->ScopeVariable(xVar); - generator->ScopeVariable(yVar); - generator->ScopeVariable(xMin); - generator->ScopeVariable(xMax); - generator->ScopeVariable(yMax); - - generator->LocalEnter(); - - expect(Token::OfSymbol); - - //Initialise position - expression(); - generator->GetPosition(); - generator->Duplicate(); - generator->Increment("-1"); - generator->StoreVariable(yVar); - generator->Increment("1"); - generator->StoreVariable(yMax); - - generator->Duplicate(); - generator->Increment("-1"); - generator->Duplicate(); - generator->StoreVariable(xVar); - generator->StoreVariable(xMin); - generator->Increment("1"); - generator->StoreVariable(xMax); - - //if(accept(Token::CommaSymbol)) - // expression(); - expect(Token::DoSymbol); - - generator->ScopeLabel(loopLabel+"Next"); - - - - - - //Check X - generator->LoadVariable(xVar); - generator->LoadVariable(xMax); - //generator->Duplicate(); //Duplicate xvar so it can be used for incrementing - - generator->JumpLessEqual(loopLabel+"Begin"); - //if(xVar > xMax) { - - //Reset X, increment Y - generator->LoadVariable(xMin); - generator->StoreVariable(xVar); - - generator->LoadVariable(yVar); - generator->Increment("1"); - generator->Duplicate(); - generator->StoreVariable(yVar); - - - //Check Y - generator->LoadVariable(yMax); - generator->JumpGreater(loopLabel+"End"); - - //} - - //Start of loop - generator->ScopeLabel(loopLabel+"Begin"); - - generator->LoadVariable(xVar); - generator->LoadVariable(yVar); - generator->GetParticle(); - generator->StoreVariable(neighbourVariable); - - block(); - - //Increment X - generator->LoadVariable(xVar); - generator->Increment("1"); - generator->StoreVariable(xVar); - - //Next element - generator->Jump(loopLabel+"Next"); - - generator->ScopeLabel(loopLabel+"End"); - generator->Return(); - generator->PopScope(); - expect(Token::EndSymbol); - } - - /* - <if statement> ::= if <condition> then <block> end - */ - void Parser::ifStatement() - { - std::string label = generator->UniqueLabel("if"); - int blockNum = 0; - expect(Token::IfSymbol); - condition(label+format::NumberToString<int>(blockNum)); - expect(Token::ThenSymbol); - block(); - while(accept(Token::ElseIfSymbol)) - { - generator->ScopeLabel(label+format::NumberToString<int>(blockNum++)); - condition(label+format::NumberToString<int>(blockNum)); - expect(Token::ThenSymbol); - block(); - } - if(accept(Token::ElseSymbol)) - { - generator->ScopeLabel(label+format::NumberToString<int>(blockNum++)); - block(); - } - else - { - generator->ScopeLabel(label+format::NumberToString<int>(blockNum++)); - } - expect(Token::EndSymbol); - //generator->End(NonTerminal::IfStatement); - } - - /* - <condition> ::= <expression> <conditional operator> <expression> - */ - void Parser::condition(std::string jumpLabel) - { - expression(); - - Token token = forward(); - - expression(); - - if(token.Symbol == Token::GreaterSymbol) - { - generator->JumpLessEqual(jumpLabel); - } - else if(token.Symbol == Token::GreaterEqualSymbol) - { - generator->JumpLess(jumpLabel); - } - else if(token.Symbol == Token::EqualSymbol) - { - generator->JumpNotEqual(jumpLabel); - } - else if(token.Symbol == Token::NotEqualSymbol) - { - generator->JumpEqual(jumpLabel); - } - else if(token.Symbol == Token::LessSymbol) - { - generator->JumpGreaterEqual(jumpLabel); - } - else if(token.Symbol == Token::LessEqualSymbol) - { - generator->JumpGreater(jumpLabel); - } - else - throw ParserExpectException(token, "conditional operator"); - } - - /* - <assigment statement> ::= identifier = <expression> | identifier.property = <expression> - */ - void Parser::assigmentStatement() - { - std::string variable = token.Source; - expect(Token::Identifier); - if(accept(Token::AssignSymbol)) - { - expression(); - generator->StoreVariable(variable); - } - else if(accept(Token::DotSymbol)) - { - std::string property = token.Source; - expect(Token::Identifier); - expect(Token::AssignSymbol); - expression(); - generator->LoadVariable(variable); - generator->StoreProperty(property); - } - } - - /* - <expression list> ::= <expression> | <expression> , <expression list> - */ - void Parser::expressionList() - { - //generator->Begin(NonTerminal::ExpressionList); - expression(); - while(accept(Token::CommaSymbol)) - expression(); - //generator->End(NonTerminal::ExpressionList); - } - - /* - <expression> ::= <term> | <expression> + <term> | <expression> - <term> - */ - void Parser::expression() - { - term(); - int as = token.Symbol; - while(accept(Token::PlusSymbol) || accept(Token::MinusSymbol)) - { - term(); - if(as == Token::PlusSymbol) - generator->Add(); - else if(as == Token::MinusSymbol) - generator->Subtract(); - } - //generator->End(NonTerminal::Expression); - } - - /* - <term> ::= <factor> | <term> * <factor> | <term> / <factor> - */ - void Parser::term() - { - //generator->Begin(NonTerminal::Term); - factor(); - int md = token.Symbol; - while(accept(Token::MultiplySymbol) || accept(Token::DivideSymbol)) - { - factor(); - if(md == Token::MultiplySymbol) - generator->Multiply(); - else if(md == Token::DivideSymbol) - generator->Divide(); - } - //generator->End(NonTerminal::Term); - } - - /* - <factor> ::= <variable value> | - <variable value> | numberConstant | - numberConstant | ( <expression> ) | - ( <expression> ) - */ - void Parser::factor() - { - bool doNegate = false; - std::string factor = token.Source; - if(accept(Token::MinusSymbol)) - { - factor = token.Source; - doNegate = true; - } - if(accept(Token::IntegerConstant) || accept(Token::DecimalConstant)) - { - if(doNegate) - { - doNegate = false; - generator->Constant("-" + factor); - } - else - generator->Constant(factor); - } - else if(accept(Token::LeftBracket)) - { - expression(); - expect(Token::RightBracket); - } - else - { - variableValue(); - } - if(doNegate) - generator->Negate(); - } - - /* - <variable value> ::= <function call> | identifier | identifier.property | rtmacro | <particle action> - */ - void Parser::variableValue() - { - std::string variable = token.Source; - if(accept(Token::Identifier)) - { - if(look(Token::LeftBracket)) - { - back(); - functionCall(); - } - else - { - if(accept(Token::DotSymbol)) - { - std::string property = token.Source; - expect(Token::Identifier); - generator->LoadVariable(variable); - generator->LoadProperty(property); - } - else - { - generator->LoadVariable(variable); - } - } - } - else if(accept(Token::RTMacro)) - { - generator->RTConstant(variable); - } - else - { - particleAction(); - } - } - - bool Parser::accept(int symbol) - { - if(symbol == token.Symbol) - { - lastToken = token; - if(previousTokens.size()) - { - token = previousTokens.top(); - previousTokens.pop(); - } - else - token = scanner->NextToken(); - //std::cout << "Symbol " << Token::SymbolNames[symbol] << " " << lastToken.Source << std::endl; - return true; - } - //std::cout << "Bad Symbol " << Token::SymbolNames[symbol] << " " << token.Source << " (" << token.GetName() << ")" << std::endl; - return false; - } - - - bool Parser::look(int symbol) - { - if(symbol == token.Symbol) - return true; - return false; - } - - void Parser::back() - { - previousTokens.push(token); - token = lastToken; - } - - Token Parser::forward() - { - lastToken = token; - if(previousTokens.size()) - { - token = previousTokens.top(); - previousTokens.pop(); - } - else - token = scanner->NextToken(); - return lastToken; - } - - void Parser::expect(int symbol) - { - if(!accept(symbol)) - throw ParserExpectException(token, symbol); - } - } -} diff --git a/src/pim/Parser.h b/src/pim/Parser.h deleted file mode 100644 index 19a2835..0000000 --- a/src/pim/Parser.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include <string> -#include <cstring> -#include <sstream> -#include "Scanner.h" -#include "Generator.h" -#include "Token.h" -namespace pim -{ - namespace compiler - { - class ParserExpectException: public std::exception - { - char * error; - public: - ParserExpectException(Token token, int expectingSymbol) { - error = strdup(std::string("Expecting " + Token::SymbolNames[expectingSymbol] + " got " + token.Source).c_str()); - } - ParserExpectException(Token token, std::string expectingString) { - error = strdup(std::string("Expecting " + expectingString + " got " + token.Source).c_str()); - } - const char * what() const throw() - { - return error; - } - ~ParserExpectException() throw() {}; - }; - class Parser - { - std::stringstream & source; - Generator * generator; - Scanner * scanner; - Token token; - Token lastToken; - std::string breakLabel; - std::string continueLabel; - std::stack<Token> previousTokens; - - void program(); - void functionList(); - void function(); - void functionCall(); - void block(); - void argumentList(); - void argument(); - void declarationList(); - void declaration(); - void identifierList(); - void statementList(); - void statement(); - void neighbourStatement(); - void ifStatement(); - void condition(std::string jumpLabel); - void assigmentStatement(); - void particleAction(); - void killStatement(); - void getStatement(); - void createStatement(); - void transformStatement(); - void expressionList(); - - void expression(); - void term(); - void factor(); - void variableValue(); - - Token forward(); - bool accept(int symbol); - bool look(int symbol); - void back(); - void expect(int symbol); - public: - Parser(std::stringstream & source_); - - std::vector<unsigned char> Compile(); - }; - } -} diff --git a/src/pim/Scanner.cpp b/src/pim/Scanner.cpp deleted file mode 100644 index 4ceb942..0000000 --- a/src/pim/Scanner.cpp +++ /dev/null @@ -1,199 +0,0 @@ -//Lexical analyser -#include <algorithm> -#include <cctype> -#include "Scanner.h" - -namespace pim -{ - namespace compiler - { - Scanner::Scanner(std::stringstream & source_) : - source(source_) - { - nextCharacter(); - } - - Token Scanner::NextToken() - { - //Read whitespace, newlines and comments - while( - cChar == ' ' || cChar == '\t' || - cChar == '\r' || cChar == '\n' || - cChar == '/') - { - if(cChar == '/') - { - nextCharacter(); - if(cChar == '/') - { - while(cChar != '\n' && cChar != '\r') - nextCharacter(); - } - else - return Token(Token::DivideSymbol, "/", cLine); - } - - if(cChar == '\r') - { - nextCharacter(); - if(cChar == '\n') - cLine++; - else - continue; - } - else if(cChar == '\n') - cLine++; - - nextCharacter(); - } - - if(std::isalpha(cChar)) //Read alphanumeric symbols - { - cToken.clear(); - while(std::isalpha(cChar) || std::isdigit(cChar)) - { - cToken.push_back(cChar); - nextCharacter(); - } - - std::transform(cToken.begin(), cToken.end(), cToken.begin(), ::tolower); - - for(int i = 0; i < Token::SymbolNumber; i++) - if(Token::SymbolNames[i] == cToken) - return Token(i, cToken, cLine); - return Token(Token::Identifier, cToken, cLine); - } - else if(std::isdigit(cChar)) //Read numeric constants - { - bool decimal = false; - cToken.clear(); - while(std::isdigit(cChar)) - { - cToken.push_back(cChar); - nextCharacter(); - } - if(cChar == '.') - { - decimal = true; - cToken.push_back(cChar); - nextCharacter(); - while(std::isdigit(cChar)) - { - cToken.push_back(cChar); - nextCharacter(); - } - } - if(decimal) - return Token(Token::DecimalConstant, cToken, cLine); - return Token(Token::IntegerConstant, cToken, cLine); - } - else if(cChar == '[') - { - cToken.clear(); - nextCharacter(); - while(std::isalpha(cChar) || std::isdigit(cChar) || cChar == '_' || cChar == '-') - { - cToken.push_back(cChar); - nextCharacter(); - } - nextCharacter(); - - std::transform(cToken.begin(), cToken.end(), cToken.begin(), ::toupper); - - return Token(Token::RTMacro, cToken, cLine); - } - else if(cChar == '=') - { - nextCharacter(); - if(cChar == '=') - { - nextCharacter(); - return Token(Token::EqualSymbol, "==", cLine); - } - return Token(Token::AssignSymbol, "=", cLine); - } - else if(cChar == '!') - { - nextCharacter(); - if(cChar == '=') - return Token(Token::NotEqualSymbol, "==", cLine); - } - else if(cChar == '(') - { - nextCharacter(); - return Token(Token::LeftBracket, "(", cLine); - } - else if(cChar == ')') - { - nextCharacter(); - return Token(Token::RightBracket, ")", cLine); - } - else if(cChar == '/') - { - nextCharacter(); - return Token(Token::DivideSymbol, "/", cLine); - } - else if(cChar == '*') - { - nextCharacter(); - return Token(Token::MultiplySymbol, "*", cLine); - } - else if(cChar == '+') - { - nextCharacter(); - return Token(Token::PlusSymbol, "+", cLine); - } - else if(cChar == '-') - { - nextCharacter(); - return Token(Token::MinusSymbol, "-", cLine); - } - else if(cChar == '%') - { - nextCharacter(); - return Token(Token::ModuloSymbol, "%", cLine); - } - else if(cChar == '<') - { - nextCharacter(); - if(cChar == '=') - { - return Token(Token::LessEqualSymbol, "<=", cLine); - } - return Token(Token::LessSymbol, "<", cLine); - } - else if(cChar == '>') - { - nextCharacter(); - if(cChar == '=') - { - return Token(Token::GreaterEqualSymbol, ">=", cLine); - } - return Token(Token::GreaterSymbol, ">", cLine); - } - else if(cChar == ',') - { - nextCharacter(); - return Token(Token::CommaSymbol, ",", cLine); - } - else if(cChar == '.') - { - nextCharacter(); - return Token(Token::DotSymbol, ".", cLine); - } - else - { - nextCharacter(); - return Token(Token::InvalidSymbol, std::string(1, cChar), cLine); - } - } - - void Scanner::nextCharacter() - { - if(source.good()) - cChar = source.get(); - else - cChar = 0; - } - } -} diff --git a/src/pim/Scanner.h b/src/pim/Scanner.h deleted file mode 100644 index 70e02ac..0000000 --- a/src/pim/Scanner.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <string> -#include <sstream> -#include "Token.h" -namespace pim -{ - namespace compiler - { - class Scanner - { - char cChar; - int cLine; - std::string cToken; - std::stringstream & source; - void nextCharacter(); - public: - Scanner(std::stringstream & source_); - Token NextToken(); - }; - } -} diff --git a/src/pim/Token.cpp b/src/pim/Token.cpp deleted file mode 100644 index 62931ac..0000000 --- a/src/pim/Token.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "Token.h" - -namespace pim -{ - namespace compiler - { - std::string Token::SymbolNames[] = { - "=", - "function", - "(", - ")", - "/", - "*", - "+", - "-", - "%", - "INTEGER", - "DECIMAL", - "PARTICLE", - "integer", - "decimal", - "particle", - "is", - "<", - "<=", - ">", - ">=", - "==", - "!=", - "neighbour", - "do", - "of", - "break", - "continue", - "if", - "else", - "elseif", - "then", - "end", - "kill", - "create", - "transform", - "get", - "RUNTIMEMACRO", - "IDENTIFIER", - ",", - ".", - "INVALID SYMBOL" - }; - } -} diff --git a/src/pim/Token.h b/src/pim/Token.h deleted file mode 100644 index 95d3f08..0000000 --- a/src/pim/Token.h +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include <string> -namespace pim -{ - namespace compiler - { - class Token - { - public: - static std::string SymbolNames[]; - - enum - { - AssignSymbol = 0, - FunctionSymbol, - - LeftBracket, - RightBracket, - DivideSymbol, - MultiplySymbol, - PlusSymbol, - MinusSymbol, - ModuloSymbol, - - IntegerConstant, - DecimalConstant, - ParticleConstant, - - IntegerSymbol, - DecimalSymbol, - ParticleSymbol, - - IsSymbol, - LessSymbol, - LessEqualSymbol, - GreaterSymbol, - GreaterEqualSymbol, - NotEqualSymbol, - EqualSymbol, - - NeighbourSymbol, - DoSymbol, - OfSymbol, - BreakSymbol, - ContinueSymbol, - IfSymbol, - ElseSymbol, - ElseIfSymbol, - ThenSymbol, - EndSymbol, - - KillSymbol, - CreateSymbol, - TransformSymbol, - GetSymbol, - - RTMacro, - Identifier, - - CommaSymbol, - DotSymbol, - - InvalidSymbol, - - SymbolNumber - }; - int Symbol; - int LineNumber; - std::string Source; - - Token(int symbol = InvalidSymbol, std::string source = "HERP DERP", int lineNumber = 0) : - Symbol(symbol), - Source(source), - LineNumber(lineNumber) {} - - std::string GetName() - { - return SymbolNames[Symbol]; - } - }; - } -} diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index 76c0830..60ca1f7 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -2216,7 +2216,7 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny) part_change_type(i, x, y, PT_ELEC); parts[i].ctype = 0; } - else if ((r&0xFF) == PT_H2 && pv[y/CELL][x/CELL] < 45.0f) + else if ((r&0xFF) == PT_H2 && pv[y/CELL][x/CELL] < 45.0f && parts[i].temp < 3000) { part_change_type(i, x, y, PT_PROT); parts[i].ctype = 0; diff --git a/src/simulation/elements/VIRS.cpp b/src/simulation/elements/VIRS.cpp index b30eecf..92ef220 100644 --- a/src/simulation/elements/VIRS.cpp +++ b/src/simulation/elements/VIRS.cpp @@ -153,6 +153,7 @@ int Element_VIRS::update(UPDATE_FUNC_ARGS) //#TPT-Directive ElementHeader Element_VIRS static int graphics(GRAPHICS_FUNC_ARGS) int Element_VIRS::graphics(GRAPHICS_FUNC_ARGS) { + *pixel_mode |= PMODE_BLUR; *pixel_mode |= NO_DECO; return 1; } diff --git a/src/simulation/elements/VRSG.cpp b/src/simulation/elements/VRSG.cpp index e787bfe..76fba44 100644 --- a/src/simulation/elements/VRSG.cpp +++ b/src/simulation/elements/VRSG.cpp @@ -43,7 +43,21 @@ Element_VRSG::Element_VRSG() HighTemperatureTransition = NT; Update = &Element_VIRS::update; - Graphics = &Element_VIRS::graphics; + Graphics = &Element_VRSG::graphics; +} + + +//#TPT-Directive ElementHeader Element_VRSG static int graphics(GRAPHICS_FUNC_ARGS) +int Element_VRSG::graphics(GRAPHICS_FUNC_ARGS) +{ + *pixel_mode &= ~PMODE; + *pixel_mode |= FIRE_BLEND; + *firer = *colr/2; + *fireg = *colg/2; + *fireb = *colb/2; + *firea = 125; + *pixel_mode |= NO_DECO; + return 1; } Element_VRSG::~Element_VRSG() {} diff --git a/src/simulation/elements/VRSS.cpp b/src/simulation/elements/VRSS.cpp index 808fc93..3bfb529 100644 --- a/src/simulation/elements/VRSS.cpp +++ b/src/simulation/elements/VRSS.cpp @@ -43,7 +43,14 @@ Element_VRSS::Element_VRSS() HighTemperatureTransition = PT_VIRS; Update = &Element_VIRS::update; - Graphics = &Element_VIRS::graphics; + Graphics = &Element_VRSS::graphics; +} + +//#TPT-Directive ElementHeader Element_VRSS static int graphics(GRAPHICS_FUNC_ARGS) +int Element_VRSS::graphics(GRAPHICS_FUNC_ARGS) +{ + *pixel_mode |= NO_DECO; + return 1; } Element_VRSS::~Element_VRSS() {} diff --git a/src/tests/PowderInteractionMachine.cpp b/src/tests/PowderInteractionMachine.cpp deleted file mode 100644 index 329cfd7..0000000 --- a/src/tests/PowderInteractionMachine.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef TEST - -#include <iostream> -#include <fstream> -#include <sstream> -#include "pim/Parser.h" - -int main(int argc, char * argv[]) -{ - std::ifstream file("test.p"); - - std::stringstream buffer; - - buffer << file.rdbuf(); - file.close(); - - pim::compiler::Parser * parser = new pim::compiler::Parser(buffer); - - parser->Compile(); -} -#endif diff --git a/src/tests/VirtualMachineTest.cpp b/src/tests/VirtualMachineTest.cpp deleted file mode 100644 index 1f8a52d..0000000 --- a/src/tests/VirtualMachineTest.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef TEST - -#include <iostream> -#include "virtualmachine/VirtualMachine.h" - -int main(int argc, char * argv[]) -{ - vm::VirtualMachine * vm = new vm::VirtualMachine(2); - vm->LoadProgram("test.qvm"); - while(true) - { - vm->Call(0/*, 0, 88, 12*/); - std::cout << "Return value: " << vm->Pop<vm::uint4_t>() << std::endl; - } -} -#endif diff --git a/src/tests/test.qvm b/src/tests/test.qvm Binary files differdeleted file mode 100644 index 22b99b2..0000000 --- a/src/tests/test.qvm +++ /dev/null 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; - }; - }; - -} |
