make do_execute() a template so that execution loop prologues/epilogues

can be performed in derived engines
This commit is contained in:
gbeauche 2003-09-28 21:22:09 +00:00
parent 2f13888ea8
commit 4e5e13d92d
2 changed files with 97 additions and 89 deletions

View File

@ -242,97 +242,13 @@ void powerpc_cpu::dump_registers()
fflush(stderr); fflush(stderr);
} }
struct execute_nothing {
static inline void execute(powerpc_cpu *) { }
};
void powerpc_cpu::execute() void powerpc_cpu::execute()
{ {
#ifdef PPC_NO_DECODE_CACHE do_execute<execute_nothing, execute_nothing>();
for (;;) {
uint32 opcode = vm_read_memory_4(pc());
const instr_info_t *ii = decode(opcode);
// D(bug("[%08x]-> %08x: %s\n", pc(), opcode, ii->name));
#ifdef PPC_EXECUTE_DUMP_STATE
fprintf(stderr, "[%08x]-> %08x\n", pc(), opcode);
#endif
if (logging)
record_step(opcode);
assert(ii->execute != NULL);
(this->*(ii->execute))(opcode);
#ifdef PPC_EXECUTE_DUMP_STATE
dump_registers();
#endif
}
#else
for (;;) {
block_info *bi = block_cache.new_blockinfo();
bi->init(pc());
// Predecode a new block
block_info::decode_info *di = bi->di = decode_cache_p;
const instr_info_t *ii;
uint32 dpc = pc() - 4;
do {
uint32 opcode = vm_read_memory_4(dpc += 4);
ii = decode(opcode);
di->opcode = opcode;
di->execute = ii->execute;
if (++di >= decode_cache_end_p) {
// Invalidate cache and move current code to start
invalidate_cache();
const int blocklen = di - bi->di;
memmove(decode_cache_p, bi->di, blocklen * sizeof(*di));
bi->di = decode_cache_p;
di = bi->di + blocklen;
}
} while ((ii->cflow & CFLOW_END_BLOCK) == 0);
#ifdef PPC_LAZY_PC_UPDATE
bi->end_pc = dpc;
#endif
bi->size = di - bi->di;
// bi->count = 10;
block_cache.add_to_cl_list(bi);
block_cache.add_to_active_list(bi);
decode_cache_p += bi->size;
// Execute all cached blocks
for (;;) {
#ifdef PPC_LAZY_PC_UPDATE
pc() = bi->end_pc;
#endif
di = bi->di;
#ifdef PPC_NO_DECODE_CACHE_UNROLL_EXECUTE
for (int i = 0; i < bi->size; i++)
(this->*(di[i].execute))(di[i].opcode);
#else
const int r = bi->size % 4;
switch (r) {
case 3: (this->*(di->execute))(di->opcode); di++;
case 2: (this->*(di->execute))(di->opcode); di++;
case 1: (this->*(di->execute))(di->opcode); di++;
case 0: break;
}
const int n = bi->size / 4;
for (int i = 0; i < n; i++) {
(this->*(di[0].execute))(di[0].opcode);
(this->*(di[1].execute))(di[1].opcode);
(this->*(di[2].execute))(di[2].opcode);
(this->*(di[3].execute))(di[3].opcode);
di += 4;
}
#endif
if (0 && --bi->count <= 0) {
#if ENABLE_MON
printf("Recompile block: %08x (%d insns)\n", bi->pc, bi->size);
uint32 dpc = bi->pc;
for (int i = 0; i < bi->size; i++, dpc += 4)
disass_ppc(stdout, dpc, bi->di[i].opcode);
#endif
bi->count = 0x7fffffff;
}
if ((bi->pc != pc()) && ((bi = block_cache.find(pc())) == NULL))
break;
}
}
#endif
} }
void powerpc_cpu::init_decode_cache() void powerpc_cpu::init_decode_cache()

View File

@ -22,6 +22,7 @@
#define PPC_CPU_H #define PPC_CPU_H
#include "basic-cpu.hpp" #include "basic-cpu.hpp"
#include "cpu/vm.hpp"
#include "cpu/block-cache.hpp" #include "cpu/block-cache.hpp"
#include "cpu/ppc/ppc-config.hpp" #include "cpu/ppc/ppc-config.hpp"
#include "cpu/ppc/ppc-bitfields.hpp" #include "cpu/ppc/ppc-bitfields.hpp"
@ -214,6 +215,8 @@ public:
void dump_registers(); void dump_registers();
// Start emulation loop // Start emulation loop
template< class prologue, class epilogue >
void do_execute();
void execute(); void execute();
// Set VALUE to register ID // Set VALUE to register ID
@ -321,6 +324,95 @@ private:
void execute_fp_round(uint32 opcode); void execute_fp_round(uint32 opcode);
void execute_icbi(uint32 opcode); void execute_icbi(uint32 opcode);
void execute_isync(uint32 opcode); void execute_isync(uint32 opcode);
template< class RA, class RB >
void execute_dcbz(uint32 opcode);
}; };
template< class prologue, class epilogue >
inline void powerpc_cpu::do_execute()
{
#ifdef PPC_NO_DECODE_CACHE
for (;;) {
prologue::execute(this);
uint32 opcode = vm_read_memory_4(pc());
const instr_info_t *ii = decode(opcode);
#ifdef PPC_EXECUTE_DUMP_STATE
fprintf(stderr, "[%08x]-> %08x\n", pc(), opcode);
#endif
if (logging)
record_step(opcode);
assert(ii->execute != NULL);
(this->*(ii->execute))(opcode);
#ifdef PPC_EXECUTE_DUMP_STATE
dump_registers();
#endif
epilogue::execute(this);
}
#else
for (;;) {
block_info *bi = block_cache.new_blockinfo();
bi->init(pc());
// Predecode a new block
block_info::decode_info *di = bi->di = decode_cache_p;
const instr_info_t *ii;
uint32 dpc = pc() - 4;
do {
uint32 opcode = vm_read_memory_4(dpc += 4);
ii = decode(opcode);
di->opcode = opcode;
di->execute = ii->execute;
if (++di >= decode_cache_end_p) {
// Invalidate cache and move current code to start
invalidate_cache();
const int blocklen = di - bi->di;
memmove(decode_cache_p, bi->di, blocklen * sizeof(*di));
bi->di = decode_cache_p;
di = bi->di + blocklen;
}
} while ((ii->cflow & CFLOW_END_BLOCK) == 0);
#ifdef PPC_LAZY_PC_UPDATE
bi->end_pc = dpc;
#endif
bi->size = di - bi->di;
block_cache.add_to_cl_list(bi);
block_cache.add_to_active_list(bi);
decode_cache_p += bi->size;
// Execute all cached blocks
for (;;) {
prologue::execute(this);
#ifdef PPC_LAZY_PC_UPDATE
pc() = bi->end_pc;
#endif
di = bi->di;
#ifdef PPC_NO_DECODE_CACHE_UNROLL_EXECUTE
for (int i = 0; i < bi->size; i++)
(this->*(di[i].execute))(di[i].opcode);
#else
const int r = bi->size % 4;
switch (r) {
case 3: (this->*(di->execute))(di->opcode); di++;
case 2: (this->*(di->execute))(di->opcode); di++;
case 1: (this->*(di->execute))(di->opcode); di++;
case 0: break;
}
const int n = bi->size / 4;
for (int i = 0; i < n; i++) {
(this->*(di[0].execute))(di[0].opcode);
(this->*(di[1].execute))(di[1].opcode);
(this->*(di[2].execute))(di[2].opcode);
(this->*(di[3].execute))(di[3].opcode);
di += 4;
}
#endif
epilogue::execute(this);
if ((bi->pc != pc()) && ((bi = block_cache.find(pc())) == NULL))
break;
}
}
#endif
}
#endif /* PPC_CPU_H */ #endif /* PPC_CPU_H */