Remove old unfinished virtual machine and Lua bindings for it

This commit is contained in:
Simon Robertshaw 2013-10-20 15:33:06 +01:00
parent eea006ad6f
commit e8c53dc3e8
28 changed files with 0 additions and 5238 deletions

View File

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

View File

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

View File

@ -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()
{
}
}
}

View File

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

View File

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

View File

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

View File

@ -1,12 +0,0 @@
namespace pim
{
struct Opcode
{
enum
{
#define OPDEF(name) name,
#include "Opcodes.inl"
#undef OPDEF
};
};
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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