mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-25 17:29:19 +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[] = {
|
static const instr_info_t sheep_ii_table[] = {
|
||||||
{ "sheep",
|
{ "sheep",
|
||||||
(execute_fn)&sheepshaver_cpu::execute_sheep,
|
(execute_pmf)&sheepshaver_cpu::execute_sheep,
|
||||||
NULL,
|
NULL,
|
||||||
D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
|
D_form, 6, 0, CFLOW_JUMP | CFLOW_TRAP
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#ifndef PPC_BLOCKINFO_H
|
#ifndef PPC_BLOCKINFO_H
|
||||||
#define PPC_BLOCKINFO_H
|
#define PPC_BLOCKINFO_H
|
||||||
|
|
||||||
|
#include "nvmemfun.hpp"
|
||||||
#include "basic-blockinfo.hpp"
|
#include "basic-blockinfo.hpp"
|
||||||
|
|
||||||
class powerpc_cpu;
|
class powerpc_cpu;
|
||||||
@ -28,7 +29,7 @@ class powerpc_cpu;
|
|||||||
struct powerpc_block_info
|
struct powerpc_block_info
|
||||||
: public basic_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
|
struct decode_info
|
||||||
{
|
{
|
||||||
|
@ -331,23 +331,23 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache)
|
|||||||
#ifdef PPC_EXECUTE_DUMP_STATE
|
#ifdef PPC_EXECUTE_DUMP_STATE
|
||||||
if (dump_state) {
|
if (dump_state) {
|
||||||
di->opcode = opcode;
|
di->opcode = opcode;
|
||||||
di->execute = &powerpc_cpu::dump_instruction;
|
di->execute = nv_mem_fun(&powerpc_cpu::dump_instruction);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if PPC_FLIGHT_RECORDER
|
#if PPC_FLIGHT_RECORDER
|
||||||
if (is_logging()) {
|
if (is_logging()) {
|
||||||
di->opcode = opcode;
|
di->opcode = opcode;
|
||||||
di->execute = &powerpc_cpu::record_step;
|
di->execute = nv_mem_fun(&powerpc_cpu::record_step);
|
||||||
di++;
|
di++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
di->opcode = opcode;
|
di->opcode = opcode;
|
||||||
di->execute = ii->decode ? (this->*(ii->decode))(opcode) : ii->execute;
|
di->execute = ii->decode ? ii->decode(this, opcode) : ii->execute;
|
||||||
di++;
|
di++;
|
||||||
#ifdef PPC_EXECUTE_DUMP_STATE
|
#ifdef PPC_EXECUTE_DUMP_STATE
|
||||||
if (dump_state) {
|
if (dump_state) {
|
||||||
di->opcode = 0;
|
di->opcode = 0;
|
||||||
di->execute = &powerpc_cpu::fake_dump_registers;
|
di->execute = nv_mem_fun(&powerpc_cpu::fake_dump_registers);
|
||||||
di++;
|
di++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -376,21 +376,21 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache)
|
|||||||
di = bi->di;
|
di = bi->di;
|
||||||
#ifdef PPC_NO_DECODE_CACHE_UNROLL_EXECUTE
|
#ifdef PPC_NO_DECODE_CACHE_UNROLL_EXECUTE
|
||||||
for (int i = 0; i < bi->size; i++)
|
for (int i = 0; i < bi->size; i++)
|
||||||
(this->*(di[i].execute))(di[i].opcode);
|
di[i].execute(this, di[i].opcode);
|
||||||
#else
|
#else
|
||||||
const int r = bi->size % 4;
|
const int r = bi->size % 4;
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 3: (this->*(di->execute))(di->opcode); di++;
|
case 3: di->execute(this, di->opcode); di++;
|
||||||
case 2: (this->*(di->execute))(di->opcode); di++;
|
case 2: di->execute(this, di->opcode); di++;
|
||||||
case 1: (this->*(di->execute))(di->opcode); di++;
|
case 1: di->execute(this, di->opcode); di++;
|
||||||
case 0: break;
|
case 0: break;
|
||||||
}
|
}
|
||||||
const int n = bi->size / 4;
|
const int n = bi->size / 4;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
(this->*(di[0].execute))(di[0].opcode);
|
di[0].execute(this, di[0].opcode);
|
||||||
(this->*(di[1].execute))(di[1].opcode);
|
di[1].execute(this, di[1].opcode);
|
||||||
(this->*(di[2].execute))(di[2].opcode);
|
di[2].execute(this, di[2].opcode);
|
||||||
(this->*(di[3].execute))(di[3].opcode);
|
di[3].execute(this, di[3].opcode);
|
||||||
di += 4;
|
di += 4;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -424,7 +424,7 @@ void powerpc_cpu::execute(uint32 entry, bool enable_cache)
|
|||||||
record_step(opcode);
|
record_step(opcode);
|
||||||
#endif
|
#endif
|
||||||
assert(ii->execute != 0);
|
assert(ii->execute != 0);
|
||||||
(this->*(ii->execute))(opcode);
|
ii->execute(this, opcode);
|
||||||
#ifdef PPC_EXECUTE_DUMP_STATE
|
#ifdef PPC_EXECUTE_DUMP_STATE
|
||||||
if (dump_state)
|
if (dump_state)
|
||||||
dump_registers();
|
dump_registers();
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#define PPC_CPU_H
|
#define PPC_CPU_H
|
||||||
|
|
||||||
#include "basic-cpu.hpp"
|
#include "basic-cpu.hpp"
|
||||||
|
#include "nvmemfun.hpp"
|
||||||
#include "cpu/vm.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"
|
||||||
@ -139,10 +140,12 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Callbacks associated with each instruction
|
// 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
|
// 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
|
// Instruction information structure
|
||||||
struct instr_info_t {
|
struct instr_info_t {
|
||||||
|
Loading…
Reference in New Issue
Block a user