#pragma once #include "PPCInstrTable.h" #pragma warning( disable : 4800 ) template class InstrCaller { public: virtual ~InstrCaller() { } virtual void operator ()(TO* op, u32 code) const = 0; virtual u32 operator [](u32) const { return 0; } }; class PPC_Decoder { protected: u32 m_code; public: u32 GetCode() const { return m_code; } virtual void Decode(const u32 code)=0; }; template class InstrBinder_0 : public InstrCaller { 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 class InstrBinder_1 : public InstrCaller { 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 class InstrBinder_2 : public InstrCaller { 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 class InstrBinder_3 : public InstrCaller { 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 class InstrBinder_4 : public InstrCaller { 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 class InstrBinder_5 : public InstrCaller { 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 class InstrBinder_6 : public InstrCaller { 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 InstrCaller* instr_bind(void (TO::*func)()) { return new InstrBinder_0(func); } template InstrCaller* instr_bind(void (TO::*func)(T1), const CodeFieldBase& arg_func_1) { return new InstrBinder_1(func, arg_func_1); } template InstrCaller* instr_bind(void (TO::*func)(T1, T2), const CodeFieldBase& arg_func_1, const CodeFieldBase& arg_func_2) { return new InstrBinder_2(func, arg_func_1, arg_func_2); } template InstrCaller* 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(func, arg_func_1, arg_func_2, arg_func_3); } template InstrCaller* 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(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4); } template InstrCaller* 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(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5); } template InstrCaller* 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(func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6); } template class InstrBase : public InstrCaller { 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() , 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& args) const { return encode(args); } virtual void decode(TO* op, u32 code) const=0; virtual u32 encode(const Array& args) const=0; }; template class InstrList : public InstrCaller { public: static const int count = _count; protected: const CodeFieldBase& m_func; InstrCaller* m_instrs[count]; InstrBase* m_instrs_info[count]; InstrCaller* m_error_func; InstrCaller* m_parent; int m_opcode; public: InstrList(const CodeFieldBase& func, InstrCaller* error_func) : InstrCaller() , m_func(func) , m_error_func(error_func) , m_parent(nullptr) , m_opcode(-1) { memset(m_instrs, 0, sizeof(InstrCaller*) * count); memset(m_instrs_info, 0, sizeof(InstrBase*) * count); } virtual ~InstrList() { for(int i=0; i* parent, int opcode) { m_opcode = opcode; m_parent = parent; } InstrCaller* get_parent() const { return m_parent; } u32 get_opcode() const { return m_opcode; } void set_error_func(InstrCaller* error_func) { m_error_func = error_func; } void set_instr(uint pos, InstrCaller* func, InstrBase* info = nullptr) { assert(pos < count); m_instrs[pos] = func; m_instrs_info[pos] = info; } InstrCaller* get_instr(int pos) const { assert(pos < count); return m_instrs[pos]; } InstrBase* 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 { InstrCaller* instr = m_instrs[entry]; if(instr) { (*instr)(op, code); } else if(m_error_func) { (*m_error_func)(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 static InstrList* connect_list(InstrList* parent, InstrList* child, int opcode) { parent->set_instr(opcode, child); child->set_parent(parent, opcode); return child; } template static InstrList* connect_list(InstrList* parent, InstrList* child) { parent->set_error_func(child); child->set_parent(parent->get_parent(), parent->get_opcode()); return child; } template static InstrList* new_list(const CodeFieldBase& func, InstrCaller* error_func = nullptr) { return new InstrList(func, error_func); } template static InstrList* new_list(InstrList* parent, int opcode, const CodeFieldBase& func, InstrCaller* error_func = nullptr) { return connect_list(parent, new InstrList(func, error_func), opcode); } template static InstrList* new_list(InstrList* parent, const CodeFieldBase& func, InstrCaller* error_func = nullptr) { return connect_list(parent, new InstrList(func, error_func)); } template class Instr0 : public InstrBase { InstrList& m_list; public: Instr0(InstrList* 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& 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 class Instr1 : public InstrBase { InstrList& m_list; public: Instr1(InstrList* 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& 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 class Instr2 : public InstrBase { InstrList& m_list; public: Instr2(InstrList* 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& 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 class Instr3 : public InstrBase { InstrList& m_list; public: Instr3(InstrList* 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& 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 class Instr4 : public InstrBase { InstrList& m_list; public: Instr4(InstrList* 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& 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 class Instr5 : public InstrBase { InstrList& m_list; public: Instr5(InstrList* 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& 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 class Instr6 : public InstrBase { InstrList& m_list; public: Instr6(InstrList* 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& 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 static Instr0& make_instr(InstrList* list, const wxString& name, void (TO::*func)()) { return *new Instr0(list, name, func); } template static Instr1& make_instr(InstrList* list, const wxString& name, void (TO::*func)(T1), CodeFieldBase& arg_1) { return *new Instr1(list, name, func, arg_1); } template static Instr2& make_instr(InstrList* list, const wxString& name, void (TO::*func)(T1, T2), CodeFieldBase& arg_1, CodeFieldBase& arg_2) { return *new Instr2(list, name, func, arg_1, arg_2); } template static Instr3& make_instr(InstrList* list, const wxString& name, void (TO::*func)(T1, T2, T3), CodeFieldBase& arg_1, CodeFieldBase& arg_2, CodeFieldBase& arg_3) { return *new Instr3(list, name, func, arg_1, arg_2, arg_3); } template static Instr4& make_instr(InstrList* 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(list, name, func, arg_1, arg_2, arg_3, arg_4); } template static Instr5& make_instr(InstrList* 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(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5); } template static Instr6& make_instr(InstrList* 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(list, name, func, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6); }