Remove old unfinished virtual machine and Lua bindings for it
This commit is contained in:
parent
eea006ad6f
commit
e8c53dc3e8
@ -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();
|
||||
|
||||
@ -1873,49 +1868,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 +2190,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 +2294,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
|
||||
|
@ -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 :(
|
||||
@ -115,9 +111,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 +125,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);
|
||||
|
@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace pim
|
||||
{
|
||||
struct Opcode
|
||||
{
|
||||
enum
|
||||
{
|
||||
#define OPDEF(name) name,
|
||||
#include "Opcodes.inl"
|
||||
#undef OPDEF
|
||||
};
|
||||
};
|
||||
}
|
@ -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)
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
};
|
||||
}
|
||||
}
|
@ -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"
|
||||
};
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -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
|
@ -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
|
Binary file not shown.
@ -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() {};
|
||||
};
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
@ -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 */
|
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#include "tpt_syscalls.h"
|
||||
|
||||
int update_TEST(int i, int x, int y, int nt, int ss)
|
||||
{
|
||||
int k, j, index;
|
||||
|
||||
for(k=-1; k<2; k++)
|
||||
for(j=-1; j<2; j++)
|
||||
{
|
||||
index = pmapData(x+k, y+j);
|
||||
if ((index&0xFF) == 2)
|
||||
killPart(index>>8);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
code
|
||||
|
||||
equ sin -1
|
||||
equ cos -2
|
||||
equ atan2 -3
|
||||
equ sqrt -4
|
||||
equ floor -5
|
||||
equ ceil -6
|
||||
|
||||
equ error -7
|
||||
equ print -8
|
||||
equ partCreate -9
|
||||
equ partChangeType -10
|
||||
equ pmapData -11
|
||||
equ deletePart -12
|
||||
equ killPart -13
|
@ -1,20 +0,0 @@
|
||||
#ifndef TPT_SYSCALLS_H
|
||||
#define TPT_SYSCALLS_H
|
||||
|
||||
float sin(float value);
|
||||
float cos(float value);
|
||||
float atan2(float x, float y);
|
||||
float sqrt(float value);
|
||||
float floor(float value);
|
||||
float ceil(float value);
|
||||
|
||||
void print(char * message);
|
||||
void error(char * message);
|
||||
|
||||
int partCreate(int i, int x, int y, int type);
|
||||
void partChangeType(int i, int x, int y, int type);
|
||||
int pmapData(int x, int y);
|
||||
void deletePart(int x, int y, int flags);
|
||||
void killPart(int i);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user