rpcs3/rpcs3/Emu/CPU/CPUDecoder.h
DH b263c3ebaf - Renamed ARM9 to ARMv7.
- Improved ELF32 loader.
2013-11-05 21:22:58 +02:00

879 lines
20 KiB
C++

#pragma once
#include "CPUInstrTable.h"
#pragma warning( disable : 4800 )
class CPUDecoder
{
public:
virtual u8 DecodeMemory(const u64 address)=0;
};
template<typename TO>
class InstrCaller
{
public:
virtual ~InstrCaller()
{
}
virtual void operator ()(TO* op, u32 code) const = 0;
virtual u32 operator [](u32) const
{
return 0;
}
};
template<typename TO>
class InstrBinder_0 : public InstrCaller<TO>
{
typedef void (TO::*func_t)();
func_t m_func;
public:
InstrBinder_0(func_t func)
: InstrCaller()
, m_func(func)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)();
}
};
template<typename TO, typename T1>
class InstrBinder_1 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
public:
InstrBinder_1(func_t func, const CodeFieldBase& arg_func_1)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)((T1)m_arg_func_1(code));
}
};
template<typename TO, typename T1, typename T2>
class InstrBinder_2 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
public:
InstrBinder_2(func_t func, const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3>
class InstrBinder_3 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
public:
InstrBinder_3(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4>
class InstrBinder_4 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
public:
InstrBinder_4(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
class InstrBinder_5 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
public:
InstrBinder_5(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code)
);
}
};
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class InstrBinder_6 : public InstrCaller<TO>
{
typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6);
func_t m_func;
const CodeFieldBase& m_arg_func_1;
const CodeFieldBase& m_arg_func_2;
const CodeFieldBase& m_arg_func_3;
const CodeFieldBase& m_arg_func_4;
const CodeFieldBase& m_arg_func_5;
const CodeFieldBase& m_arg_func_6;
public:
InstrBinder_6(func_t func,
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
: InstrCaller()
, m_func(func)
, m_arg_func_1(arg_func_1)
, m_arg_func_2(arg_func_2)
, m_arg_func_3(arg_func_3)
, m_arg_func_4(arg_func_4)
, m_arg_func_5(arg_func_5)
, m_arg_func_6(arg_func_6)
{
}
virtual void operator ()(TO* op, u32 code) const
{
(op->*m_func)(
(T1)m_arg_func_1(code),
(T2)m_arg_func_2(code),
(T3)m_arg_func_3(code),
(T4)m_arg_func_4(code),
(T5)m_arg_func_5(code),
(T6)m_arg_func_6(code)
);
}
};
template<typename TO>
InstrCaller<TO>* instr_bind(void (TO::*func)())
{
return new InstrBinder_0<TO>(func);
}
template<typename TO, typename T1>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1)
{
return new InstrBinder_1<TO, T1>(func, arg_func_1);
}
template<typename TO, typename T1, typename T2>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2)
{
return new InstrBinder_2<TO, T1, T2>(func, arg_func_1, arg_func_2);
}
template<typename TO, typename T1, typename T2, typename T3>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3)
{
return new InstrBinder_3<TO, T1, T2, T3>(func, arg_func_1, arg_func_2, arg_func_3);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4)
{
return new InstrBinder_4<TO, T1, T2, T3, T4>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5)
{
return new InstrBinder_5<TO, T1, T2, T3, T4, T5>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5);
}
template<typename TO, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
InstrCaller<TO>* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6),
const CodeFieldBase& arg_func_1,
const CodeFieldBase& arg_func_2,
const CodeFieldBase& arg_func_3,
const CodeFieldBase& arg_func_4,
const CodeFieldBase& arg_func_5,
const CodeFieldBase& arg_func_6)
{
return new InstrBinder_6<TO, T1, T2, T3, T4, T5, T6>(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6);
}
template<typename TO>
class InstrBase : public InstrCaller<TO>
{
protected:
wxString m_name;
const u32 m_opcode;
CodeFieldBase** m_args;
const uint m_args_count;
public:
InstrBase(const wxString& name, int opcode, uint args_count)
: InstrCaller<TO>()
, m_name(name)
, m_opcode(opcode)
, m_args_count(args_count)
, m_args(args_count ? new CodeFieldBase*[args_count] : nullptr)
{
m_name.MakeLower().Replace("_", ".");
}
__forceinline const wxString& GetName() const
{
return m_name;
}
__forceinline const uint GetArgCount() const
{
return m_args_count;
}
__forceinline const CodeFieldBase& GetArg(uint index) const
{
assert(index < m_args_count);
return *m_args[index];
}
void operator ()(TO* op, u32 code) const
{
decode(op, code);
}
u32 operator()(const Array<u32>& args) const
{
return encode(args);
}
virtual void decode(TO* op, u32 code) const=0;
virtual u32 encode(const Array<u32>& args) const=0;
};
template<int _count, typename TO>
class InstrList : public InstrCaller<TO>
{
public:
static const int count = _count;
protected:
const CodeFieldBase& m_func;
InstrCaller<TO>* m_instrs[count];
InstrBase<TO>* m_instrs_info[count];
InstrCaller<TO>* m_error_func;
InstrCaller<TO>* m_parent;
int m_opcode;
public:
InstrList(const CodeFieldBase& func, InstrCaller<TO>* error_func)
: InstrCaller<TO>()
, m_func(func)
, m_error_func(error_func)
, m_parent(nullptr)
, m_opcode(-1)
{
for(int i=0; i<count; ++i)
{
m_instrs[i] = error_func;
}
memset(m_instrs_info, 0, sizeof(InstrBase<TO>*) * count);
}
virtual ~InstrList()
{
for(int i=0; i<count; ++i)
{
delete m_instrs[i];
}
delete m_error_func;
}
void set_parent(InstrCaller<TO>* parent, int opcode)
{
m_opcode = opcode;
m_parent = parent;
}
InstrCaller<TO>* get_parent() const
{
return m_parent;
}
u32 get_opcode() const
{
return m_opcode;
}
void set_error_func(InstrCaller<TO>* error_func)
{
for(int i=0; i<count; ++i)
{
if(m_instrs[i] == m_error_func || !m_instrs[i])
{
m_instrs[i] = error_func;
}
}
m_error_func = error_func;
}
void set_instr(uint pos, InstrCaller<TO>* func, InstrBase<TO>* info = nullptr)
{
assert(pos < count);
m_instrs[pos] = func;
m_instrs_info[pos] = info;
}
InstrCaller<TO>* get_instr(int pos) const
{
assert(pos < count);
return m_instrs[pos];
}
InstrBase<TO>* get_instr_info(int pos) const
{
assert(pos < count);
return m_instrs_info[pos];
}
u32 encode(u32 entry) const
{
return m_func[entry] | (m_parent ? (*m_parent)[m_opcode] : 0);
}
void decode(TO* op, u32 entry, u32 code) const
{
(*m_instrs[entry])(op, code);
}
virtual void operator ()(TO* op, u32 code) const
{
decode(op, m_func(code) & (count - 1), code);
}
virtual u32 operator [](u32 entry) const
{
return encode(entry);
}
};
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child, int opcode)
{
parent->set_instr(opcode, child);
child->set_parent(parent, opcode);
return child;
}
template<int count1, int count2, typename TO>
static InstrList<count2, TO>* connect_list(InstrList<count1, TO>* parent, InstrList<count2, TO>* child)
{
parent->set_error_func(child);
child->set_parent(parent->get_parent(), parent->get_opcode());
return child;
}
template<typename TO, int opcode, int count>
class Instr0 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr0(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)())
: InstrBase(name, opcode, 0)
, m_list(*list)
{
m_list.set_instr(opcode, instr_bind(func), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode);
}
u32 encode() const
{
return m_list.encode(opcode);
}
u32 operator()() const
{
return encode();
}
};
template<typename TO, int opcode, int count, typename T1>
class Instr1 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr1(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
: InstrBase(name, opcode, 1)
, m_list(*list)
{
m_args[0] = &arg_1;
m_list.set_instr(opcode, instr_bind(func, arg_1), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]];
}
u32 encode(T1 a1) const
{
return m_list.encode(opcode) | (*m_args[0])[a1];
}
u32 operator()(T1 a1) const
{
return encode(a1);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2>
class Instr2 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr2(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
: InstrBase(name, opcode, 2)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]];
}
u32 encode(T1 a1, T2 a2) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2];
}
u32 operator()(T1 a1, T2 a2) const
{
return encode(a1, a2);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3>
class Instr3 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr3(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
: InstrBase(name, opcode, 3)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) | (*m_args[0])[args[0]] | (*m_args[1])[args[1]] | (*m_args[2])[args[2]];
}
u32 encode(T1 a1, T2 a2, T3 a3) const
{
return m_list.encode(opcode) | (*m_args[0])[a1] | (*m_args[1])[a2] | (*m_args[2])[a3];
}
u32 operator()(T1 a1, T2 a2, T3 a3) const
{
return encode(a1, a2, a3);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4>
class Instr4 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr4(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
: InstrBase(name, opcode, 4)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4) const
{
return encode(a1, a2, a3, a4);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
class Instr5 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr5(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
: InstrBase(name, opcode, 5)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const
{
return encode(a1, a2, a3, a4, a5);
}
};
template<typename TO, int opcode, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Instr6 : public InstrBase<TO>
{
InstrList<count, TO>& m_list;
public:
Instr6(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
: InstrBase(name, opcode, 6)
, m_list(*list)
{
m_args[0] = &arg_1;
m_args[1] = &arg_2;
m_args[2] = &arg_3;
m_args[3] = &arg_4;
m_args[4] = &arg_5;
m_args[5] = &arg_6;
m_list.set_instr(opcode, instr_bind(func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6), this);
}
virtual void decode(TO* op, u32 code) const
{
m_list.decode(op, opcode, code);
}
virtual u32 encode(const Array<u32>& args) const
{
assert(args.GetCount() == m_args_count);
return m_list.encode(opcode) |
(*m_args[0])[args[0]] |
(*m_args[1])[args[1]] |
(*m_args[2])[args[2]] |
(*m_args[3])[args[3]] |
(*m_args[4])[args[4]] |
(*m_args[5])[args[5]];
}
u32 encode(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T5 a6) const
{
return m_list.encode(opcode) |
(*m_args[0])[a1] |
(*m_args[1])[a2] |
(*m_args[2])[a3] |
(*m_args[3])[a4] |
(*m_args[4])[a5] |
(*m_args[5])[a6];
}
u32 operator()(T1 a1, T2 a2, T3 a3, T4 a4, T4 a5, T4 a6) const
{
return encode(a1, a2, a3, a4, a5, a6);
}
};
template<int opcode, typename TO, int count>
static Instr0<TO, opcode, count>& make_instr(InstrList<count, TO>* list, const wxString& name, void (TO::*func)())
{
return *new Instr0<TO, opcode, count>(list, name, func);
}
template<int opcode, typename TO, int count, typename T1>
static Instr1<TO, opcode, count, T1>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1),
CodeFieldBase& arg_1)
{
return *new Instr1<TO, opcode, count, T1>(list, name, func, arg_1);
}
template<int opcode, typename TO, int count, typename T1, typename T2>
static Instr2<TO, opcode, count, T1, T2>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2)
{
return *new Instr2<TO, opcode, count, T1, T2>(list, name, func, arg_1, arg_2);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3>
static Instr3<TO, opcode, count, T1, T2, T3>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3)
{
return *new Instr3<TO, opcode, count, T1, T2, T3>(list, name, func, arg_1, arg_2, arg_3);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4>
static Instr4<TO, opcode, count, T1, T2, T3, T4>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4)
{
return *new Instr4<TO, opcode, count, T1, T2, T3, T4>(list, name, func, arg_1, arg_2, arg_3, arg_4);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5>
static Instr5<TO, opcode, count, T1, T2, T3, T4, T5>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5)
{
return *new Instr5<TO, opcode, count, T1, T2, T3, T4, T5>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5);
}
template<int opcode, typename TO, int count, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
static Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>& make_instr(InstrList<count, TO>* list, const wxString& name,
void (TO::*func)(T1, T2, T3, T4, T5, T6),
CodeFieldBase& arg_1,
CodeFieldBase& arg_2,
CodeFieldBase& arg_3,
CodeFieldBase& arg_4,
CodeFieldBase& arg_5,
CodeFieldBase& arg_6)
{
return *new Instr6<TO, opcode, count, T1, T2, T3, T4, T5, T6>(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
}