diff --git a/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp b/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp new file mode 100644 index 00000000..59f8a4e8 --- /dev/null +++ b/SheepShaver/src/kpx_cpu/include/nvmemfun.hpp @@ -0,0 +1,144 @@ +/* + * nvmemfun.hpp - Non-virtual member function wrappers + * + * Kheperix (C) 2003 Gwenole Beauchesne + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef NVMEMFUN_H +#define NVMEMFUN_H + +#include + +#if (defined(__GNUC__) || defined(__ICC)) + +template< class PMF, class PF > +inline PF nv_mem_fun_of(PMF pmf) { + union { PMF pmf; uintptr p[2]; } x; + x.pmf = pmf; +#if defined(__GXX_ABI_VERSION) /* GCC >= 3.0 */ + const int N = 0; +#else + const int N = 1; +#endif + return (PF)x.p[N]; +} + +template< class R, class T > +class nv_mem_fun_t : public std::unary_function { + typedef R (T::*pmf_t)(); + typedef R (*pf_t)(T *); + pf_t pf; +public: + nv_mem_fun_t(pmf_t pmf) : pf(nv_mem_fun_of(pmf)) {} + R operator()(T *p) const { return (*pf)(p); } + operator bool () const { return pf; } +}; + +template< class R, class T > +class const_nv_mem_fun_t : public std::unary_function { + typedef R (T::*pmf_t)(); + typedef R (*pf_t)(T *); + pf_t const pf; +public: + const_nv_mem_fun_t(pmf_t const pmf) : pf(nv_mem_fun_of(pmf)) {} + R operator()(const T *p) const { return (*pf)(p); } + operator bool () const { return pf; } +}; + +template< class R, class T, class A > +class nv_mem_fun1_t : public std::binary_function { + typedef R (T::*pmf_t)(A); + typedef R (*pf_t)(T *, A x); + pf_t pf; +public: + nv_mem_fun1_t(pmf_t pmf) : pf(nv_mem_fun_of(pmf)) {} + R operator()(T *p, A x) const { return (*pf)(p, x); } + operator bool () const { return pf; } +}; + +template< class R, class T, class A > +class const_nv_mem_fun1_t : public std::binary_function { + typedef R (T::*pmf_t)(A); + typedef R (*pf_t)(T *, A x); + pf_t const pf; +public: + const_nv_mem_fun1_t(pmf_t const pmf) : pf(nv_mem_fun_of(pmf)) {} + R operator()(const T *p, A x) const { return (*pf)(p, x); } + operator bool () const { return pf; } +}; + +#else + +template< class R, class T > +class nv_mem_fun_t : public std::unary_function { + R (T::*pf)(); +public: + nv_mem_fun_t(R (T::*pmf)()) : pf(pmf) {} + R operator()(T *p) const { return (p->*pf)(); } + operator bool () const { return pf; } +}; + +template< class R, class T > +class const_nv_mem_fun_t : public std::unary_function { + R (T::*pf)() const; +public: + const_nv_mem_fun_t(R (T::*pmf)() const) : pf(pmf) {} + R operator()(const T *p) const { return (p->*pf)(); } + operator bool () const { return pf; } +}; + +template< class R, class T, class A > +class nv_mem_fun1_t : public std::binary_function { + R (T::*pf)(A); +public: + nv_mem_fun1_t(R (T::*pmf)(A)) : pf(pmf) {} + R operator()(T *p, A x) const { return (p->*pf)(x); } + operator bool () const { return pf; } +}; + +template< class R, class T, class A > +class const_nv_mem_fun1_t : public std::binary_function { + R (T::*pf)(A) const; +public: + const_nv_mem_fun1_t(R (T::*pmf)(A) const) : pf(pmf) {} + R operator()(const T *p, A x) const { return (p->*pf)(x); } + operator bool () const { return pf; } +}; + +#endif + +template< class R, class T > +inline nv_mem_fun_t nv_mem_fun(R (T::*pmf)()) { + return nv_mem_fun_t(pmf); +} + +template< class R, class T > +inline const_nv_mem_fun_t nv_mem_fun(R (T::*pmf)() const) { + return const_nv_mem_fun_t(pmf); +} + +template< class R, class T, class A > +inline nv_mem_fun1_t nv_mem_fun(R (T::*pmf)(A)) { + return nv_mem_fun1_t(pmf); +} + +template< class R, class T, class A > +inline const_nv_mem_fun1_t nv_mem_fun(R (T::*pmf)(A) const) { + return const_nv_mem_fun1_t(pmf); +} + +#endif /* NVMEMFUN_H */ diff --git a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp index eca62ad8..ffe59de7 100644 --- a/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp +++ b/SheepShaver/src/kpx_cpu/sheepshaver_glue.cpp @@ -141,7 +141,7 @@ void sheepshaver_cpu::init_decoder() static const instr_info_t sheep_ii_table[] = { { "sheep", - (execute_fn)&sheepshaver_cpu::execute_sheep, + (execute_pmf)&sheepshaver_cpu::execute_sheep, NULL, D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP } diff --git a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp index 80e28d54..786872d3 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-blockinfo.hpp @@ -21,6 +21,7 @@ #ifndef PPC_BLOCKINFO_H #define PPC_BLOCKINFO_H +#include "nvmemfun.hpp" #include "basic-blockinfo.hpp" class powerpc_cpu; @@ -28,7 +29,7 @@ class powerpc_cpu; struct powerpc_block_info : public basic_block_info { - typedef void (powerpc_cpu::*execute_fn)(uint32 opcode); + typedef nv_mem_fun1_t< void, powerpc_cpu, uint32 > execute_fn; struct decode_info { 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 14b22293..141a60a9 100644 --- a/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp +++ b/SheepShaver/src/kpx_cpu/src/cpu/ppc/ppc-cpu.cpp @@ -331,23 +331,23 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) #ifdef PPC_EXECUTE_DUMP_STATE if (dump_state) { di->opcode = opcode; - di->execute = &powerpc_cpu::dump_instruction; + di->execute = nv_mem_fun(&powerpc_cpu::dump_instruction); } #endif #if PPC_FLIGHT_RECORDER if (is_logging()) { di->opcode = opcode; - di->execute = &powerpc_cpu::record_step; + di->execute = nv_mem_fun(&powerpc_cpu::record_step); di++; } #endif di->opcode = opcode; - di->execute = ii->decode ? (this->*(ii->decode))(opcode) : ii->execute; + di->execute = ii->decode ? ii->decode(this, opcode) : ii->execute; di++; #ifdef PPC_EXECUTE_DUMP_STATE if (dump_state) { di->opcode = 0; - di->execute = &powerpc_cpu::fake_dump_registers; + di->execute = nv_mem_fun(&powerpc_cpu::fake_dump_registers); di++; } #endif @@ -376,21 +376,21 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) 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); + di[i].execute(this, 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 3: di->execute(this, di->opcode); di++; + case 2: di->execute(this, di->opcode); di++; + case 1: di->execute(this, 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[0].execute(this, di[0].opcode); + di[1].execute(this, di[1].opcode); + di[2].execute(this, di[2].opcode); + di[3].execute(this, di[3].opcode); di += 4; } #endif @@ -424,7 +424,7 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache) record_step(opcode); #endif assert(ii->execute != 0); - (this->*(ii->execute))(opcode); + ii->execute(this, opcode); #ifdef PPC_EXECUTE_DUMP_STATE if (dump_state) dump_registers(); 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 848f9776..9178e5d8 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 "nvmemfun.hpp" #include "cpu/vm.hpp" #include "cpu/block-cache.hpp" #include "cpu/ppc/ppc-config.hpp" @@ -139,10 +140,12 @@ protected: }; // Callbacks associated with each instruction - typedef void (powerpc_cpu::*execute_fn)(uint32 opcode); + typedef void (powerpc_cpu::*execute_pmf)(uint32 opcode); + typedef nv_mem_fun1_t< void, powerpc_cpu, uint32 > execute_fn; // Specialzed instruction decoders type - typedef execute_fn (powerpc_cpu::*decode_fn)(uint32 opcode); + typedef execute_fn (powerpc_cpu::*decode_pmf)(uint32 opcode); + typedef nv_mem_fun1_t< execute_fn, powerpc_cpu, uint32 > decode_fn; // Instruction information structure struct instr_info_t {