mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 19:29:18 +00:00
Optimized pointers to non virtual member functions. This reduces space
and overhead since runtime checks are eliminated. Actually, it yields up to 10% performance improvement with specialized decoders.
This commit is contained in:
parent
d956d3c4ca
commit
f0ea192460
144
SheepShaver/src/kpx_cpu/include/nvmemfun.hpp
Normal file
144
SheepShaver/src/kpx_cpu/include/nvmemfun.hpp
Normal file
@ -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 <functional>
|
||||
|
||||
#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<T, R> {
|
||||
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_t, pf_t>(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<T, R> {
|
||||
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_t, pf_t>(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<T, A, R> {
|
||||
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_t, pf_t>(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<T, A, R> {
|
||||
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_t, pf_t>(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<T, R> {
|
||||
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<T, R> {
|
||||
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<T, A, R> {
|
||||
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<T, A, R> {
|
||||
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<R, T> nv_mem_fun(R (T::*pmf)()) {
|
||||
return nv_mem_fun_t<R, T>(pmf);
|
||||
}
|
||||
|
||||
template< class R, class T >
|
||||
inline const_nv_mem_fun_t<R, T> nv_mem_fun(R (T::*pmf)() const) {
|
||||
return const_nv_mem_fun_t<R, T>(pmf);
|
||||
}
|
||||
|
||||
template< class R, class T, class A >
|
||||
inline nv_mem_fun1_t<R, T, A> nv_mem_fun(R (T::*pmf)(A)) {
|
||||
return nv_mem_fun1_t<R, T, A>(pmf);
|
||||
}
|
||||
|
||||
template< class R, class T, class A >
|
||||
inline const_nv_mem_fun1_t<R, T, A> nv_mem_fun(R (T::*pmf)(A) const) {
|
||||
return const_nv_mem_fun1_t<R, T, A>(pmf);
|
||||
}
|
||||
|
||||
#endif /* NVMEMFUN_H */
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user