I'm not sure about what a caching interpreter is. But it may be a case of JIT (like the one in Xenia) which allows to reduce the overhead of decoding a contiguous set of instructions (usually called a basic block) by decoding them only once then execute them every time the address is hit by the instruction fetcher. Under certain architectures, you need to use a special instruction to flush icache so you can also discard a basic block from the instruction cache this way.
The simplest way is probably something like that:
P.S.: decode_insn returns a vector of decoded insns which represents a basic block (there is no branch-like instruction in the block except for the last instruction)
The simplest way is probably something like that:
Code:
struct insn { void (*interpret_insn)(Context & context); };
...
std::unordered_map< u32, std::vector< insn > > insn_cache;
...
do
{
auto pc = context.pc;
auto bb = insn_cache.find(pc);
if (bb == insn_cache.end())
{
insn_cache[pc] = decode_insn(pc);
}
else
{
for (auto i : bb) i->interpret_insn(context);
}
}
while (context.no_external_event);
...
}
P.S.: decode_insn returns a vector of decoded insns which represents a basic block (there is no branch-like instruction in the block except for the last instruction)