mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 18:49:58 +00:00
added code execution main loop
This commit is contained in:
parent
770eb14d95
commit
d80cb3461c
5 changed files with 207 additions and 6 deletions
|
@ -1,21 +1,186 @@
|
||||||
|
|
||||||
#include "interpreter.hpp"
|
#include "interpreter.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "opcodes.hpp"
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
|
void Interpreter::execute (Type_Code code)
|
||||||
|
{
|
||||||
|
unsigned int segSpec = code>>30;
|
||||||
|
|
||||||
|
switch (segSpec)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
int opcode = code>>24;
|
||||||
|
unsigned int arg0 = code & 0xffffff;
|
||||||
|
|
||||||
|
std::map<int, Opcode1 *>::iterator iter = mSegment0.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment0.end())
|
||||||
|
abortUnknownCode (0, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime, arg0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
int opcode = (code>>24) & 0x3f;
|
||||||
|
unsigned int arg0 = (code>>16) & 0xfff;
|
||||||
|
unsigned int arg1 = code & 0xfff;
|
||||||
|
|
||||||
|
std::map<int, Opcode2 *>::iterator iter = mSegment1.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment1.end())
|
||||||
|
abortUnknownCode (1, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime, arg0, arg1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
int opcode = (code>>20) & 0x3ff;
|
||||||
|
unsigned int arg0 = code & 0xfffff;
|
||||||
|
|
||||||
|
std::map<int, Opcode1 *>::iterator iter = mSegment2.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment2.end())
|
||||||
|
abortUnknownCode (2, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime, arg0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
segSpec = code>>26;
|
||||||
|
|
||||||
|
switch (segSpec)
|
||||||
|
{
|
||||||
|
case 0x30:
|
||||||
|
{
|
||||||
|
int opcode = (code>>16) & 0x3ff;
|
||||||
|
unsigned int arg0 = code & 0xffff;
|
||||||
|
|
||||||
|
std::map<int, Opcode1 *>::iterator iter = mSegment3.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment3.end())
|
||||||
|
abortUnknownCode (3, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime, arg0);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x31:
|
||||||
|
{
|
||||||
|
int opcode = (code>>16) & 0x3ff;
|
||||||
|
unsigned int arg0 = (code>>8) & 0xff;
|
||||||
|
unsigned int arg1 = code & 0xff;
|
||||||
|
|
||||||
|
std::map<int, Opcode2 *>::iterator iter = mSegment4.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment4.end())
|
||||||
|
abortUnknownCode (4, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime, arg0, arg1);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0x32:
|
||||||
|
{
|
||||||
|
int opcode = code & 0x3ffffff;
|
||||||
|
|
||||||
|
std::map<int, Opcode0 *>::iterator iter = mSegment5.find (opcode);
|
||||||
|
|
||||||
|
if (iter==mSegment5.end())
|
||||||
|
abortUnknownCode (5, opcode);
|
||||||
|
|
||||||
|
iter->second->execute (mRuntime);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abortUnknownSegment (code);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Interpreter::abortUnknownCode (int segment, int opcode)
|
||||||
|
{
|
||||||
|
std::ostringstream error;
|
||||||
|
|
||||||
|
error << "unknown opcode " << opcode << " in segment " << segment;
|
||||||
|
|
||||||
|
throw std::runtime_error (error.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Interpreter::abortUnknownSegment (Type_Code code)
|
||||||
|
{
|
||||||
|
std::ostringstream error;
|
||||||
|
|
||||||
|
error << "opcode outside of the allocated segment range: " << code;
|
||||||
|
|
||||||
|
throw std::runtime_error (error.str());
|
||||||
|
}
|
||||||
|
|
||||||
Interpreter::Interpreter (Context& context)
|
Interpreter::Interpreter (Context& context)
|
||||||
: mRuntime (context)
|
: mRuntime (context)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
Interpreter::~Interpreter()
|
Interpreter::~Interpreter()
|
||||||
{
|
{
|
||||||
|
for (std::map<int, Opcode1 *>::iterator iter (mSegment0.begin());
|
||||||
|
iter!=mSegment0.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
for (std::map<int, Opcode2 *>::iterator iter (mSegment1.begin());
|
||||||
|
iter!=mSegment1.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
for (std::map<int, Opcode1 *>::iterator iter (mSegment2.begin());
|
||||||
|
iter!=mSegment2.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
for (std::map<int, Opcode1 *>::iterator iter (mSegment3.begin());
|
||||||
|
iter!=mSegment3.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
for (std::map<int, Opcode2 *>::iterator iter (mSegment4.begin());
|
||||||
|
iter!=mSegment4.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
|
||||||
|
for (std::map<int, Opcode0 *>::iterator iter (mSegment5.begin());
|
||||||
|
iter!=mSegment5.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::run (const Type_Code *code, int codeSize)
|
void Interpreter::run (const Type_Code *code, int codeSize)
|
||||||
{
|
{
|
||||||
|
assert (codeSize>=4);
|
||||||
|
|
||||||
mRuntime.configure (code, codeSize);
|
mRuntime.configure (code, codeSize);
|
||||||
|
|
||||||
|
int opcodes = static_cast<int> (code[0]);
|
||||||
|
|
||||||
|
const Type_Code *codeBlock = code + 4;
|
||||||
|
|
||||||
|
while (mRuntime.getPC()>=0 && mRuntime.getPC()<opcodes)
|
||||||
|
{
|
||||||
|
Type_Code code = codeBlock[mRuntime.getPC()];
|
||||||
|
mRuntime.setPC (mRuntime.getPC()+1);
|
||||||
|
execute (code);
|
||||||
|
}
|
||||||
|
|
||||||
mRuntime.clear();
|
mRuntime.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,37 @@
|
||||||
#ifndef INTERPRETER_INTERPRETER_H_INCLUDED
|
#ifndef INTERPRETER_INTERPRETER_H_INCLUDED
|
||||||
#define INTERPRETER_INTERPRETER_H_INCLUDED
|
#define INTERPRETER_INTERPRETER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "runtime.hpp"
|
#include "runtime.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
|
class Opcode0;
|
||||||
|
class Opcode1;
|
||||||
|
class Opcode2;
|
||||||
|
|
||||||
class Interpreter
|
class Interpreter
|
||||||
{
|
{
|
||||||
Runtime mRuntime;
|
Runtime mRuntime;
|
||||||
|
std::map<int, Opcode1 *> mSegment0;
|
||||||
|
std::map<int, Opcode2 *> mSegment1;
|
||||||
|
std::map<int, Opcode1 *> mSegment2;
|
||||||
|
std::map<int, Opcode1 *> mSegment3;
|
||||||
|
std::map<int, Opcode2 *> mSegment4;
|
||||||
|
std::map<int, Opcode0 *> mSegment5;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Interpreter (const Interpreter&);
|
Interpreter (const Interpreter&);
|
||||||
Interpreter& operator= (const Interpreter&);
|
Interpreter& operator= (const Interpreter&);
|
||||||
|
|
||||||
|
void execute (Type_Code code);
|
||||||
|
|
||||||
|
void abortUnknownCode (int segment, int opcode);
|
||||||
|
|
||||||
|
void abortUnknownSegment (Type_Code code);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Interpreter (Context& context);
|
Interpreter (Context& context);
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Interpreter
|
||||||
|
|
||||||
virtual void execute (Runtime& runtime, unsigned int arg0) = 0;
|
virtual void execute (Runtime& runtime, unsigned int arg0) = 0;
|
||||||
|
|
||||||
virtual ~Opcode0() {}
|
virtual ~Opcode1() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// opcode for 2 arguments
|
/// opcode for 2 arguments
|
||||||
|
@ -32,7 +32,7 @@ namespace Interpreter
|
||||||
|
|
||||||
virtual void execute (Runtime& runtime, unsigned int arg1, unsigned int arg2) = 0;
|
virtual void execute (Runtime& runtime, unsigned int arg1, unsigned int arg2) = 0;
|
||||||
|
|
||||||
virtual ~Opcode0() {}
|
virtual ~Opcode2() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,20 @@
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
Runtime::Runtime (Context& context) : mContext (context), mCode (0) {}
|
Runtime::Runtime (Context& context) : mContext (context), mCode (0), mPC (0) {}
|
||||||
|
|
||||||
|
int Runtime::getPC() const
|
||||||
|
{
|
||||||
|
return mPC;
|
||||||
|
}
|
||||||
|
|
||||||
void Runtime::configure (const Interpreter::Type_Code *code, int codeSize)
|
void Runtime::configure (const Interpreter::Type_Code *code, int codeSize)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
mCode = code;
|
mCode = code;
|
||||||
mCodeSize = codeSize;
|
mCodeSize = codeSize;
|
||||||
|
mPC = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runtime::clear()
|
void Runtime::clear()
|
||||||
|
@ -18,5 +24,10 @@ namespace Interpreter
|
||||||
mCode = 0;
|
mCode = 0;
|
||||||
mCodeSize = 0;
|
mCodeSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Runtime::setPC (int PC)
|
||||||
|
{
|
||||||
|
mPC = PC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,18 +12,25 @@ namespace Interpreter
|
||||||
class Runtime
|
class Runtime
|
||||||
{
|
{
|
||||||
Context& mContext;
|
Context& mContext;
|
||||||
const Interpreter::Type_Code *mCode;
|
const Type_Code *mCode;
|
||||||
int mCodeSize;
|
int mCodeSize;
|
||||||
|
int mPC;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Runtime (Context& context);
|
Runtime (Context& context);
|
||||||
|
|
||||||
|
int getPC() const;
|
||||||
|
///< return program counter.
|
||||||
|
|
||||||
void configure (const Interpreter::Type_Code *code, int codeSize);
|
void configure (const Interpreter::Type_Code *code, int codeSize);
|
||||||
///< \a context and \a code must exist as least until either configure, clear or
|
///< \a context and \a code must exist as least until either configure, clear or
|
||||||
/// the destructor is called. \a codeSize is given in 32-bit words.
|
/// the destructor is called. \a codeSize is given in 32-bit words.
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void setPC (int PC);
|
||||||
|
///< set program counter.
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue