diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp index d225e7d2..e1c291be 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -242,97 +242,13 @@ void powerpc_cpu::dump_registers() fflush(stderr); } +struct execute_nothing { + static inline void execute(powerpc_cpu *) { } +}; + void powerpc_cpu::execute() { -#ifdef PPC_NO_DECODE_CACHE - 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 + do_execute(); } void powerpc_cpu::init_decode_cache() diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp index b0e30c11..f658992b 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.hpp @@ -22,6 +22,7 @@ #define PPC_CPU_H #include "basic-cpu.hpp" +#include "cpu/vm.hpp" #include "cpu/block-cache.hpp" #include "cpu/ppc/ppc-config.hpp" #include "cpu/ppc/ppc-bitfields.hpp" @@ -214,6 +215,8 @@ public: void dump_registers(); // Start emulation loop + template< class prologue, class epilogue > + void do_execute(); void execute(); // Set VALUE to register ID @@ -321,6 +324,95 @@ private: void execute_fp_round(uint32 opcode); void execute_icbi(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 */