mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-04-30 05:47:57 +03:00
Imported Upstream version 0.26.0
This commit is contained in:
commit
9a2b6c69b6
1398 changed files with 212217 additions and 0 deletions
216
components/interpreter/interpreter.cpp
Normal file
216
components/interpreter/interpreter.cpp
Normal file
|
@ -0,0 +1,216 @@
|
|||
|
||||
#include "interpreter.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "opcodes.hpp"
|
||||
|
||||
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>>8) & 0x3ffff;
|
||||
unsigned int arg0 = code & 0xff;
|
||||
|
||||
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()
|
||||
{}
|
||||
|
||||
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::installSegment0 (int code, Opcode1 *opcode)
|
||||
{
|
||||
mSegment0.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment1 (int code, Opcode2 *opcode)
|
||||
{
|
||||
mSegment1.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment2 (int code, Opcode1 *opcode)
|
||||
{
|
||||
mSegment2.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment3 (int code, Opcode1 *opcode)
|
||||
{
|
||||
mSegment3.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment4 (int code, Opcode2 *opcode)
|
||||
{
|
||||
mSegment4.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::installSegment5 (int code, Opcode0 *opcode)
|
||||
{
|
||||
mSegment5.insert (std::make_pair (code, opcode));
|
||||
}
|
||||
|
||||
void Interpreter::run (const Type_Code *code, int codeSize, Context& context)
|
||||
{
|
||||
assert (codeSize>=4);
|
||||
|
||||
mRuntime.configure (code, codeSize, context);
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue