mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-28 19:20:36 +00:00
879 lines
20 KiB
C++
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);
|
|
} |