From b35dfdf29bf03382b310f77472c3c9e262317c1f Mon Sep 17 00:00:00 2001 From: DH Date: Wed, 3 Jul 2013 19:17:16 +0300 Subject: [PATCH] - Improved PPCDecoder. - Improved PPUDecoder. - Improved Debugger GUI. CompilerELF: - Added all PPU instructions. - Fixed analyzer crash. --- rpcs3/Emu/Cell/Decoder.h | 342 ---- rpcs3/Emu/Cell/PPCDecoder.h | 899 +++++++++ rpcs3/Emu/Cell/{DisAsm.h => PPCDisAsm.h} | 4 +- rpcs3/Emu/Cell/PPCInstrTable.h | 135 ++ rpcs3/Emu/Cell/PPCThread.cpp | 43 +- rpcs3/Emu/Cell/PPCThread.h | 4 +- rpcs3/Emu/Cell/PPUDecoder.h | 755 +------- rpcs3/Emu/Cell/PPUDisAsm.h | 16 +- rpcs3/Emu/Cell/PPUInstrTable.h | 640 +++++++ rpcs3/Emu/Cell/PPUProgramCompiler.cpp | 1747 +++++++++++++++++ rpcs3/Emu/Cell/PPUProgramCompiler.h | 192 ++ rpcs3/Emu/Cell/SPUDecoder.h | 4 +- rpcs3/Emu/Cell/SPUDisAsm.h | 8 +- rpcs3/Emu/GS/GL/GLGSRender.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp | 4 +- rpcs3/Emu/System.cpp | 119 +- rpcs3/Emu/System.h | 12 +- rpcs3/Gui/CompilerELF.cpp | 2226 +--------------------- rpcs3/Gui/CompilerELF.h | 71 - rpcs3/Gui/DisAsmFrame.cpp | 8 +- rpcs3/Gui/GameViewer.cpp | 2 +- rpcs3/Gui/InterpreterDisAsm.cpp | 151 +- rpcs3/Gui/InterpreterDisAsm.h | 9 +- rpcs3/Gui/MainFrame.cpp | 118 +- rpcs3/Gui/MainFrame.h | 3 - rpcs3/Loader/ELF64.cpp | 59 +- rpcs3/Loader/ELF64.h | 6 +- rpcs3/Loader/Loader.h | 24 + rpcs3/rpcs3.cpp | 10 +- rpcs3/rpcs3.h | 14 + rpcs3/rpcs3.vcxproj | 7 +- rpcs3/rpcs3.vcxproj.filters | 21 +- 32 files changed, 4074 insertions(+), 3581 deletions(-) delete mode 100644 rpcs3/Emu/Cell/Decoder.h create mode 100644 rpcs3/Emu/Cell/PPCDecoder.h rename rpcs3/Emu/Cell/{DisAsm.h => PPCDisAsm.h} (99%) create mode 100644 rpcs3/Emu/Cell/PPCInstrTable.h create mode 100644 rpcs3/Emu/Cell/PPUInstrTable.h create mode 100644 rpcs3/Emu/Cell/PPUProgramCompiler.cpp create mode 100644 rpcs3/Emu/Cell/PPUProgramCompiler.h diff --git a/rpcs3/Emu/Cell/Decoder.h b/rpcs3/Emu/Cell/Decoder.h deleted file mode 100644 index 0aa488e33e..0000000000 --- a/rpcs3/Emu/Cell/Decoder.h +++ /dev/null @@ -1,342 +0,0 @@ -#pragma once - -class Decoder -{ -protected: - class instr_caller - { - public: - virtual ~instr_caller() - { - } - - virtual void operator ()() = 0; - }; - - instr_caller* m_instr_decoder; - - template - class instr_binder_0 : public instr_caller - { - typedef void (TO::*func_t)(); - TO* m_op; - func_t m_func; - - public: - instr_binder_0(TO* op, func_t func) - : instr_caller() - , m_op(op) - , m_func(func) - { - } - - virtual void operator ()() - { - (m_op->*m_func)(); - } - }; - - template - class instr_binder_1 : public instr_caller - { - typedef void (TO::*func_t)(T1); - typedef T1 (TD::*arg_1_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - - public: - instr_binder_1(TO* op, TD* dec, func_t func, arg_1_t arg_func_1) - : instr_caller() - , m_op(op) - , m_dec(dec) - , m_func(func) - , m_arg_func_1(arg_func_1) - { - } - - virtual void operator ()() - { - (m_op->*m_func)((m_dec->*m_arg_func_1)()); - } - }; - - template - class instr_binder_2 : public instr_caller - { - typedef void (TO::*func_t)(T1, T2); - typedef T1 (TD::*arg_1_t)(); - typedef T2 (TD::*arg_2_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - arg_2_t m_arg_func_2; - - public: - instr_binder_2(TO* op, TD* dec, func_t func, arg_1_t arg_func_1, arg_2_t arg_func_2) - : instr_caller() - , m_op(op) - , m_dec(dec) - , m_func(func) - , m_arg_func_1(arg_func_1) - , m_arg_func_2(arg_func_2) - { - } - - virtual void operator ()() - { - (m_op->*m_func)( - (m_dec->*m_arg_func_1)(), - (m_dec->*m_arg_func_2)() - ); - } - }; - - template - class instr_binder_3 : public instr_caller - { - typedef void (TO::*func_t)(T1, T2, T3); - typedef T1 (TD::*arg_1_t)(); - typedef T2 (TD::*arg_2_t)(); - typedef T3 (TD::*arg_3_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - arg_2_t m_arg_func_2; - arg_3_t m_arg_func_3; - - public: - instr_binder_3(TO* op, TD* dec, func_t func, - arg_1_t arg_func_1, - arg_2_t arg_func_2, - arg_3_t arg_func_3) - : instr_caller() - , m_op(op) - , m_dec(dec) - , 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 ()() - { - (m_op->*m_func)( - (m_dec->*m_arg_func_1)(), - (m_dec->*m_arg_func_2)(), - (m_dec->*m_arg_func_3)() - ); - } - }; - - template - class instr_binder_4 : public instr_caller - { - typedef void (TO::*func_t)(T1, T2, T3, T4); - typedef T1 (TD::*arg_1_t)(); - typedef T2 (TD::*arg_2_t)(); - typedef T3 (TD::*arg_3_t)(); - typedef T4 (TD::*arg_4_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - arg_2_t m_arg_func_2; - arg_3_t m_arg_func_3; - arg_4_t m_arg_func_4; - - public: - instr_binder_4(TO* op, TD* dec, func_t func, - arg_1_t arg_func_1, - arg_2_t arg_func_2, - arg_3_t arg_func_3, - arg_4_t arg_func_4) - : instr_caller() - , m_op(op) - , m_dec(dec) - , 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 ()() - { - (m_op->*m_func)( - (m_dec->*m_arg_func_1)(), - (m_dec->*m_arg_func_2)(), - (m_dec->*m_arg_func_3)(), - (m_dec->*m_arg_func_4)() - ); - } - }; - - template - class instr_binder_5 : public instr_caller - { - typedef void (TO::*func_t)(T1, T2, T3, T4, T5); - typedef T1 (TD::*arg_1_t)(); - typedef T2 (TD::*arg_2_t)(); - typedef T3 (TD::*arg_3_t)(); - typedef T4 (TD::*arg_4_t)(); - typedef T5 (TD::*arg_5_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - arg_2_t m_arg_func_2; - arg_3_t m_arg_func_3; - arg_4_t m_arg_func_4; - arg_5_t m_arg_func_5; - - public: - instr_binder_5(TO* op, TD* dec, func_t func, - arg_1_t arg_func_1, - arg_2_t arg_func_2, - arg_3_t arg_func_3, - arg_4_t arg_func_4, - arg_5_t arg_func_5) - : instr_caller() - , m_op(op) - , m_dec(dec) - , 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 ()() - { - (m_op->*m_func)( - (m_dec->*m_arg_func_1)(), - (m_dec->*m_arg_func_2)(), - (m_dec->*m_arg_func_3)(), - (m_dec->*m_arg_func_4)(), - (m_dec->*m_arg_func_5)() - ); - } - }; - - template - class instr_binder_6 : public instr_caller - { - typedef void (TO::*func_t)(T1, T2, T3, T4, T5, T6); - typedef T1 (TD::*arg_1_t)(); - typedef T2 (TD::*arg_2_t)(); - typedef T3 (TD::*arg_3_t)(); - typedef T4 (TD::*arg_4_t)(); - typedef T5 (TD::*arg_5_t)(); - typedef T6 (TD::*arg_6_t)(); - TO* m_op; - TD* m_dec; - func_t m_func; - arg_1_t m_arg_func_1; - arg_2_t m_arg_func_2; - arg_3_t m_arg_func_3; - arg_4_t m_arg_func_4; - arg_5_t m_arg_func_5; - arg_6_t m_arg_func_6; - - public: - instr_binder_6(TO* op, TD* dec, func_t func, - arg_1_t arg_func_1, - arg_2_t arg_func_2, - arg_3_t arg_func_3, - arg_4_t arg_func_4, - arg_5_t arg_func_5, - arg_6_t arg_func_6) - : instr_caller() - , m_op(op) - , m_dec(dec) - , 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 ()() - { - (m_op->*m_func)( - (m_dec->*m_arg_func_1)(), - (m_dec->*m_arg_func_2)(), - (m_dec->*m_arg_func_3)(), - (m_dec->*m_arg_func_4)(), - (m_dec->*m_arg_func_5)(), - (m_dec->*m_arg_func_6)() - ); - } - }; - - template - class instr_list : public instr_caller - { - typedef T (TD::*func_t)(); - - TD* m_parent; - func_t m_func; - instr_caller* m_instrs[count]; - instr_caller* m_error_func; - - public: - instr_list(TD* parent, func_t func, instr_caller* error_func) - : instr_caller() - , m_parent(parent) - , m_func(func) - , m_error_func(error_func) - { - memset(m_instrs, 0, sizeof(instr_caller*) * count); - } - - virtual ~instr_list() - { - for(int i=0; i*m_func)() & (count - 1)]; - - if(instr) - { - (*instr)(); - } - else if(m_error_func) - { - (*m_error_func)(); - } - } - }; - - template - instr_list* new_list(TD* parent, T (TD::*func)(), instr_caller* error_func) - { - return new instr_list(parent, func, error_func); - } - -public: - virtual void Decode(const u32 code)=0; -}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCDecoder.h b/rpcs3/Emu/Cell/PPCDecoder.h new file mode 100644 index 0000000000..f315da01b3 --- /dev/null +++ b/rpcs3/Emu/Cell/PPCDecoder.h @@ -0,0 +1,899 @@ +#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); +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/DisAsm.h b/rpcs3/Emu/Cell/PPCDisAsm.h similarity index 99% rename from rpcs3/Emu/Cell/DisAsm.h rename to rpcs3/Emu/Cell/PPCDisAsm.h index 5411e38dbe..14ca84246c 100644 --- a/rpcs3/Emu/Cell/DisAsm.h +++ b/rpcs3/Emu/Cell/PPCDisAsm.h @@ -11,7 +11,7 @@ enum DisAsmModes CompilerElfMode, }; -class DisAsm +class PPC_DisAsm { protected: DisAsmFrame* disasm_frame; @@ -58,7 +58,7 @@ public: uint dump_pc; protected: - DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) + PPC_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) : m_mode(mode) , disasm_frame(NULL) { diff --git a/rpcs3/Emu/Cell/PPCInstrTable.h b/rpcs3/Emu/Cell/PPCInstrTable.h new file mode 100644 index 0000000000..91725c1c7c --- /dev/null +++ b/rpcs3/Emu/Cell/PPCInstrTable.h @@ -0,0 +1,135 @@ +#pragma once + +template __forceinline static T sign(const T value) +{ + if(value & (1 << (size - 1))) + { + return value - (1 << size); + } + + return value; +} + +enum CodeFieldType +{ + FIELD_IMM, + FIELD_R_GPR, + FIELD_R_FPR, + FIELD_R_VPR, + FIELD_R_CR, + FIELD_BRANCH, +}; + +class CodeFieldBase +{ +public: + CodeFieldType m_type; + +public: + CodeFieldBase(CodeFieldType type = FIELD_IMM) : m_type(type) + { + } + + virtual u32 operator ()(u32 data) const=0; + virtual void operator()(u32& data, u32 value) const=0; + + virtual u32 operator[](u32 value) const + { + u32 result = 0; + (*this)(result, value); + return result; + } +}; + +template +class CodeField : public CodeFieldBase +{ + static_assert(from <= to, "too big 'from' value"); + static_assert(to <= 31, "too big 'to' value"); + +public: + CodeField(CodeFieldType type = FIELD_IMM) : CodeFieldBase(type) + { + } + + static const u32 shift = 31 - to; + static const u32 mask = ((1ULL << ((to - from) + 1)) - 1) << shift; + + static __forceinline void encode(u32& data, u32 value) + { + data &= ~mask; + data |= (value << shift) & mask; + } + + static __forceinline u32 decode(u32 data) + { + return (data & mask) >> shift; + } + + virtual u32 operator ()(u32 data) const + { + return decode(data); + } + + virtual void operator()(u32& data, u32 value) const + { + encode(data, value); + } +}; + +template +class DoubleCodeField : public CodeField +{ + static_assert(from2 <= to2, "too big from2 value"); + static_assert(to2 <= 31, "too big to2 value"); + +public: + DoubleCodeField(CodeFieldType type = FIELD_IMM) : CodeField(type) + { + } + + static const u32 shift2 = 31 - to2; + static const u32 mask2 = ((1 << ((to2 - from2) + 1)) - 1) << shift2; + + static __forceinline void encode(u32& data, u32 value) + { + data &= ~(mask | mask2); + data |= ((value << shift) & mask) | (((value >> offset) << shift2) & mask2); + } + + static __forceinline u32 decode(u32 data) + { + return ((data & mask) >> shift) | (((data & mask2) >> shift2) << offset); + } + + virtual u32 operator ()(u32 data) const + { + return decode(data); + } + + virtual void operator()(u32& data, u32 value) const + { + encode(data, value); + } +}; + +template +class CodeFieldSigned : public CodeField +{ +public: + CodeFieldSigned(CodeFieldType type = FIELD_IMM) : CodeField(type) + { + } + + static const int size = _size; + + static __forceinline u32 decode(u32 data) + { + return sign((data & mask) >> shift); + } + + virtual u32 operator ()(u32 data) const + { + return decode(data); + } +}; diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index 316f8e19ba..8124a58115 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -168,6 +168,8 @@ void PPCThread::Run() return; } + wxGetApp().SendDbgCommand(DID_START_THREAD, this); + m_status = Runned; SetPc(entry); @@ -176,49 +178,52 @@ void PPCThread::Run() DoRun(); Emu.CheckStatus(); - wxGetApp().SendDbgCommand(DID_START_THREAD, this); - - if(DisAsmFrame) (*(InterpreterDisAsmFrame*)DisAsmFrame).DoUpdate(); + wxGetApp().SendDbgCommand(DID_STARTED_THREAD, this); } void PPCThread::Resume() { if(!IsPaused()) return; + wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this); + m_status = Runned; DoResume(); Emu.CheckStatus(); - wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this); - ThreadBase::Start(); + + wxGetApp().SendDbgCommand(DID_RESUMED_THREAD, this); } void PPCThread::Pause() { if(!IsRunned()) return; + wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); + m_status = Paused; DoPause(); Emu.CheckStatus(); - wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); - ThreadBase::Stop(false); + wxGetApp().SendDbgCommand(DID_PAUSED_THREAD, this); } void PPCThread::Stop() { if(IsStopped()) return; + wxGetApp().SendDbgCommand(DID_STOP_THREAD, this); + m_status = Stopped; Reset(); DoStop(); Emu.CheckStatus(); - wxGetApp().SendDbgCommand(DID_STOP_THREAD, this); - ThreadBase::Stop(); + + wxGetApp().SendDbgCommand(DID_STOPED_THREAD, this); } void PPCThread::Exec() @@ -237,8 +242,19 @@ void PPCThread::Task() { ConLog.Write("%s enter", PPCThread::GetFName()); + const Array& bp = Emu.GetBreakPoints(); + try { + for(uint i=0; i> (31 - p)) & 0x1; - } - - __forceinline u32 GetField(const u32 from, const u32 to) - { - return (m_code >> (31 - to)) & ((1 << ((to - from) + 1)) - 1); - } - public: - template - instr_caller* instr_bind(TD* parent, void (TO::*func)()) + PPU_Decoder(PPU_Opcodes& op) : m_op(&op) { - return new instr_binder_0(parent, func); - } - - template - instr_caller* instr_bind(void (TO::*func)()) - { - return instr_bind(&m_op, func); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1), T1 (TD::*arg_func_1)()) - { - return new instr_binder_1(&m_op, this, func, arg_func_1); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1, T2), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)()) - { - return new instr_binder_2(&m_op, this, func, arg_func_1, arg_func_2); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1, T2, T3), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)()) - { - return new instr_binder_3(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)()) - { - return new instr_binder_4(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)(), T5 (TD::*arg_func_5)()) - { - return new instr_binder_5(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5); - } - - template - instr_caller* instr_bind(void (TO::*func)(T1, T2, T3, T4, T5, T6), T1 (TD::*arg_func_1)(), T2 (TD::*arg_func_2)(), T3 (TD::*arg_func_3)(), T4 (TD::*arg_func_4)(), T5 (TD::*arg_func_5)(), T6 (TD::*arg_func_6)()) - { - return new instr_binder_6(&m_op, this, func, arg_func_1, arg_func_2, arg_func_3, arg_func_4, arg_func_5, arg_func_6); - } - - void UNK_MAIN() - { - if(!m_code) - { - m_op.NULL_OP(); - } - else - { - u32 opcd = OPCD(); - m_op.UNK(m_code, opcd, opcd); - } - } - - PPU_Decoder(PPU_Opcodes& op) : m_op(op) - { -#define bind_instr(list, instr, ...) list->set_instr(instr, instr_bind(&PPU_Opcodes::##instr, ##__VA_ARGS__)) - - using namespace PPU_opcodes; - auto main_list = new_list<0x40>(this, &PPU_Decoder::OPCD, instr_bind(this, &PPU_Decoder::UNK_MAIN)); - auto g04_0_list = new_list<0x800>(this, &PPU_Decoder::GD_04_0, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_04_0)); - auto g04_list = new_list<0x40>(this, &PPU_Decoder::GD_04, g04_0_list); - auto g13_list = new_list<0x400>(this, &PPU_Decoder::GD_13, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_13)); - auto g1e_list = new_list<0x4>(this, &PPU_Decoder::GD_1e, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_1e)); - auto g1f_list = new_list<0x400>(this, &PPU_Decoder::GD_1f, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_1f)); - auto g3a_list = new_list<0x4>(this, &PPU_Decoder::GD_3a, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3a)); - auto g3b_list = new_list<0x20>(this, &PPU_Decoder::GD_3b, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3b)); - auto g3e_list = new_list<0x4>(this, &PPU_Decoder::GD_3e, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3e)); - auto g3f_0_list = new_list<0x400>(this, &PPU_Decoder::GD_3f_0, instr_bind(&PPU_Opcodes::UNK, &PPU_Decoder::GetCode, &PPU_Decoder::OPCD, &PPU_Decoder::GD_3f_0)); - auto g3f_list = new_list<0x20>(this, &PPU_Decoder::GD_3f, g3f_0_list); - - bind_instr(main_list, TDI, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, TWI, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::simm16); - main_list->set_instr(G_04, g04_list); - bind_instr(main_list, MULLI, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, SUBFIC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, CMPLI, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::uimm16); - bind_instr(main_list, CMPI, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, ADDIC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, ADDIC_, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, ADDI, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, ADDIS, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::simm16); - bind_instr(main_list, BC, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BD, &PPU_Decoder::AA, &PPU_Decoder::LK); - bind_instr(main_list, SC, &PPU_Decoder::SYS); - bind_instr(main_list, B, &PPU_Decoder::LL, &PPU_Decoder::AA, &PPU_Decoder::LK); - main_list->set_instr(G_13, g13_list); - bind_instr(main_list, RLWIMI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::SH, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC); - bind_instr(main_list, RLWINM, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::SH, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC); - bind_instr(main_list, RLWNM, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::MB, &PPU_Decoder::ME, &PPU_Decoder::RC); - bind_instr(main_list, ORI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - bind_instr(main_list, ORIS, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - bind_instr(main_list, XORI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - bind_instr(main_list, XORIS, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - bind_instr(main_list, ANDI_, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - bind_instr(main_list, ANDIS_, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::uimm16); - main_list->set_instr(G_1e, g1e_list); - main_list->set_instr(G_1f, g1f_list); - bind_instr(main_list, LWZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LWZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LBZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LBZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STW, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STWU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STB, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STBU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LHZ, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LHZU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STH, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STHU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LMW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STMW, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LFS, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LFSU, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LFD, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, LFDU, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STFS, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STFSU, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STFD, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(main_list, STFDU, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::D); - main_list->set_instr(G_3a, g3a_list); - main_list->set_instr(G_3b, g3b_list); - main_list->set_instr(G_3e, g3e_list); - main_list->set_instr(G_3f, g3f_list); - - bind_instr(g04_list, VMADDFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMHADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMHRADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMLADDUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMMBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMSHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VMSUMUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VNMSUBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VPERM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VSEL, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VC); - bind_instr(g04_list, VSLDOI, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB, &PPU_Decoder::VSH); - - bind_instr(g04_0_list, MFVSCR, &PPU_Decoder::VD); - bind_instr(g04_0_list, MTVSCR, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDCUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDSBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUWM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VADDUWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAND, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VANDC, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VAVGUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCFSX, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCFUX, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPBFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPEQUW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGEFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGEFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTFP_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTSW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUB_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUH_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCMPGTUW_, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCTSXS, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VCTUXS, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VEXPTEFP, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VLOGEFP, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMAXUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINSW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMINUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGHB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGHH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGHW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMRGLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULESB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULESH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULEUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULEUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULOSB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULOSH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULOUB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VMULOUH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VNOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKPX, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKSHSS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKSHUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKSWSS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKSWUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKUHUM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKUHUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKUWUM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VPKUWUS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VREFP, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRFIM, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRFIN, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRFIP, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRFIZ, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VRSQRTEFP, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSL, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSLB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSLH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSLO, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSLW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSPLTB, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSPLTH, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSPLTISB, &PPU_Decoder::VD, &PPU_Decoder::VSIMM); - bind_instr(g04_0_list, VSPLTISH, &PPU_Decoder::VD, &PPU_Decoder::VSIMM); - bind_instr(g04_0_list, VSPLTISW, &PPU_Decoder::VD, &PPU_Decoder::VSIMM); - bind_instr(g04_0_list, VSPLTW, &PPU_Decoder::VD, &PPU_Decoder::VUIMM, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRAB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRAH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRAW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRB, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRH, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRO, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSRW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBCUW, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBFP, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBSBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBSHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUBM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUHM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUWM, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUBUWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUMSWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUM2SWS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUM4SBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUM4SHS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VSUM4UBS, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKHPX, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKHSB, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKHSH, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKLPX, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKLSB, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VUPKLSH, &PPU_Decoder::VD, &PPU_Decoder::VB); - bind_instr(g04_0_list, VXOR, &PPU_Decoder::VD, &PPU_Decoder::VA, &PPU_Decoder::VB); - - bind_instr(g13_list, MCRF, &PPU_Decoder::CRFD, &PPU_Decoder::CRFS); - bind_instr(g13_list, BCLR, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BH, &PPU_Decoder::LK); - bind_instr(g13_list, CRNOR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CRANDC, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, ISYNC); - bind_instr(g13_list, CRXOR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CRNAND, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CRAND, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CREQV, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CRORC, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, CROR, &PPU_Decoder::CRBD, &PPU_Decoder::CRBA, &PPU_Decoder::CRBB); - bind_instr(g13_list, BCCTR, &PPU_Decoder::BO, &PPU_Decoder::BI, &PPU_Decoder::BH, &PPU_Decoder::LK); - - bind_instr(g1e_list, RLDICL, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC); - bind_instr(g1e_list, RLDICR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::me, &PPU_Decoder::RC); - bind_instr(g1e_list, RLDIC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC); - bind_instr(g1e_list, RLDIMI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::mb, &PPU_Decoder::RC); - - /*0x000*/bind_instr(g1f_list, CMP, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x004*/bind_instr(g1f_list, TW, &PPU_Decoder::TO, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x006*/bind_instr(g1f_list, LVSL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x007*/bind_instr(g1f_list, LVEBX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x008*/bind_instr(g1f_list, SUBFC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x009*/bind_instr(g1f_list, MULHDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x00a*/bind_instr(g1f_list, ADDC, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x00b*/bind_instr(g1f_list, MULHWU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x013*/bind_instr(g1f_list, MFOCRF, &PPU_Decoder::L_11, &PPU_Decoder::RD, &PPU_Decoder::CRM); - /*0x014*/bind_instr(g1f_list, LWARX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x015*/bind_instr(g1f_list, LDX, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB); - /*0x017*/bind_instr(g1f_list, LWZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x018*/bind_instr(g1f_list, SLW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x01a*/bind_instr(g1f_list, CNTLZW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC); - /*0x01b*/bind_instr(g1f_list, SLD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x01c*/bind_instr(g1f_list, AND, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x020*/bind_instr(g1f_list, CMPL, &PPU_Decoder::CRFD, &PPU_Decoder::L_10, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x026*/bind_instr(g1f_list, LVSR, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x027*/bind_instr(g1f_list, LVEHX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x028*/bind_instr(g1f_list, SUBF, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x036*/bind_instr(g1f_list, DCBST, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x03a*/bind_instr(g1f_list, CNTLZD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC); - /*0x03c*/bind_instr(g1f_list, ANDC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x047*/bind_instr(g1f_list, LVEWX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x049*/bind_instr(g1f_list, MULHD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x04b*/bind_instr(g1f_list, MULHW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x054*/bind_instr(g1f_list, LDARX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x056*/bind_instr(g1f_list, DCBF, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x057*/bind_instr(g1f_list, LBZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x067*/bind_instr(g1f_list, LVX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x068*/bind_instr(g1f_list, NEG, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x077*/bind_instr(g1f_list, LBZUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x07c*/bind_instr(g1f_list, NOR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x087*/bind_instr(g1f_list, STVEBX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x088*/bind_instr(g1f_list, SUBFE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x08a*/bind_instr(g1f_list, ADDE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x090*/bind_instr(g1f_list, MTOCRF, &PPU_Decoder::CRM, &PPU_Decoder::RS); - /*0x095*/bind_instr(g1f_list, STDX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x096*/bind_instr(g1f_list, STWCX_, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x097*/bind_instr(g1f_list, STWX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0a7*/bind_instr(g1f_list, STVEHX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0b5*/bind_instr(g1f_list, STDUX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0c7*/bind_instr(g1f_list, STVEWX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0ca*/bind_instr(g1f_list, ADDZE, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x0d6*/bind_instr(g1f_list, STDCX_, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0d7*/bind_instr(g1f_list, STBX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0e7*/bind_instr(g1f_list, STVX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x0e9*/bind_instr(g1f_list, MULLD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x0ea*/bind_instr(g1f_list, ADDME, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x0eb*/bind_instr(g1f_list, MULLW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x0f6*/bind_instr(g1f_list, DCBTST, &PPU_Decoder::TH, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x10a*/bind_instr(g1f_list, ADD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x116*/bind_instr(g1f_list, DCBT, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::TH); - /*0x117*/bind_instr(g1f_list, LHZX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x11c*/bind_instr(g1f_list, EQV, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x136*/bind_instr(g1f_list, ECIWX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x137*/bind_instr(g1f_list, LHZUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x13c*/bind_instr(g1f_list, XOR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x153*/bind_instr(g1f_list, MFSPR, &PPU_Decoder::RD, &PPU_Decoder::SPR); - /*0x156*/bind_instr(g1f_list, DST, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::STRM, &PPU_Decoder::L_6); - /*0x157*/bind_instr(g1f_list, LHAX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x167*/bind_instr(g1f_list, LVXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x168*/bind_instr(g1f_list, ABS, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x173*/bind_instr(g1f_list, MFTB, &PPU_Decoder::RD, &PPU_Decoder::SPR); - /*0x176*/bind_instr(g1f_list, DSTST, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::STRM, &PPU_Decoder::L_6); - /*0x177*/bind_instr(g1f_list, LHAUX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x197*/bind_instr(g1f_list, STHX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x19c*/bind_instr(g1f_list, ORC, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x1b6*/bind_instr(g1f_list, ECOWX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x1bc*/bind_instr(g1f_list, OR, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x1c9*/bind_instr(g1f_list, DIVDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x1cb*/bind_instr(g1f_list, DIVWU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x1d3*/bind_instr(g1f_list, MTSPR, &PPU_Decoder::SPR, &PPU_Decoder::RS); - /*0x1d6*///DCBI - /*0x1dc*/bind_instr(g1f_list, NAND, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x1e7*/bind_instr(g1f_list, STVXL, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x1e9*/bind_instr(g1f_list, DIVD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x1eb*/bind_instr(g1f_list, DIVW, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB, &PPU_Decoder::OE, &PPU_Decoder::RC); - /*0x207*/bind_instr(g1f_list, LVLX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x216*/bind_instr(g1f_list, LWBRX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x217*/bind_instr(g1f_list, LFSX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x218*/bind_instr(g1f_list, SRW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x21b*/bind_instr(g1f_list, SRD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x227*/bind_instr(g1f_list, LVRX, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x237*/bind_instr(g1f_list, LFSUX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x256*/bind_instr(g1f_list, SYNC, &PPU_Decoder::L_9_10); - /*0x257*/bind_instr(g1f_list, LFDX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x277*/bind_instr(g1f_list, LFDUX, &PPU_Decoder::FRD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x287*/bind_instr(g1f_list, STVLX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x297*/bind_instr(g1f_list, STFSX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x2a7*/bind_instr(g1f_list, STVRX, &PPU_Decoder::VS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x2d7*/bind_instr(g1f_list, STFDX, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x307*/bind_instr(g1f_list, LVLXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x316*/bind_instr(g1f_list, LHBRX, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x318*/bind_instr(g1f_list, SRAW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x31a*/bind_instr(g1f_list, SRAD, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RB, &PPU_Decoder::RC); - /*0x327*/bind_instr(g1f_list, LVRXL, &PPU_Decoder::VD, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x336*/bind_instr(g1f_list, DSS, &PPU_Decoder::STRM, &PPU_Decoder::L_6); - /*0x338*/bind_instr(g1f_list, SRAWI, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC); - /*0x33a*/bind_instr(g1f_list, SRADI1, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC); - /*0x33b*/bind_instr(g1f_list, SRADI2, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::sh, &PPU_Decoder::RC); - /*0x356*/bind_instr(g1f_list, EIEIO); - /*0x39a*/bind_instr(g1f_list, EXTSH, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC); - /*0x3ba*/bind_instr(g1f_list, EXTSB, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC); - /*0x3d7*/bind_instr(g1f_list, STFIWX, &PPU_Decoder::FRS, &PPU_Decoder::RA, &PPU_Decoder::RB); - /*0x3da*/bind_instr(g1f_list, EXTSW, &PPU_Decoder::RA, &PPU_Decoder::RS, &PPU_Decoder::RC); - /*0x3d6*///ICBI - /*0x3f6*/bind_instr(g1f_list, DCBZ, &PPU_Decoder::RA, &PPU_Decoder::RB); - - bind_instr(g3a_list, LD, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(g3a_list, LDU, &PPU_Decoder::RD, &PPU_Decoder::RA, &PPU_Decoder::DS); - - bind_instr(g3b_list, FDIVS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FSQRTS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FRES, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FMULS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::RC); - bind_instr(g3b_list, FMADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FMSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FNMSUBS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3b_list, FNMADDS, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - - bind_instr(g3e_list, STD, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::D); - bind_instr(g3e_list, STDU, &PPU_Decoder::RS, &PPU_Decoder::RA, &PPU_Decoder::DS); - - bind_instr(g3f_list, FSEL, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_list, FMUL, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::RC); - bind_instr(g3f_list, FMSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_list, FMADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_list, FNMSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_list, FNMADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRC, &PPU_Decoder::FRB, &PPU_Decoder::RC); - - bind_instr(g3f_0_list, FDIV, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FSUB, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FADD, &PPU_Decoder::FRD, &PPU_Decoder::FRA, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FSQRT, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FRSQRTE, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCMPU, &PPU_Decoder::CRFD, &PPU_Decoder::FRA, &PPU_Decoder::FRB); - bind_instr(g3f_0_list, FRSP, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCTIW, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCTIWZ, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCMPO, &PPU_Decoder::CRFD, &PPU_Decoder::FRA, &PPU_Decoder::FRB); - bind_instr(g3f_0_list, FNEG, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FMR, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FNABS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FABS, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCFID, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCTID, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - bind_instr(g3f_0_list, FCTIDZ, &PPU_Decoder::FRD, &PPU_Decoder::FRB, &PPU_Decoder::RC); - - bind_instr(g3f_0_list, MTFSB1, &PPU_Decoder::BT, &PPU_Decoder::RC); - bind_instr(g3f_0_list, MCRFS, &PPU_Decoder::BF, &PPU_Decoder::BFA); - bind_instr(g3f_0_list, MTFSB0, &PPU_Decoder::BT, &PPU_Decoder::RC); - bind_instr(g3f_0_list, MTFSFI, &PPU_Decoder::CRFD, &PPU_Decoder::I, &PPU_Decoder::RC); - bind_instr(g3f_0_list, MFFS, &PPU_Decoder::FRD, &PPU_Decoder::RC); - bind_instr(g3f_0_list, MTFSF, &PPU_Decoder::FLM, &PPU_Decoder::FRB, &PPU_Decoder::RC); - - m_instr_decoder = main_list; } ~PPU_Decoder() { - m_op.Exit(); - delete m_instr_decoder; + m_op->Exit(); + delete m_op; } virtual void Decode(const u32 code) { - m_code = code; - (*m_instr_decoder)(); + (*PPU_instr::main_list)(m_op, code); } -}; - -#undef START_OPCODES_GROUP -#undef START_OPCODES_SUB_GROUP -#undef ADD_OPCODE -#undef ADD_NULL_OPCODE -#undef END_OPCODES_GROUP -#undef END_OPCODES_ND_GROUP -#undef END_OPCODES_SUB_GROUP \ No newline at end of file +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index 1574230cf1..6efde556b7 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -1,7 +1,7 @@ #pragma once #include "Emu/Cell/PPUOpcodes.h" -#include "Emu/Cell/DisAsm.h" +#include "Emu/Cell/PPCDisAsm.h" #include "Emu/Cell/PPCThread.h" #include "Gui/DisAsmFrame.h" #include "Emu/Memory/Memory.h" @@ -11,19 +11,19 @@ class PPU_DisAsm : public PPU_Opcodes - , public DisAsm + , public PPC_DisAsm { public: PPCThread& CPU; PPU_DisAsm() - : DisAsm(*(PPCThread*)NULL, DumpMode) + : PPC_DisAsm(*(PPCThread*)NULL, DumpMode) , CPU(*(PPCThread*)NULL) { } PPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) - : DisAsm(cpu, mode) + : PPC_DisAsm(cpu, mode) , CPU(cpu) { } @@ -937,14 +937,6 @@ private: case 1: DisAsm_INT3("bcctrl", bo, bi, bh); break; } } - void BCTR() - { - Write("bctr"); - } - void BCTRL() - { - Write("bctrl"); - } END_OPCODES_GROUP(G_13); diff --git a/rpcs3/Emu/Cell/PPUInstrTable.h b/rpcs3/Emu/Cell/PPUInstrTable.h new file mode 100644 index 0000000000..018532d751 --- /dev/null +++ b/rpcs3/Emu/Cell/PPUInstrTable.h @@ -0,0 +1,640 @@ +#pragma once +#include "PPCInstrTable.h" +#include "PPCDecoder.h" +#include "PPUOpcodes.h" + +namespace PPU_instr +{ + //This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask + static DoubleCodeField<21, 25, 26, 26, 5> mb; + + //This field is used in rotate instructions to specify the last 1 bit of a 64-bit mask + static DoubleCodeField<21, 25, 26, 26, 5> me; + + //This field is used to specify a shift amount + static DoubleCodeField<16, 20, 30, 30, 5> sh; + + //This field is used to specify a special-purpose register for the mtspr and mfspr instructions + static CodeField<11, 20> SPR; + + // + static CodeField<6, 10> VS(FIELD_R_VPR); + + // + static CodeField<6, 10> VD(FIELD_R_VPR); + + // + static CodeField<11, 15> VA(FIELD_R_VPR); + + // + static CodeField<16, 20> VB(FIELD_R_VPR); + + // + static CodeField<21, 25> VC(FIELD_R_VPR); + + // + static CodeField<11, 15> VUIMM; + + // + static CodeFieldSigned<11, 15> VSIMM; + + // + static CodeField<22, 25> VSH; + + //This field is used to specify a GPR to be used as a destination + static CodeField<6, 10> RD(FIELD_R_GPR); + + //This field is used to specify a GPR to be used as a source + static CodeField<6, 10> RS(FIELD_R_GPR); + + //This field is used to specify a GPR to be used as a source or destination + static CodeField<11, 15> RA(FIELD_R_GPR); + + //This field is used to specify a GPR to be used as a source + static CodeField<16, 20> RB(FIELD_R_GPR); + + //This field is used to specify the number of bytes to move in an immediate string load or store + static CodeField<16, 20> NB; + + //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a destination + static CodeField<6, 8> CRFD(FIELD_R_CR); + + //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a source + static CodeField<11, 13> CRFS(FIELD_R_CR); + + //This field is used to specify a bit in the CR to be used as a source + static CodeField<11, 15> CRBA(FIELD_R_CR); + + //This field is used to specify a bit in the CR to be used as a source + static CodeField<16, 20> CRBB(FIELD_R_CR); + + //This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction + static CodeField<6, 10> CRBD(FIELD_R_CR); + + // + static CodeField<6, 10> BT; + + // + static CodeField<11, 15> BA; + + // + static CodeField<16, 20> BB; + + // + static CodeField<6, 10> BF; + + //This field is used to specify options for the branch conditional instructions + static CodeField<6, 10> BO; + + //This field is used to specify a bit in the CR to be used as the condition of a branch conditional instruction + static CodeField<11, 13> BI; + + //Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the + //right with ‘00’ and sign-extended to 64 bits. + static CodeFieldSigned<16, 31> BD(FIELD_BRANCH); + + // + static CodeField<19, 20> BH; + + // + static CodeField<11, 13> BFA; + + //Field used by the optional data stream variant of the dcbt instruction. + static CodeField<9, 10> TH; + + //This field is used to specify the conditions on which to trap + static CodeField<6, 10> TO; + + // + static CodeField<21, 25> MB; + + // + static CodeField<26, 30> ME; + + //This field is used to specify a shift amount + static CodeField<16, 20> SH; + + /* + Absolute address bit. + 0 The immediate field represents an address relative to the current instruction address (CIA). (For more + information on the CIA, see Table 8-3.) The effective (logical) address of the branch is either the sum + of the LI field sign-extended to 64 bits and the address of the branch instruction or the sum of the BD + field sign-extended to 64 bits and the address of the branch instruction. + 1 The immediate field represents an absolute address. The effective address (EA) of the branch is the + LI field sign-extended to 64 bits or the BD field sign-extended to 64 bits. + */ + static CodeField<30> AA; + + // + static CodeFieldSigned<6, 31> LL(FIELD_BRANCH); + /* + Link bit. + 0 Does not update the link register (LR). + 1 Updates the LR. If the instruction is a branch instruction, the address of the instruction following the + branch instruction is placed into the LR. + */ + static CodeField<31> LK; + + //This field is used for extended arithmetic to enable setting OV and SO in the XER + static CodeField<21> OE; + + //Field used to specify whether an integer compare instruction is to compare 64-bit numbers or 32-bit numbers + static CodeField<10> L_10; + static CodeField<6> L_6; + static CodeField<9, 10> L_9_10; + static CodeField<11> L_11; + // + static CodeField<16, 19> I; + + // + static CodeField<16, 27> DQ; + + //This field is used to specify an FPR as the destination + static CodeField<6, 10> FRD; + + //This field is used to specify an FPR as a source + static CodeField<6, 10> FRS; + + // + static CodeField<7, 14> FLM; + + //This field is used to specify an FPR as a source + static CodeField<11, 15> FRA(FIELD_R_FPR); + + //This field is used to specify an FPR as a source + static CodeField<16, 20> FRB(FIELD_R_FPR); + + //This field is used to specify an FPR as a source + static CodeField<21, 25> FRC(FIELD_R_FPR); + + //This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction. + static CodeField<12, 19> CRM; + + // + static CodeField<6, 31> SYS; + + //Immediate field specifying a 16-bit signed two's complement integer that is sign-extended to 64 bits + static CodeFieldSigned<16, 31> D; + + // + struct : public CodeFieldSigned<16, 31> + { + static __forceinline u32 decode(u32 data) + { + int res = sign((data & mask) >> shift); + if(res < 0) return res - 1; + return res; + } + + static __forceinline void encode(u32& data, u32 value) + { + if((s32)value < 0) + { + value++; + } + + data &= ~mask; + data |= (value << shift) & mask; + } + + virtual u32 operator ()(u32 data) const + { + return decode(data); + } + + virtual void operator ()(u32& data, u32 value) const + { + return encode(data, value); + } + } static DS; + + //This immediate field is used to specify a 16-bit signed integer + static CodeFieldSigned<16, 31> simm16; + + //This immediate field is used to specify a 16-bit unsigned integer + static CodeField<16, 31> uimm16; + + /* + Record bit. + 0 Does not update the condition register (CR). + 1 Updates the CR to reflect the result of the operation. + For integer instructions, CR bits [0–2] are set to reflect the result as a signed quantity and CR bit [3] + receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit + string can be deduced from the EQ bit. For floating-point instructions, CR bits [4–7] are set to reflect + floating-point exception, floating-point enabled exception, floating-point invalid operation exception, + and floating-point overflow exception. + */ + static CodeField<31> RC; + + //Primary opcode field + static CodeField<0, 5> OPCD; + + static CodeField<26, 31> GD_04; //0x3f + static CodeField<21, 31> GD_04_0;//0x7ff + static CodeField<21, 30> GD_13; //0x3ff + static CodeField<28, 29> GD_1e; //0x3 + static CodeField<21, 30> GD_1f; //0x3ff + static CodeField<30, 31> GD_3a; //0x3 + static CodeField<26, 30> GD_3b; //0x1f + static CodeField<30, 31> GD_3e; //0x3 + static CodeField<26, 30> GD_3f;//0x1f + static CodeField<21, 30> GD_3f_0; //0x3ff + + static CodeField<0, 31> GetCode; + static CodeField<9, 10> STRM; + + static auto main_list = new_list<0x40>(OPCD, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, OPCD)); + static auto g04_list = new_list<0x40>(main_list, PPU_opcodes::G_04, GD_04); + static auto g04_0_list = new_list<0x800>(g04_list, GD_04_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_04_0)); + static auto g13_list = new_list<0x400>(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_13)); + static auto g1e_list = new_list<0x4>(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1e)); + static auto g1f_list = new_list<0x400>(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_1f)); + static auto g3a_list = new_list<0x4>(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3a)); + static auto g3b_list = new_list<0x20>(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3b)); + static auto g3e_list = new_list<0x4>(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3e)); + static auto g3f_list = new_list<0x20>(main_list, PPU_opcodes::G_3f, GD_3f); + static auto g3f_0_list = new_list<0x400>(g3f_list, GD_3f_0, instr_bind(&PPU_Opcodes::UNK, GetCode, OPCD, GD_3f_0)); + + #define bind_instr(list, name, ...) \ + static const auto& name = make_instr(list, #name, &PPU_Opcodes::name, ##__VA_ARGS__) + + bind_instr(main_list, TDI, TO, RA, simm16); + bind_instr(main_list, TWI, TO, RA, simm16); + bind_instr(main_list, MULLI, RD, RA, simm16); + bind_instr(main_list, SUBFIC, RD, RA, simm16); + bind_instr(main_list, CMPLI, CRFD, L_10, RA, uimm16); + bind_instr(main_list, CMPI, CRFD, L_10, RA, simm16); + bind_instr(main_list, ADDIC, RD, RA, simm16); + bind_instr(main_list, ADDIC_, RD, RA, simm16); + bind_instr(main_list, ADDI, RD, RA, simm16); + bind_instr(main_list, ADDIS, RD, RA, simm16); + bind_instr(main_list, BC, BO, BI, BD, AA, LK); + bind_instr(main_list, SC, SYS); + bind_instr(main_list, B, LL, AA, LK); + bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC); + bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC); + bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC); + bind_instr(main_list, ORI, RA, RS, uimm16); + bind_instr(main_list, ORIS, RA, RS, uimm16); + bind_instr(main_list, XORI, RA, RS, uimm16); + bind_instr(main_list, XORIS, RA, RS, uimm16); + bind_instr(main_list, ANDI_, RA, RS, uimm16); + bind_instr(main_list, ANDIS_, RA, RS, uimm16); + bind_instr(main_list, LWZ, RD, RA, D); + bind_instr(main_list, LWZU, RD, RA, D); + bind_instr(main_list, LBZ, RD, RA, D); + bind_instr(main_list, LBZU, RD, RA, D); + bind_instr(main_list, STW, RS, RA, D); + bind_instr(main_list, STWU, RS, RA, D); + bind_instr(main_list, STB, RS, RA, D); + bind_instr(main_list, STBU, RS, RA, D); + bind_instr(main_list, LHZ, RD, RA, D); + bind_instr(main_list, LHZU, RD, RA, D); + bind_instr(main_list, STH, RS, RA, D); + bind_instr(main_list, STHU, RS, RA, D); + bind_instr(main_list, LMW, RD, RA, D); + bind_instr(main_list, STMW, RS, RA, D); + bind_instr(main_list, LFS, FRD, RA, D); + bind_instr(main_list, LFSU, FRD, RA, D); + bind_instr(main_list, LFD, FRD, RA, D); + bind_instr(main_list, LFDU, FRD, RA, D); + bind_instr(main_list, STFS, FRS, RA, D); + bind_instr(main_list, STFSU, FRS, RA, D); + bind_instr(main_list, STFD, FRS, RA, D); + bind_instr(main_list, STFDU, FRS, RA, D); + + bind_instr(g04_list, VMADDFP, VD, VA, VB, VC); + bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMMBM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMSHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC); + bind_instr(g04_list, VNMSUBFP, VD, VA, VB, VC); + bind_instr(g04_list, VPERM, VD, VA, VB, VC); + bind_instr(g04_list, VSEL, VD, VA, VB, VC); + bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH); + + bind_instr(g04_0_list, MFVSCR, VD); + bind_instr(g04_0_list, MTVSCR, VB); + bind_instr(g04_0_list, VADDCUW, VD, VA, VB); + bind_instr(g04_0_list, VADDFP, VD, VA, VB); + bind_instr(g04_0_list, VADDSBS, VD, VA, VB); + bind_instr(g04_0_list, VADDSHS, VD, VA, VB); + bind_instr(g04_0_list, VADDSWS, VD, VA, VB); + bind_instr(g04_0_list, VADDUBM, VD, VA, VB); + bind_instr(g04_0_list, VADDUBS, VD, VA, VB); + bind_instr(g04_0_list, VADDUHM, VD, VA, VB); + bind_instr(g04_0_list, VADDUHS, VD, VA, VB); + bind_instr(g04_0_list, VADDUWM, VD, VA, VB); + bind_instr(g04_0_list, VADDUWS, VD, VA, VB); + bind_instr(g04_0_list, VAND, VD, VA, VB); + bind_instr(g04_0_list, VANDC, VD, VA, VB); + bind_instr(g04_0_list, VAVGSB, VD, VA, VB); + bind_instr(g04_0_list, VAVGSH, VD, VA, VB); + bind_instr(g04_0_list, VAVGSW, VD, VA, VB); + bind_instr(g04_0_list, VAVGUB, VD, VA, VB); + bind_instr(g04_0_list, VAVGUH, VD, VA, VB); + bind_instr(g04_0_list, VAVGUW, VD, VA, VB); + bind_instr(g04_0_list, VCFSX, VD, VUIMM, VB); + bind_instr(g04_0_list, VCFUX, VD, VUIMM, VB); + bind_instr(g04_0_list, VCMPBFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPBFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUB, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUH, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUW, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUW_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGEFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPGEFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSB, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSH, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSW, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSW_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUB, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUH, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUW, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUW_, VD, VA, VB); + bind_instr(g04_0_list, VCTSXS, VD, VUIMM, VB); + bind_instr(g04_0_list, VCTUXS, VD, VUIMM, VB); + bind_instr(g04_0_list, VEXPTEFP, VD, VB); + bind_instr(g04_0_list, VLOGEFP, VD, VB); + bind_instr(g04_0_list, VMAXFP, VD, VA, VB); + bind_instr(g04_0_list, VMAXSB, VD, VA, VB); + bind_instr(g04_0_list, VMAXSH, VD, VA, VB); + bind_instr(g04_0_list, VMAXSW, VD, VA, VB); + bind_instr(g04_0_list, VMAXUB, VD, VA, VB); + bind_instr(g04_0_list, VMAXUH, VD, VA, VB); + bind_instr(g04_0_list, VMAXUW, VD, VA, VB); + bind_instr(g04_0_list, VMINFP, VD, VA, VB); + bind_instr(g04_0_list, VMINSB, VD, VA, VB); + bind_instr(g04_0_list, VMINSH, VD, VA, VB); + bind_instr(g04_0_list, VMINSW, VD, VA, VB); + bind_instr(g04_0_list, VMINUB, VD, VA, VB); + bind_instr(g04_0_list, VMINUH, VD, VA, VB); + bind_instr(g04_0_list, VMINUW, VD, VA, VB); + bind_instr(g04_0_list, VMRGHB, VD, VA, VB); + bind_instr(g04_0_list, VMRGHH, VD, VA, VB); + bind_instr(g04_0_list, VMRGHW, VD, VA, VB); + bind_instr(g04_0_list, VMRGLB, VD, VA, VB); + bind_instr(g04_0_list, VMRGLH, VD, VA, VB); + bind_instr(g04_0_list, VMRGLW, VD, VA, VB); + bind_instr(g04_0_list, VMULESB, VD, VA, VB); + bind_instr(g04_0_list, VMULESH, VD, VA, VB); + bind_instr(g04_0_list, VMULEUB, VD, VA, VB); + bind_instr(g04_0_list, VMULEUH, VD, VA, VB); + bind_instr(g04_0_list, VMULOSB, VD, VA, VB); + bind_instr(g04_0_list, VMULOSH, VD, VA, VB); + bind_instr(g04_0_list, VMULOUB, VD, VA, VB); + bind_instr(g04_0_list, VMULOUH, VD, VA, VB); + bind_instr(g04_0_list, VNOR, VD, VA, VB); + bind_instr(g04_0_list, VOR, VD, VA, VB); + bind_instr(g04_0_list, VPKPX, VD, VA, VB); + bind_instr(g04_0_list, VPKSHSS, VD, VA, VB); + bind_instr(g04_0_list, VPKSHUS, VD, VA, VB); + bind_instr(g04_0_list, VPKSWSS, VD, VA, VB); + bind_instr(g04_0_list, VPKSWUS, VD, VA, VB); + bind_instr(g04_0_list, VPKUHUM, VD, VA, VB); + bind_instr(g04_0_list, VPKUHUS, VD, VA, VB); + bind_instr(g04_0_list, VPKUWUM, VD, VA, VB); + bind_instr(g04_0_list, VPKUWUS, VD, VA, VB); + bind_instr(g04_0_list, VREFP, VD, VB); + bind_instr(g04_0_list, VRFIM, VD, VB); + bind_instr(g04_0_list, VRFIN, VD, VB); + bind_instr(g04_0_list, VRFIP, VD, VB); + bind_instr(g04_0_list, VRFIZ, VD, VB); + bind_instr(g04_0_list, VRLB, VD, VA, VB); + bind_instr(g04_0_list, VRLH, VD, VA, VB); + bind_instr(g04_0_list, VRLW, VD, VA, VB); + bind_instr(g04_0_list, VRSQRTEFP, VD, VB); + bind_instr(g04_0_list, VSL, VD, VA, VB); + bind_instr(g04_0_list, VSLB, VD, VA, VB); + bind_instr(g04_0_list, VSLH, VD, VA, VB); + bind_instr(g04_0_list, VSLO, VD, VA, VB); + bind_instr(g04_0_list, VSLW, VD, VA, VB); + bind_instr(g04_0_list, VSPLTB, VD, VUIMM, VB); + bind_instr(g04_0_list, VSPLTH, VD, VUIMM, VB); + bind_instr(g04_0_list, VSPLTISB, VD, VSIMM); + bind_instr(g04_0_list, VSPLTISH, VD, VSIMM); + bind_instr(g04_0_list, VSPLTISW, VD, VSIMM); + bind_instr(g04_0_list, VSPLTW, VD, VUIMM, VB); + bind_instr(g04_0_list, VSR, VD, VA, VB); + bind_instr(g04_0_list, VSRAB, VD, VA, VB); + bind_instr(g04_0_list, VSRAH, VD, VA, VB); + bind_instr(g04_0_list, VSRAW, VD, VA, VB); + bind_instr(g04_0_list, VSRB, VD, VA, VB); + bind_instr(g04_0_list, VSRH, VD, VA, VB); + bind_instr(g04_0_list, VSRO, VD, VA, VB); + bind_instr(g04_0_list, VSRW, VD, VA, VB); + bind_instr(g04_0_list, VSUBCUW, VD, VA, VB); + bind_instr(g04_0_list, VSUBFP, VD, VA, VB); + bind_instr(g04_0_list, VSUBSBS, VD, VA, VB); + bind_instr(g04_0_list, VSUBSHS, VD, VA, VB); + bind_instr(g04_0_list, VSUBSWS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUBM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUBS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUHM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUHS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUWM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUWS, VD, VA, VB); + bind_instr(g04_0_list, VSUMSWS, VD, VA, VB); + bind_instr(g04_0_list, VSUM2SWS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4SBS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4SHS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4UBS, VD, VA, VB); + bind_instr(g04_0_list, VUPKHPX, VD, VB); + bind_instr(g04_0_list, VUPKHSB, VD, VB); + bind_instr(g04_0_list, VUPKHSH, VD, VB); + bind_instr(g04_0_list, VUPKLPX, VD, VB); + bind_instr(g04_0_list, VUPKLSB, VD, VB); + bind_instr(g04_0_list, VUPKLSH, VD, VB); + bind_instr(g04_0_list, VXOR, VD, VA, VB); + + bind_instr(g13_list, MCRF, CRFD, CRFS); + bind_instr(g13_list, BCLR, BO, BI, BH, LK); + bind_instr(g13_list, CRNOR, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRANDC, CRBD, CRBA, CRBB); + bind_instr(g13_list, ISYNC); + bind_instr(g13_list, CRXOR, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRNAND, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRAND, CRBD, CRBA, CRBB); + bind_instr(g13_list, CREQV, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRORC, CRBD, CRBA, CRBB); + bind_instr(g13_list, CROR, CRBD, CRBA, CRBB); + bind_instr(g13_list, BCCTR, BO, BI, BH, LK); + + bind_instr(g1e_list, RLDICL, RA, RS, sh, mb, RC); + bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC); + bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC); + bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC); + + /*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB); + /*0x004*/bind_instr(g1f_list, TW, TO, RA, RB); + /*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB); + /*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB); + /*0x008*/bind_instr(g1f_list, SUBFC, RD, RA, RB, OE, RC); + /*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC); + /*0x00a*/bind_instr(g1f_list, ADDC, RD, RA, RB, OE, RC); + /*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC); + /*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM); + /*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB); + /*0x015*/bind_instr(g1f_list, LDX, RA, RS, RB); + /*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB); + /*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC); + /*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC); + /*0x01b*/bind_instr(g1f_list, SLD, RA, RS, RB, RC); + /*0x01c*/bind_instr(g1f_list, AND, RA, RS, RB, RC); + /*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB); + /*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB); + /*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB); + /*0x028*/bind_instr(g1f_list, SUBF, RD, RA, RB, OE, RC); + /*0x036*/bind_instr(g1f_list, DCBST, RA, RB); + /*0x03a*/bind_instr(g1f_list, CNTLZD, RA, RS, RC); + /*0x03c*/bind_instr(g1f_list, ANDC, RA, RS, RB, RC); + /*0x047*/bind_instr(g1f_list, LVEWX, VD, RA, RB); + /*0x049*/bind_instr(g1f_list, MULHD, RD, RA, RB, RC); + /*0x04b*/bind_instr(g1f_list, MULHW, RD, RA, RB, RC); + /*0x054*/bind_instr(g1f_list, LDARX, RD, RA, RB); + /*0x056*/bind_instr(g1f_list, DCBF, RA, RB); + /*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB); + /*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB); + /*0x068*/bind_instr(g1f_list, NEG, RD, RA, OE, RC); + /*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB); + /*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC); + /*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB); + /*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC); + /*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC); + /*0x090*/bind_instr(g1f_list, MTOCRF, CRM, RS); + /*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB); + /*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB); + /*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB); + /*0x0a7*/bind_instr(g1f_list, STVEHX, VS, RA, RB); + /*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB); + /*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB); + /*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC); + /*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB); + /*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB); + /*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB); + /*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC); + /*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC); + /*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC); + /*0x0f6*/bind_instr(g1f_list, DCBTST, TH, RA, RB); + /*0x10a*/bind_instr(g1f_list, ADD, RD, RA, RB, OE, RC); + /*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH); + /*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB); + /*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC); + /*0x136*/bind_instr(g1f_list, ECIWX, RD, RA, RB); + /*0x137*/bind_instr(g1f_list, LHZUX, RD, RA, RB); + /*0x13c*/bind_instr(g1f_list, XOR, RA, RS, RB, RC); + /*0x153*/bind_instr(g1f_list, MFSPR, RD, SPR); + /*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6); + /*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB); + /*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB); + /*0x168*/bind_instr(g1f_list, ABS, RD, RA, OE, RC); + /*0x173*/bind_instr(g1f_list, MFTB, RD, SPR); + /*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6); + /*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB); + /*0x197*/bind_instr(g1f_list, STHX, RS, RA, RB); + /*0x19c*/bind_instr(g1f_list, ORC, RA, RS, RB, RC); + /*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB); + /*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC); + /*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC); + /*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC); + /*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS); + /*0x1d6*///DCBI + /*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC); + /*0x1e7*/bind_instr(g1f_list, STVXL, RS, RA, RB); + /*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC); + /*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC); + /*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB); + /*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB); + /*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB); + /*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC); + /*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC); + /*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB); + /*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB); + /*0x256*/bind_instr(g1f_list, SYNC, L_9_10); + /*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB); + /*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB); + /*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB); + /*0x297*/bind_instr(g1f_list, STFSX, RS, RA, RB); + /*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB); + /*0x2d7*/bind_instr(g1f_list, STFDX, RS, RA, RB); + /*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB); + /*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB); + /*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC); + /*0x31a*/bind_instr(g1f_list, SRAD, RA, RS, RB, RC); + /*0x327*/bind_instr(g1f_list, LVRXL, VD, RA, RB); + /*0x336*/bind_instr(g1f_list, DSS, STRM, L_6); + /*0x338*/bind_instr(g1f_list, SRAWI, RA, RS, sh, RC); + /*0x33a*/bind_instr(g1f_list, SRADI1, RA, RS, sh, RC); + /*0x33b*/bind_instr(g1f_list, SRADI2, RA, RS, sh, RC); + /*0x356*/bind_instr(g1f_list, EIEIO); + /*0x39a*/bind_instr(g1f_list, EXTSH, RA, RS, RC); + /*0x3ba*/bind_instr(g1f_list, EXTSB, RA, RS, RC); + /*0x3d7*/bind_instr(g1f_list, STFIWX, FRS, RA, RB); + /*0x3da*/bind_instr(g1f_list, EXTSW, RA, RS, RC); + /*0x3d6*///ICBI + /*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB); + + bind_instr(g3a_list, LD, RD, RA, D); + bind_instr(g3a_list, LDU, RD, RA, DS); + + bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FSUBS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FADDS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FSQRTS, FRD, FRB, RC); + bind_instr(g3b_list, FRES, FRD, FRB, RC); + bind_instr(g3b_list, FMULS, FRD, FRA, FRC, RC); + bind_instr(g3b_list, FMADDS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FMSUBS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC); + + bind_instr(g3e_list, STD, RS, RA, D); + bind_instr(g3e_list, STDU, RS, RA, DS); + + bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FMUL, FRD, FRA, FRC, RC); + bind_instr(g3f_list, FMSUB, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FMADD, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FNMSUB, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FNMADD, FRD, FRA, FRC, FRB, RC); + + bind_instr(g3f_0_list, FDIV, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FSUB, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FADD, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FSQRT, FRD, FRB, RC); + bind_instr(g3f_0_list, FRSQRTE, FRD, FRB, RC); + bind_instr(g3f_0_list, FCMPU, CRFD, FRA, FRB); + bind_instr(g3f_0_list, FRSP, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIW, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIWZ, FRD, FRB, RC); + bind_instr(g3f_0_list, FCMPO, CRFD, FRA, FRB); + bind_instr(g3f_0_list, FNEG, FRD, FRB, RC); + bind_instr(g3f_0_list, FMR, FRD, FRB, RC); + bind_instr(g3f_0_list, FNABS, FRD, FRB, RC); + bind_instr(g3f_0_list, FABS, FRD, FRB, RC); + bind_instr(g3f_0_list, FCFID, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTID, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIDZ, FRD, FRB, RC); + + bind_instr(g3f_0_list, MTFSB1, BT, RC); + bind_instr(g3f_0_list, MCRFS, BF, BFA); + bind_instr(g3f_0_list, MTFSB0, BT, RC); + bind_instr(g3f_0_list, MTFSFI, CRFD, I, RC); + bind_instr(g3f_0_list, MFFS, FRD, RC); + bind_instr(g3f_0_list, MTFSF, FLM, FRB, RC); +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp new file mode 100644 index 0000000000..8733ab4a36 --- /dev/null +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp @@ -0,0 +1,1747 @@ +#include "stdafx.h" +#include "PPUProgramCompiler.h" + +using namespace PPU_instr; + +template +InstrBase* GetInstruction(T* list, const wxString& str) +{ + for(int i=0; icount; ++i) + { + auto instr = list->get_instr_info(i); + + if(instr) + { + if(instr->GetName().Cmp(str) == 0) + { + return instr; + } + } + } + + return nullptr; +} + +template +InstrBase* GetInstruction(const wxString& str) +{ + if(auto res = GetInstruction(main_list, str)) return res; + if(auto res = GetInstruction(g04_list, str)) return res; + if(auto res = GetInstruction(g04_0_list, str)) return res; + if(auto res = GetInstruction(g13_list, str)) return res; + if(auto res = GetInstruction(g1e_list, str)) return res; + if(auto res = GetInstruction(g1f_list, str)) return res; + if(auto res = GetInstruction(g3a_list, str)) return res; + if(auto res = GetInstruction(g3b_list, str)) return res; + if(auto res = GetInstruction(g3e_list, str)) return res; + if(auto res = GetInstruction(g3f_list, str)) return res; + if(auto res = GetInstruction(g3f_0_list, str)) return res; + + return nullptr; +} + +s64 FindOp(const wxString& text, const wxString& op, s64 from) +{ + if(text.Len() < op.Len()) return -1; + + for(s64 i=from; i= text.Len() || text[i + op.Len()] == '\n' || + CompilePPUProgram::IsSkip(text[i + op.Len()])) return i; + } + } + + return -1; +} + +ArrayF sections_list; +u32 section_name_offs = 0; +u32 section_offs = 0; + +SectionInfo::SectionInfo(const wxString& _name) : name(_name) +{ + memset(&shdr, 0, sizeof(Elf64_Shdr)); + + section_num = sections_list.Add(this); + + shdr.sh_offset = section_offs; + shdr.sh_name = section_name_offs; + + section_name_offs += name.Len() + 1; +} + +void SectionInfo::SetDataSize(u32 size, u32 align) +{ + if(align) shdr.sh_addralign = align; + if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign); + + if(code.GetCount()) + { + for(u32 i=section_num + 1; iWriteText(text); + } +} + +void CompilePPUProgram::WriteError(const wxString& error) +{ + if(m_err_list) + { + m_err_list->WriteText(wxString::Format("line %lld: %s\n", m_line, error)); + } +} + +bool CompilePPUProgram::IsSkip(const char c) { return c == ' ' || c == '\t'; } +bool CompilePPUProgram::IsCommit(const char c) { return c == '#'; } +bool CompilePPUProgram::IsEnd() const { return p >= m_asm.Len(); } +bool CompilePPUProgram::IsEndLn(const char c) const { return c == '\n' || p - 1 >= m_asm.Len(); } + +char CompilePPUProgram::NextChar() { return *m_asm(p++, 1); } +void CompilePPUProgram::NextLn() { while( !IsEndLn(NextChar()) ); if(!IsEnd()) m_line++; } +void CompilePPUProgram::EndLn() +{ + NextLn(); + p--; + m_line--; +} + +void CompilePPUProgram::FirstChar() +{ + p = 0; + m_line = 1; + m_branch_pos = 0; +} + +void CompilePPUProgram::PrevArg() +{ + while( --p >= 0 && (IsSkip(m_asm[p]) || m_asm[p] == ',')); + while( --p >= 0 && !IsSkip(m_asm[p]) && !IsEndLn(m_asm[p]) ); + if(IsEndLn(m_asm[p])) p++; +} + +bool CompilePPUProgram::GetOp(wxString& result) +{ + s64 from = -1; + + for(;;) + { + const char cur_char = NextChar(); + + const bool skip = IsSkip(cur_char); + const bool commit = IsCommit(cur_char); + const bool endln = IsEndLn(cur_char); + + if(endln) p--; + + if(from == -1) + { + if(endln || commit) return false; + if(!skip) from = p - 1; + continue; + } + + if(skip || endln || commit) + { + const s64 to = (endln ? p : p - 1) - from; + result = m_asm(from, to); + + return true; + } + } + + return false; +} + +int CompilePPUProgram::GetArg(wxString& result, bool func) +{ + s64 from = -1; + + for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) + { + const bool skip = IsSkip(cur_char); + const bool commit = IsCommit(cur_char); + const bool endln = IsEndLn(cur_char); + const bool end = cur_char == ',' || (func && cur_char == ']'); + + if(endln) p--; + + if(from == -1) + { + if(endln || commit || end) return 0; + if(!skip) from = p - 1; + continue; + } + + const bool text = m_asm[from] == '"'; + const bool end_text = cur_char == '"'; + + if((text ? end_text : (skip || commit || end)) || endln) + { + if(text && p > 2 && m_asm[p - 2] == '\\' && (p <= 3 || m_asm[p - 3] != '\\')) + { + continue; + } + + if(text && !end_text) + { + WriteError(wxString::Format("'\"' not found.")); + m_error = true; + } + + const s64 to = ((endln || text) ? p : p - 1) - from; + int ret = 1; + + if(skip || text) + { + for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) + { + const bool skip = IsSkip(cur_char); + const bool commit = IsCommit(cur_char); + const bool endln = IsEndLn(cur_char); + const bool end = cur_char == ',' || (func && cur_char == ']'); + + if(skip) continue; + if(end) break; + + if(commit) + { + EndLn(); + ret = -1; + break; + } + + if(endln) + { + p--; + break; + } + + WriteError(wxString::Format("Bad symbol '%c'", cur_char)); + m_error = true; + break; + } + } + + result = m_asm(from, to); + + if(text) + { + for(u32 pos = 0; (s32)(pos = result.find('\\', pos)) >= 0;) + { + if(pos + 1 < result.Len() && result[pos + 1] == '\\') + { + pos += 2; + continue; + } + + const char v = result[pos + 1]; + switch(v) + { + case 'n': result = result(0, pos) + '\n' + result(pos+2, result.Len()-(pos+2)); break; + case 'r': result = result(0, pos) + '\r' + result(pos+2, result.Len()-(pos+2)); break; + case 't': result = result(0, pos) + '\t' + result(pos+2, result.Len()-(pos+2)); break; + } + + pos++; + } + } + + return ret; + } + } + + return 0; +} + +bool CompilePPUProgram::CheckEnd(bool show_err) +{ + if(m_error) + { + NextLn(); + return false; + } + + while(true) + { + const char cur_char = NextChar(); + const bool skip = IsSkip(cur_char); + const bool commit = IsCommit(cur_char); + const bool endln = IsEndLn(cur_char); + + if(skip) continue; + + if(commit) + { + NextLn(); + return true; + } + + if(endln) + { + p--; + NextLn(); + return true; + } + + WriteError(wxString::Format("Bad symbol '%c'", cur_char)); + NextLn(); + return false; + } + + return false; +} + +void CompilePPUProgram::DetectArgInfo(Arg& arg) +{ + const wxString str = arg.string; + + if(str.Len() <= 0) + { + arg.type = ARG_ERR; + return; + } + + if(GetInstruction(str)) + { + arg.type = ARG_INSTR; + return; + } + + if(str.Len() > 1) + { + for(u32 i=0; i '9') + { + arg.type = ARG_ERR; + return; + } + } + + u32 reg; + sscanf(str(1, str.Len() - 1), "%d", ®); + + if(reg >= 32) + { + arg.type = ARG_ERR; + return; + } + + switch(str[0]) + { + case 'r': arg.type = ARG_REG_R; break; + case 'f': arg.type = ARG_REG_F; break; + case 'v': arg.type = ARG_REG_V; break; + default: arg.type = ARG_ERR; break; + } + + arg.value = reg; + return; + + case 'c': + if(str.Len() > 2 && str[1] == 'r') + { + for(u32 i=2; i '9') + { + arg.type = ARG_ERR; + return; + } + } + + u32 reg; + sscanf(str, "cr%d", ®); + + if(reg < 8) + { + arg.type = ARG_REG_CR; + arg.value = reg; + } + else + { + arg.type = ARG_ERR; + } + + return; + } + break; + + case '"': + if(str.Len() < 2) + { + arg.type = ARG_ERR; + return; + } + + if(str[str.Len() - 1] != '"') + { + arg.type = ARG_ERR; + return; + } + + arg.string = str(1, str.Len() - 2); + arg.type = ARG_TXT; + return; + } + + if(str.Len() > 2 && str(0, 2).Cmp("0x") == 0) + { + for(u32 i=2; i= '0' && str[i] <= '9') || + (str[i] >= 'a' && str[i] <= 'f') || + (str[i] >= 'A' && str[i] <= 'F') + ) continue; + + arg.type = ARG_ERR; + return; + } + + u32 val; + sscanf(str, "0x%x", &val); + + arg.type = ARG_NUM16; + arg.value = val; + return; + } + + for(u32 i= str[0] == '-' ? 1 : 0; i '9') + { + arg.type = ARG_ERR; + return; + } + } + + u32 val; + sscanf(str, "%d", &val); + + arg.type = ARG_NUM; + arg.value = val; +} + +void CompilePPUProgram::LoadArgs() +{ + m_args.Clear(); + m_cur_arg = 0; + + wxString str; + while(int r = GetArg(str)) + { + Arg* arg = new Arg(str); + DetectArgInfo(*arg); + m_args.Add(arg); + if(r == -1) break; + } + + m_end_args = m_args.GetCount() > 0; +} + +u32 CompilePPUProgram::GetBranchValue(const wxString& branch) +{ + for(u32 i=0; i= 0) return m_text_addr + m_branches[i].m_pos * 4; + + return m_branches[i].m_addr; + } + + return 0; +} + +bool CompilePPUProgram::SetNextArgType(u32 types, bool show_err) +{ + if(m_error) return false; + + if(m_cur_arg >= m_args.GetCount()) + { + if(show_err) + { + WriteError(wxString::Format("%d arg not found", m_cur_arg + 1)); + m_error = true; + } + + return false; + } + + const Arg& arg = m_args[m_cur_arg]; + + if(arg.type & types) + { + m_cur_arg++; + return true; + } + + if(show_err) + { + WriteError(wxString::Format("Bad arg '%s'", arg.string)); + m_error = true; + } + + return false; +} + +bool CompilePPUProgram::SetNextArgBranch(u8 aa, bool show_err) +{ + const u32 pos = m_cur_arg; + const bool ret = SetNextArgType(ARG_BRANCH | ARG_IMM, show_err); + + if(!aa && pos < m_args.GetCount()) + { + switch(m_args[pos].type) + { + case ARG_NUM: + m_args[pos].value += m_text_addr + m_branch_pos * 4; + break; + + case ARG_BRANCH: + m_args[pos].value -= m_text_addr + m_branch_pos * 4; + break; + } + } + + return ret; +} + +bool CompilePPUProgram::IsBranchOp(const wxString& op) +{ + return op.Len() > 1 && op[op.Len() - 1] == ':'; +} + +bool CompilePPUProgram::IsFuncOp(const wxString& op) +{ + return op.Len() >= 1 && op[0] == '['; +} + +CompilePPUProgram::SP_TYPE CompilePPUProgram::GetSpType(const wxString& op) +{ + if(op.Cmp(".int") == 0) return SP_INT; + if(op.Cmp(".string") == 0) return SP_STRING; + if(op.Cmp(".strlen") == 0) return SP_STRLEN; + if(op.Cmp(".buf") == 0) return SP_BUF; + if(op.Cmp(".srl") == 0) return SP_SRL; + if(op.Cmp(".srr") == 0) return SP_SRR; + if(op.Cmp(".mul") == 0) return SP_MUL; + if(op.Cmp(".div") == 0) return SP_DIV; + if(op.Cmp(".add") == 0) return SP_ADD; + if(op.Cmp(".sub") == 0) return SP_SUB; + if(op.Cmp(".and") == 0) return SP_AND; + if(op.Cmp(".or") == 0) return SP_OR; + if(op.Cmp(".xor") == 0) return SP_XOR; + if(op.Cmp(".not") == 0) return SP_NOT; + if(op.Cmp(".nor") == 0) return SP_NOR; + + return SP_ERR; +} + +wxString CompilePPUProgram::GetSpStyle(const SP_TYPE sp) +{ + switch(sp) + { + case SP_INT: + case SP_STRING: + case SP_STRLEN: + case SP_NOT: + return "[dst, src]"; + + case SP_BUF: + return "[dst, size]"; + + case SP_SRL: + case SP_SRR: + case SP_MUL: + case SP_DIV: + case SP_ADD: + case SP_SUB: + case SP_AND: + case SP_OR: + case SP_XOR: + case SP_NOR: + return "[dst, src1, src2]"; + } + + return "error"; +} + +bool CompilePPUProgram::IsSpOp(const wxString& op) +{ + return GetSpType(op) != SP_ERR; +} + +CompilePPUProgram::Branch& CompilePPUProgram::GetBranch(const wxString& name) +{ + for(u32 i=0; i 0 && m_asm[p] != '[') p--; + p++; + + wxString dst; + if(!GetArg(dst)) + { + if(m_analyze) WriteHex("error\n"); + WriteError(wxString::Format("dst not found. style: %s", GetSpStyle(sp))); + m_error = true; + NextLn(); + return; + } + + Arg a_dst(dst); + DetectArgInfo(a_dst); + + Branch* dst_branch = NULL; + + switch(a_dst.type) + { + case ARG_BRANCH: + { + Branch& b = GetBranch(dst); + if(b.m_addr >= 0 && b.m_id < 0 && b.m_pos < 0) dst_branch = &b; + } + break; + + case ARG_ERR: + { + m_branches.Move(new Branch(wxEmptyString, -1, 0)); + dst_branch = &m_branches[m_branches.GetCount() - 1]; + } + break; + } + + if(!dst_branch) + { + if(m_analyze) WriteHex("error\n"); + WriteError(wxString::Format("bad dst type. style: %s", GetSpStyle(sp))); + m_error = true; + NextLn(); + return; + } + + switch(sp) + { + case SP_INT: + case SP_STRING: + case SP_STRLEN: + case SP_BUF: + case SP_NOT: + { + wxString src1; + if(!GetArg(src1, true)) + { + if(m_analyze) WriteHex("error\n"); + WriteError(wxString::Format("src not found. style: %s", GetSpStyle(sp))); + m_error = true; + NextLn(); + return; + } + + Arg a_src1(src1); + DetectArgInfo(a_src1); + + if(sp == SP_STRLEN + ? ~(ARG_TXT | ARG_BRANCH) & a_src1.type + : sp == SP_STRING + ? ~ARG_TXT & a_src1.type + : ~(ARG_IMM | ARG_BRANCH) & a_src1.type) + { + if(m_analyze) WriteHex("error\n"); + WriteError(wxString::Format("bad src type. style: %s", GetSpStyle(sp))); + m_error = true; + NextLn(); + return; + } + + if(m_asm[p - 1] != ']') + { + if(m_analyze) WriteHex("error\n"); + WriteError(wxString::Format("']' not found. style: %s", GetSpStyle(sp))); + m_error = true; + NextLn(); + return; + } + + if(!CheckEnd()) + { + if(m_analyze) WriteHex("error\n"); + return; + } + + if(sp == SP_STRING) + { + src1 = src1(1, src1.Len()-2); + bool founded = false; + + for(u32 i=0; i> a_src2.value); break; + case SP_MUL: *dst_branch = Branch(dst, -1, a_src1.value * a_src2.value); break; + case SP_DIV: *dst_branch = Branch(dst, -1, a_src1.value / a_src2.value); break; + case SP_ADD: *dst_branch = Branch(dst, -1, a_src1.value + a_src2.value); break; + case SP_SUB: *dst_branch = Branch(dst, -1, a_src1.value - a_src2.value); break; + case SP_AND: *dst_branch = Branch(dst, -1, a_src1.value & a_src2.value); break; + case SP_OR: *dst_branch = Branch(dst, -1, a_src1.value | a_src2.value); break; + case SP_XOR: *dst_branch = Branch(dst, -1, a_src1.value ^ a_src2.value); break; + case SP_NOR: *dst_branch = Branch(dst, -1, ~(a_src1.value | a_src2.value)); break; + } + } + break; + } + + if(m_analyze) WriteHex("\n"); +} + +void CompilePPUProgram::Compile() +{ + if(m_err_list) + { + m_err_list->Freeze(); + m_err_list->Clear(); + } + + if(m_analyze && m_hex_list) + { + m_hex_list->Freeze(); + m_hex_list->Clear(); + } + + m_code.Clear(); + + for(u32 i=0; i m_imports; + + Module(const wxString& name, u32 import) : m_name(name) + { + Add(import); + } + + void Add(u32 import) + { + m_imports.AddCpy(import); + } + + void Clear() + { + m_name.Clear(); + m_imports.Clear(); + } + }; + + Array modules; + + FirstChar(); + while(!IsEnd()) + { + wxString op; + if(!GetOp(op) || !IsFuncOp(op)) + { + NextLn(); + continue; + } + + while(p > 0 && m_asm[p] != '[') p--; + p++; + + wxString module, name, id; + + if(!GetArg(module)) + { + WriteError("module not found. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + Arg a_module(module); + DetectArgInfo(a_module); + + if(~ARG_ERR & a_module.type) + { + WriteError("bad module type. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + if(!GetArg(name)) + { + WriteError("name not found. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + Arg a_name(name); + DetectArgInfo(a_name); + + if(~ARG_ERR & a_name.type) + { + WriteError("bad name type. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + if(!GetArg(id, true)) + { + WriteError("id not found. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + Arg a_id(id); + DetectArgInfo(a_id); + + if(~ARG_IMM & a_id.type) + { + WriteError("bad id type. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + if(m_asm[p - 1] != ']') + { + WriteError("']' not found. style: [module, name, id]"); + m_error = true; + NextLn(); + continue; + } + + if(!CheckEnd()) continue; + + m_branches.Move(new Branch(name, a_id.value, 0)); + const u32 import = m_branches.GetCount() - 1; + + bool founded = false; + for(u32 i=0; i(op); + if(instr) + { + /* + FIELD_IMM, + FIELD_R_GPR, + FIELD_R_FPR, + FIELD_R_VPR, + FIELD_R_CR, + FIELD_BRANCH, + */ + uint type[] = + { + ARG_IMM, + ARG_REG_R, + ARG_REG_F, + ARG_REG_V, + ARG_REG_CR, + }; + + for(uint i=0; iGetArgCount(); ++i) + { + switch(instr->GetArg(i).m_type) + { + case FIELD_BRANCH: + SetNextArgBranch(0); //TODO + break; + + default: + SetNextArgType(type[instr->GetArg(i).m_type]); + break; + } + } + } + else + { + WriteError(wxString::Format("unknown instruction '%s'", op)); + EndLn(); + m_error = true; + } + + CheckEnd(); + + if(m_error) + { + if(m_analyze) + { + WriteHex("error\n"); + m_error = false; + continue; + } + + break; + } + + u32 code; + + { + Array args; + args.SetCount(m_args.GetCount()); + for(uint i=0; i> 16)); + Write32(f, LWZ(12, 12, addr)); + Write32(f, STD(2, 1, 40)); + Write32(f, LWZ(0, 12, 0)); + Write32(f, LWZ(2, 12, 4)); + Write32(f, MTSPR(0x009, 0)); + Write32(f, BCCTR(20, 0, 0, 0)); + /* + Write32(f, ToOpcode(ADDI) | ToRD(12)); //li r12,0 + Write32(f, ToOpcode(ORIS) | ToRD(12) | ToRA(12) | ToIMM16(addr >> 16)); //oris r12,r12,addr>>16 + Write32(f, ToOpcode(LWZ) | ToRD(12) | ToRA(12) | ToIMM16(addr)); //lwz r12,addr&0xffff(r12) + Write32(f, 0xf8410028); //std r2,40(r1) + Write32(f, ToOpcode(LWZ) | ToRD(0) | ToRA(12) | ToIMM16(0)); //lwz r0,0(r12) + Write32(f, ToOpcode(LWZ) | ToRD(2) | ToRA(12) | ToIMM16(4)); //lwz r2,4(r12) + Write32(f, 0x7c0903a6); //mtctr r0 + Write32(f, 0x4e800420); //bctr + */ + } + + f.Seek(s_lib_stub_top.sh_offset); + f.Seek(s_lib_stub_top.sh_size, wxFromCurrent); + + f.Seek(s_lib_stub.sh_offset); + for(u32 i=0, nameoffs=4, dataoffs=0; iThaw(); + + if(m_analyze) + { + if(m_hex_list) + { + m_hex_list->Thaw(); + } + } + else + { + system("make_fself.cmd"); + } +} diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.h b/rpcs3/Emu/Cell/PPUProgramCompiler.h new file mode 100644 index 0000000000..b86d4f7a3e --- /dev/null +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.h @@ -0,0 +1,192 @@ +#pragma once +#include "PPUInstrTable.h" +#include "Loader/ELF64.h" + +enum ArgType +{ + ARG_ERR = 0, + ARG_NUM = 1 << 0, + ARG_NUM16 = 1 << 1, + ARG_TXT = 1 << 2, + ARG_REG_R = 1 << 3, + ARG_REG_F = 1 << 4, + ARG_REG_V = 1 << 5, + ARG_REG_CR = 1 << 6, + ARG_BRANCH = 1 << 7, + ARG_INSTR = 1 << 8, + ARG_IMM = ARG_NUM | ARG_NUM16 | ARG_BRANCH, +}; + +struct Arg +{ + wxString string; + u32 value; + ArgType type; + + Arg(const wxString& _string, const u32 _value = 0, const ArgType _type = ARG_ERR) + : string(_string) + , value(_value) + , type(_type) + { + } +}; + +struct SectionInfo +{ + Elf64_Shdr shdr; + wxString name; + Array code; + u32 section_num; + + SectionInfo(const wxString& name); + ~SectionInfo(); + + void SetDataSize(u32 size, u32 align = 0); +}; + +struct ProgramInfo +{ + Array code; + Elf64_Phdr phdr; + bool is_preload; + + ProgramInfo() + { + is_preload = false; + code.Clear(); + memset(&phdr, 0, sizeof(Elf64_Phdr)); + } +}; + +class CompilePPUProgram +{ + struct Branch + { + wxString m_name; + s32 m_pos; + s32 m_id; + s32 m_addr; + + Branch(const wxString& name, s32 pos) + : m_name(name) + , m_pos(pos) + , m_id(-1) + , m_addr(-1) + { + } + + Branch(const wxString& name, u32 id, u32 addr) + : m_name(name) + , m_pos(-1) + , m_id(id) + , m_addr(addr) + { + } + }; + + bool m_analyze; + s64 p; + u64 m_line; + const wxString& m_asm; + wxTextCtrl* m_asm_list; + wxTextCtrl* m_hex_list; + wxTextCtrl* m_err_list; + bool m_error; + Array m_code; + bool m_end_args; + Array m_branches; + s32 m_branch_pos; + u32 m_text_addr; + wxString m_file_path; + + struct SpData + { + wxString m_data; + u32 m_addr; + + SpData(const wxString& data, u32 addr) + : m_data(data) + , m_addr(addr) + { + } + }; + + Array m_sp_string; + Array m_args; + u32 m_cur_arg; + +public: + CompilePPUProgram( + const wxString& asm_, + const wxString& file_path = wxEmptyString, + wxTextCtrl* asm_list = nullptr, + wxTextCtrl* hex_list = nullptr, + wxTextCtrl* err_list = nullptr, + bool analyze = false); + + static bool IsSkip(const char c); + static bool IsCommit(const char c); + +protected: + bool IsEnd() const; + bool IsEndLn(const char c) const; + + void WriteHex(const wxString& text); + void WriteError(const wxString& error); + + char NextChar(); + void NextLn(); + void EndLn(); + + void FirstChar(); + void PrevArg(); + + bool GetOp(wxString& result); + int GetArg(wxString& result, bool func = false); + + bool CheckEnd(bool show_err = true); + + void DetectArgInfo(Arg& arg); + void LoadArgs(); + u32 GetBranchValue(const wxString& branch); + + bool SetNextArgType(u32 types, bool show_err = true); + bool SetNextArgBranch(u8 aa, bool show_err = true); + +public: + static bool IsBranchOp(const wxString& op); + static bool IsFuncOp(const wxString& op); + + enum SP_TYPE + { + SP_ERR, + SP_INT, + SP_STRING, + SP_STRLEN, + SP_BUF, + SP_SRL, + SP_SRR, + SP_MUL, + SP_DIV, + SP_ADD, + SP_SUB, + SP_AND, + SP_OR, + SP_XOR, + SP_NOT, + SP_NOR, + }; + + static SP_TYPE GetSpType(const wxString& op); + static wxString GetSpStyle(const SP_TYPE sp); + + static bool IsSpOp(const wxString& op); + +protected: + Branch& GetBranch(const wxString& name); + void SetSp(const wxString& name, u32 addr, bool create); + void LoadSp(const wxString& op, Elf64_Shdr& s_opd); + +public: + void Compile(); +}; diff --git a/rpcs3/Emu/Cell/SPUDecoder.h b/rpcs3/Emu/Cell/SPUDecoder.h index 5f315a8d2a..6d96281c09 100644 --- a/rpcs3/Emu/Cell/SPUDecoder.h +++ b/rpcs3/Emu/Cell/SPUDecoder.h @@ -1,7 +1,7 @@ #pragma once #include "Emu/Cell/SPUOpcodes.h" -#include "Emu/Cell/Decoder.h" +#include "Emu/Cell/PPCDecoder.h" #define START_OPCODES_GROUP_(group, reg) \ case(##group##): \ @@ -21,7 +21,7 @@ #define ADD_OPCODE(name, regs) case(##name##):m_op.##name####regs##; return #define ADD_NULL_OPCODE(name) ADD_OPCODE(##name##, ()) -class SPU_Decoder : public Decoder +class SPU_Decoder : public PPC_Decoder { u32 m_code; SPU_Opcodes& m_op; diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index 4937f4adf5..c74a58b80c 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -1,7 +1,7 @@ #pragma once #include "Emu/Cell/SPUOpcodes.h" -#include "Emu/Cell/DisAsm.h" +#include "Emu/Cell/PPCDisAsm.h" #include "Emu/Cell/SPUThread.h" #include "Gui/DisAsmFrame.h" #include "Emu/Memory/Memory.h" @@ -11,19 +11,19 @@ class SPU_DisAsm : public SPU_Opcodes - , public DisAsm + , public PPC_DisAsm { public: PPCThread& CPU; SPU_DisAsm() - : DisAsm(*(PPCThread*)NULL, DumpMode) + : PPC_DisAsm(*(PPCThread*)NULL, DumpMode) , CPU(*(PPCThread*)NULL) { } SPU_DisAsm(PPCThread& cpu, DisAsmModes mode = NormalMode) - : DisAsm(cpu, mode) + : PPC_DisAsm(cpu, mode) , CPU(cpu) { } diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index 51a42300a0..335f834fb7 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1233,7 +1233,7 @@ void GLGSRender::ExecCMD() if(m_set_viewport_horizontal && m_set_viewport_vertical) { glViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); - if(m_frame->GetSize() != wxSize(m_viewport_w, m_viewport_h)) + if(m_frame->GetClientSize() != wxSize(m_viewport_w, m_viewport_h)) m_frame->SetClientSize(m_viewport_w, m_viewport_h); //m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp index b7d672f286..4af1e69c9a 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp @@ -188,7 +188,7 @@ int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata) sc_sysutil.Warning("cellSysutilRegisterCallback(slot=%d, func_addr=0x%llx, userdata=0x%llx)", slot, func_addr, userdata); Emu.GetCallbackManager().m_exit_callback.Register(slot, func_addr, userdata); - wxGetApp().m_MainFrame->UpdateUI(); + wxGetApp().SendDbgCommand(DID_REGISTRED_CALLBACK); return CELL_OK; } @@ -198,7 +198,7 @@ int cellSysutilUnregisterCallback(int slot) sc_sysutil.Warning("cellSysutilUnregisterCallback(slot=%d)", slot); Emu.GetCallbackManager().m_exit_callback.Unregister(slot); - wxGetApp().m_MainFrame->UpdateUI(); + wxGetApp().SendDbgCommand(DID_UNREGISTRED_CALLBACK); return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 7466f5540b..812e50e05c 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -6,9 +6,11 @@ #include "Emu/Cell/PPCThreadManager.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" -#include "Gui/CompilerELF.h" +#include "Emu/Cell/PPUInstrTable.h" +using namespace PPU_instr; -using namespace PPU_opcodes; +static const wxString& BreakPointsDBName = "BreakPoints.dat"; +static const u16 bpdb_version = 0x1000; //SysCalls SysCallsManager; @@ -26,16 +28,9 @@ void Emulator::Init() //m_memory_viewer = new MemoryViewerPanel(wxGetApp().m_MainFrame); } -void Emulator::SetSelf(const wxString& path) +void Emulator::SetPath(const wxString& path) { m_path = path; - IsSelf = true; -} - -void Emulator::SetElf(const wxString& path) -{ - m_path = path; - IsSelf = false; } void Emulator::CheckStatus() @@ -110,6 +105,7 @@ void Emulator::Load() return; } + LoadPoints(BreakPointsDBName); PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64); thread.SetEntry(l.GetEntry()); @@ -123,22 +119,22 @@ void Emulator::Load() Memory.Write32(m_rsx_callback - 4, m_rsx_callback); mem32_t callback_data(m_rsx_callback); - callback_data += ToOpcode(ADDI) | ToRD(11) | ToRA(0) | ToIMM16(0x3ff); - callback_data += ToOpcode(SC) | ToSYS(2); - callback_data += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0); + callback_data += ADDI(11, 0, 0x3ff); + callback_data += SC(2); + callback_data += BCLR(0x10 | 0x04, 0, 0, 0); m_ppu_thr_exit = Memory.MainMem.Alloc(4 * 3); mem32_t ppu_thr_exit_data(m_ppu_thr_exit); - ppu_thr_exit_data += ToOpcode(ADDI) | ToRD(11) | ToRA(0) | ToIMM16(41); - ppu_thr_exit_data += ToOpcode(SC) | ToSYS(2); - ppu_thr_exit_data += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0); + ppu_thr_exit_data += ADDI(11, 0, 41); + ppu_thr_exit_data += SC(2); + ppu_thr_exit_data += BCLR(0x10 | 0x04, 0, 0, 0); thread.Run(); - wxGetApp().m_MainFrame->UpdateUI(); wxCriticalSectionLocker lock(m_cs_status); m_status = Ready; + wxGetApp().SendDbgCommand(DID_READY_EMU); } void Emulator::Run() @@ -156,6 +152,8 @@ void Emulator::Run() return; } + wxGetApp().SendDbgCommand(DID_START_EMU); + wxCriticalSectionLocker lock(m_cs_status); //ConLog.Write("run..."); m_status = Runned; @@ -165,7 +163,13 @@ void Emulator::Run() m_vfs.Mount("/app_home/", vfsDevice::GetRoot(m_path), new vfsLocalFile()); m_vfs.Mount(vfsDevice::GetRootPs3(m_path), vfsDevice::GetRoot(m_path), new vfsLocalFile()); - for(uint i=0; i %s", m_vfs.m_devices[i].GetPs3Path(), m_vfs.m_devices[i].GetLocalPath()); + ConLog.SkipLn(); + ConLog.Write("Mount info:"); + for(uint i=0; i %s", m_vfs.m_devices[i].GetPs3Path(), m_vfs.m_devices[i].GetLocalPath()); + } + ConLog.SkipLn(); //if(m_memory_viewer && m_memory_viewer->exit) safe_delete(m_memory_viewer); @@ -173,54 +177,57 @@ void Emulator::Run() //m_memory_viewer->Show(); //m_memory_viewer->ShowPC(); - wxGetApp().SendDbgCommand(DID_START_EMU); - wxGetApp().m_MainFrame->UpdateUI(); - - if(!m_dbg_console) m_dbg_console = new DbgConsole(); + if(!m_dbg_console) + m_dbg_console = new DbgConsole(); GetGSManager().Init(); GetCallbackManager().Init(); GetCPU().Exec(); + wxGetApp().SendDbgCommand(DID_STARTED_EMU); } void Emulator::Pause() { if(!IsRunned()) return; //ConLog.Write("pause..."); + wxGetApp().SendDbgCommand(DID_PAUSE_EMU); wxCriticalSectionLocker lock(m_cs_status); m_status = Paused; - wxGetApp().SendDbgCommand(DID_PAUSE_EMU); - wxGetApp().m_MainFrame->UpdateUI(); + wxGetApp().SendDbgCommand(DID_PAUSED_EMU); } void Emulator::Resume() { if(!IsPaused()) return; //ConLog.Write("resume..."); + wxGetApp().SendDbgCommand(DID_RESUME_EMU); wxCriticalSectionLocker lock(m_cs_status); m_status = Runned; - wxGetApp().SendDbgCommand(DID_RESUME_EMU); - wxGetApp().m_MainFrame->UpdateUI(); CheckStatus(); if(IsRunned() && Ini.CPUDecoderMode.GetValue() != 1) GetCPU().Exec(); + wxGetApp().SendDbgCommand(DID_RESUMED_EMU); } void Emulator::Stop() { if(IsStopped()) return; //ConLog.Write("shutdown..."); + + wxGetApp().SendDbgCommand(DID_STOP_EMU); { wxCriticalSectionLocker lock(m_cs_status); m_status = Stopped; } m_rsx_callback = 0; - wxGetApp().SendDbgCommand(DID_STOP_EMU); - wxGetApp().m_MainFrame->UpdateUI(); + + SavePoints(BreakPointsDBName); + m_break_points.Clear(); + m_marked_points.Clear(); GetGSManager().Close(); GetCPU().Close(); @@ -238,7 +245,63 @@ void Emulator::Stop() GetDbgCon().Close(); GetDbgCon().Clear(); } + //if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide(); + wxGetApp().SendDbgCommand(DID_STOPED_EMU); +} + +void Emulator::SavePoints(const wxString& path) +{ + wxFile f(path, wxFile::write); + + u32 break_count = m_break_points.GetCount(); + u32 marked_count = m_marked_points.GetCount(); + + f.Write(&bpdb_version, sizeof(u16)); + f.Write(&break_count, sizeof(u32)); + f.Write(&marked_count, sizeof(u32)); + + if(break_count) + { + f.Write(&m_break_points[0], sizeof(u64) * break_count); + } + + if(marked_count) + { + f.Write(&m_marked_points[0], sizeof(u64) * marked_count); + } +} + +void Emulator::LoadPoints(const wxString& path) +{ + if(!wxFileExists(path)) return; + + wxFile f(path); + + u32 break_count, marked_count; + u16 version; + f.Read(&version, sizeof(u16)); + f.Read(&break_count, sizeof(u32)); + f.Read(&marked_count, sizeof(u32)); + + if(version != bpdb_version || + (sizeof(u16) + break_count * sizeof(u64) + sizeof(u32) + marked_count * sizeof(u64) + sizeof(u32)) != f.Length()) + { + ConLog.Error("'%s' is borken", path); + return; + } + + if(break_count > 0) + { + m_break_points.SetCount(break_count); + f.Read(&m_break_points[0], sizeof(u64) * break_count); + } + + if(marked_count > 0) + { + m_marked_points.SetCount(marked_count); + f.Read(&m_marked_points[0], sizeof(u64) * marked_count); + } } Emulator Emu; \ No newline at end of file diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 7834238004..837fe2322f 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -63,6 +63,9 @@ class Emulator MemoryViewerPanel* m_memory_viewer; //ArrayF m_cpu_threads; + Array m_break_points; + Array m_marked_points; + PPCThreadManager m_thread_manager; PadManager m_pad_manager; IdManager m_id_manager; @@ -75,13 +78,11 @@ class Emulator public: wxString m_path; - bool IsSelf; Emulator(); void Init(); - void SetSelf(const wxString& path); - void SetElf(const wxString& path); + void SetPath(const wxString& path); PPCThreadManager& GetCPU() { return m_thread_manager; } PadManager& GetPadManager() { return m_pad_manager; } @@ -90,6 +91,8 @@ public: GSManager& GetGSManager() { return m_gs_manager; } CallbackManager& GetCallbackManager() { return m_callback_manager; } VFS& GetVFS() { return m_vfs; } + Array& GetBreakPoints() { return m_break_points; } + Array& GetMarkedPoints() { return m_marked_points; } void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) { @@ -115,6 +118,9 @@ public: void Resume(); void Stop(); + void SavePoints(const wxString& path); + void LoadPoints(const wxString& path); + __forceinline bool IsRunned() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Runned; } __forceinline bool IsPaused() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Paused; } __forceinline bool IsStopped() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Stopped; } diff --git a/rpcs3/Gui/CompilerELF.cpp b/rpcs3/Gui/CompilerELF.cpp index 45ec23c010..4da6cb1e21 100644 --- a/rpcs3/Gui/CompilerELF.cpp +++ b/rpcs3/Gui/CompilerELF.cpp @@ -1,27 +1,8 @@ #include "stdafx.h" #include "CompilerELF.h" +#include "Emu/Cell/PPUProgramCompiler.h" using namespace PPU_opcodes; -void Write8(wxFile& f, const u8 data) -{ - f.Write(&data, 1); -} -void Write16(wxFile& f, const u16 data) -{ - Write8(f, data >> 8); - Write8(f, data); -} -void Write32(wxFile& f, const u32 data) -{ - Write16(f, data >> 16); - Write16(f, data); -} -void Write64(wxFile& f, const u64 data) -{ - Write32(f, data >> 32); - Write32(f, data); -} - enum CompilerIDs { id_analyze_code = 0x555, @@ -34,346 +15,6 @@ wxFont GetFont(int size) return wxFont(size, wxMODERN, wxNORMAL, wxNORMAL); } -struct InstrField -{ - u32 (*To)(u32 i); -} RA = {ToRA}, RS = {ToRS}, RD = {ToRD}; - -enum MASKS -{ - MASK_ERROR = -1, - MASK_UNK, - MASK_NO_ARG, - MASK_RSD_RA_IMM16, - MASK_RA_RST_IMM16, - MASK_CRFD_RA_IMM16, - MASK_BI_BD, - MASK_BO_BI_BD, - MASK_SYS, - MASK_LL, - MASK_RA_RS_SH_MB_ME, - MASK_RA_RS_RB_MB_ME, - MASK_RA_RS_RB, - MASK_RD_RA_RB, - MASK_RST_RA_D, - MASK_RST_RA_DS, - MASK_TO_RA_IMM16, - MASK_RSD_IMM16, -}; - -enum SMASKS -{ - SMASK_ERROR = -1, - SMASK_NULL, - SMASK_AA = (1 << 0), - SMASK_LK = (1 << 1), - SMASK_OE = (1 << 2), - SMASK_RC = (1 << 3), - SMASK_L = (1 << 4), - SMASK_BO = (1 << 5), - SMASK_BI = (1 << 6), - - BO_MASK_BO4 = (1 << 0), - BO_MASK_BO3 = (1 << 1), - BO_MASK_BO2 = (1 << 2), - BO_MASK_BO1 = (1 << 3), - BO_MASK_BO0 = (1 << 4), - - BI_LT = 0, - BI_GT = 1, - BI_EQ = 2, - BI_GE = 0, - BI_LE = 1, - BI_NE = 2, -}; - -static const struct Instruction -{ - MASKS mask; - wxString name; - u32 op; - - struct - { - u32 op; - u32 from; - u32 to; - } subop; - - u32 smask; - u32 bo; - u32 bi; - -} m_instructions[] = -{ - {MASK_NO_ARG, "nop", ORI, {0}, SMASK_NULL}, - {MASK_TO_RA_IMM16, "tdi", TDI, {0}, SMASK_NULL}, - {MASK_TO_RA_IMM16, "twi", TWI, {0}, SMASK_NULL}, - //G_04 = 0x04, - {MASK_RSD_RA_IMM16, "mulli", MULLI, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "subfic", SUBFIC, {0}, SMASK_NULL}, - {MASK_CRFD_RA_IMM16, "cmplwi", CMPLI, {0}, SMASK_NULL}, - {MASK_CRFD_RA_IMM16, "cmpldi", CMPLI, {0}, SMASK_L}, - {MASK_CRFD_RA_IMM16, "cmpwi", CMPI, {0}, SMASK_NULL}, - {MASK_CRFD_RA_IMM16, "cmpdi", CMPI, {0}, SMASK_L}, - {MASK_RSD_RA_IMM16, "addic", ADDIC, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "addic.", ADDIC_, {0}, SMASK_RC}, - {MASK_RSD_RA_IMM16, "addi", ADDI, {0}, SMASK_NULL}, - {MASK_RSD_IMM16, "li", ADDI, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "addis", ADDIS, {0}, SMASK_NULL}, - - {MASK_BO_BI_BD, "bc", BC, {0}, SMASK_NULL}, - {MASK_BO_BI_BD, "bca", BC, {0}, SMASK_AA}, - {MASK_BO_BI_BD, "bcl", BC, {0}, SMASK_LK}, - {MASK_BO_BI_BD, "bcla", BC, {0}, SMASK_AA | SMASK_LK}, - {MASK_BI_BD, "bdz", BC, {0}, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO3}, - {MASK_BI_BD, "bdz-", BC, {0}, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO3}, - {MASK_BI_BD, "bdz+", BC, {0}, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO3 | BO_MASK_BO4}, - {MASK_BI_BD, "bdnz", BC, {0}, SMASK_BO, BO_MASK_BO0}, - {MASK_BI_BD, "bdnz-", BC, {0}, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1}, - {MASK_BI_BD, "bdnz+", BC, {0}, SMASK_BO, BO_MASK_BO0 | BO_MASK_BO1 | BO_MASK_BO4}, - {MASK_BI_BD, "bge", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_GE}, - {MASK_BI_BD, "ble", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_LE}, - {MASK_BI_BD, "bne", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2, BI_NE}, - {MASK_BI_BD, "bge-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_GE}, - {MASK_BI_BD, "ble-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_LE}, - {MASK_BI_BD, "bne-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3, BI_NE}, - {MASK_BI_BD, "bge+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_GE}, - {MASK_BI_BD, "ble+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_LE}, - {MASK_BI_BD, "bne+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_NE}, - {MASK_BI_BD, "bgt", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_GT}, - {MASK_BI_BD, "blt", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_LT}, - {MASK_BI_BD, "beq", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2, BI_EQ}, - {MASK_BI_BD, "bgt-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_GT}, - {MASK_BI_BD, "blt-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_LT}, - {MASK_BI_BD, "beq-", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3, BI_EQ}, - {MASK_BI_BD, "bgt+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_GT}, - {MASK_BI_BD, "blt+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_LT}, - {MASK_BI_BD, "beq+", BC, {0}, SMASK_BO | SMASK_BI, BO_MASK_BO1 | BO_MASK_BO2 | BO_MASK_BO3 | BO_MASK_BO4, BI_EQ}, - - {MASK_SYS, "sc", SC, {0}, SMASK_NULL}, - {MASK_LL, "b", B, {0}, SMASK_NULL}, - {MASK_LL, "ba", B, {0}, SMASK_AA}, - {MASK_LL, "bl", B, {0}, SMASK_LK}, - {MASK_LL, "bla", B, {0}, SMASK_AA | SMASK_LK}, - //G_13 = 0x13, - {MASK_RA_RS_SH_MB_ME, "rlwimi", RLWIMI, {0}, SMASK_NULL}, - {MASK_RA_RS_SH_MB_ME, "rlwimi.", RLWIMI, {0}, SMASK_RC}, - {MASK_RA_RS_SH_MB_ME, "rlwinm", RLWINM, {0}, SMASK_NULL}, - {MASK_RA_RS_SH_MB_ME, "rlwinm.", RLWINM, {0}, SMASK_RC}, - {MASK_RA_RS_RB_MB_ME, "rlwnm", RLWNM, {0}, SMASK_NULL}, - {MASK_RA_RS_RB_MB_ME, "rlwnm.", RLWNM, {0}, SMASK_RC}, - {MASK_RSD_RA_IMM16, "ori", ORI, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "oris", ORIS, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "xori", XORI, {0}, SMASK_NULL}, - {MASK_RSD_RA_IMM16, "xoris", XORIS, {0}, SMASK_NULL}, - {MASK_RA_RST_IMM16, "andi.", ANDI_, {0}, SMASK_RC}, - {MASK_RA_RST_IMM16, "andis.", ANDIS_, {0}, SMASK_RC}, - //G_1e = 0x1e, - {MASK_RD_RA_RB, "lwarx", G_1f, {LWARX, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "ldx", G_1f, {LDX, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "slw", G_1f, {SLW, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "slw.", G_1f, {SLW, 21, 30}, SMASK_RC}, - {MASK_RA_RS_RB, "sld", G_1f, {SLD, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "sld.", G_1f, {SLD, 21, 30}, SMASK_RC}, - {MASK_RA_RS_RB, "and", G_1f, {AND, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "and.", G_1f, {AND, 21, 30}, SMASK_RC}, - {MASK_RD_RA_RB, "subf", G_1f, {SUBF, 21, 30}, SMASK_NULL}, - {MASK_RD_RA_RB, "subf.", G_1f, {SUBF, 21, 30}, SMASK_RC}, - {MASK_RD_RA_RB, "subfo", G_1f, {SUBF, 21, 30}, SMASK_OE}, - {MASK_RD_RA_RB, "subfo.", G_1f, {SUBF, 21, 30}, SMASK_OE | SMASK_RC}, - {MASK_RA_RS_RB, "andc", G_1f, {ANDC, 21, 30}, SMASK_NULL}, - {MASK_RA_RS_RB, "andc.", G_1f, {ANDC, 21, 30}, SMASK_RC}, - {MASK_RD_RA_RB, "mulhd", G_1f, {MULHD, 21, 30}, SMASK_NULL}, - {MASK_RD_RA_RB, "mulhd.", G_1f, {MULHD, 21, 30}, SMASK_RC}, - {MASK_RD_RA_RB, "mulhw", G_1f, {MULHW, 21, 30}, SMASK_NULL}, - {MASK_RD_RA_RB, "mulhw.", G_1f, {MULHW, 21, 30}, SMASK_RC}, - {MASK_RD_RA_RB, "ldarx", G_1f, {LDARX, 21, 30}, SMASK_NULL}, - {MASK_RD_RA_RB, "lbzx", G_1f, {LBZX, 21, 30}, SMASK_NULL}, - - {MASK_RST_RA_D, "lwz", LWZ, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lwzu", LWZU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lbz", LBZ, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lbzu", LBZU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "stw", STW, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "stwu", STWU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "stb", STB, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "stbu", STBU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lhz", LHZ, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lhzu", LHZU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lha", LHA, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "lhau", LHAU, {0}, SMASK_NULL}, - {MASK_RST_RA_D, "sth", STH, {0}, SMASK_NULL}, - //{0, "lmw", LMW, 0, false, false}, - //LFS = 0x30, - //LFSU = 0x31, - //LFD = 0x32, - //LFDU = 0x33, - //STFS = 0x34, - //STFD = 0x36, - //LFQ = 0x38, - //LFQU = 0x39, - //G_3a = 0x3a, - //G_3b = 0x3b, - //G_3e = 0x3e, - //G_3f = 0x3f, - {MASK_UNK, "unk", 0, {0}, SMASK_NULL}, -}, m_error_instr = {MASK_ERROR, "err", 0, {0}, SMASK_ERROR}; -static const u32 instr_count = WXSIZEOF(m_instructions); - -enum ArgType -{ - ARG_ERR = 0, - ARG_NUM = 1 << 0, - ARG_NUM16 = 1 << 1, - ARG_TXT = 1 << 2, - ARG_REG_R = 1 << 3, - ARG_REG_F = 1 << 4, - ARG_REG_V = 1 << 5, - ARG_REG_CR = 1 << 6, - ARG_BRANCH = 1 << 7, - ARG_INSTR = 1 << 8, - ARG_IMM = ARG_NUM | ARG_NUM16 | ARG_BRANCH, -}; - -struct Arg -{ - wxString string; - u32 value; - ArgType type; - - Arg(const wxString& _string, const u32 _value = 0, const ArgType _type = ARG_ERR) - : string(_string) - , value(_value) - , type(_type) - { - } -}; - -Instruction GetInstruction(const wxString& str) -{ - for(u32 i=0; i& arr) -{ - if(instr.mask == MASK_ERROR) return 0; - - u32 code = - ToOE(instr.smask & SMASK_OE) | ToRC(instr.smask & SMASK_RC) | - ToAA(instr.smask & SMASK_AA) | ToLK(instr.smask & SMASK_LK) | - ToL (instr.smask & SMASK_L ); - - if(instr.smask & SMASK_BO) code |= ToBO(instr.bo); - if(instr.smask & SMASK_BI) code |= ToBI(instr.bi); - - code |= ToOpcode(instr.op); - - if(instr.subop.from < instr.subop.to) code |= SetField(instr.subop.op, instr.subop.from, instr.subop.to); - - switch(instr.mask) - { - case MASK_RSD_RA_IMM16: - return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToIMM16(arr[2].value); - case MASK_RA_RST_IMM16: - return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToIMM16(arr[2].value); - case MASK_CRFD_RA_IMM16: - return code | ToCRFD(arr[0].value) | ToRA(arr[1].value) | ToIMM16(arr[2].value); - case MASK_BO_BI_BD: - return code | ToBO(arr[0].value) | ToBI(arr[1].value) | ToBD(arr[2].value); - case MASK_BI_BD: - return code | ToBI(arr[0].value * 4) | ToBD(arr[1].value); - case MASK_SYS: - return code | ToSYS(arr[0].value); - case MASK_LL: - return code | ToLL(arr[0].value); - case MASK_RA_RS_SH_MB_ME: - return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToSH(arr[2].value) | ToMB(arr[3].value) | ToME(arr[4].value); - case MASK_RA_RS_RB_MB_ME: - return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToRB(arr[2].value) | ToMB(arr[3].value) | ToME(arr[4].value); - case MASK_RA_RS_RB: - return code | ToRA(arr[0].value) | ToRS(arr[1].value) | ToRB(arr[2].value); - case MASK_RD_RA_RB: - return code | ToRD(arr[0].value) | ToRA(arr[1].value) | ToRB(arr[2].value); - case MASK_RST_RA_D: - return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToD(arr[2].value); - case MASK_RST_RA_DS: - return code | ToRS(arr[0].value) | ToRA(arr[1].value) | ToDS(arr[2].value); - case MASK_TO_RA_IMM16: - return code | ToTO(arr[0].value) | ToRA(arr[1].value) | ToIMM16(arr[2].value); - case MASK_RSD_IMM16: - return code | ToRS(arr[0].value) | ToIMM16(arr[1].value); - - case MASK_UNK: - return arr[0].value; - case MASK_NO_ARG: - return code; - } - - return 0; -} - -ArrayF sections_list; -u32 section_name_offs = 0; -u32 section_offs = 0; - -SectionInfo::SectionInfo(const wxString& _name) : name(_name) -{ - memset(&shdr, 0, sizeof(Elf64_Shdr)); - - section_num = sections_list.Add(this); - - shdr.sh_offset = section_offs; - shdr.sh_name = section_name_offs; - - section_name_offs += name.Len() + 1; -} - -void SectionInfo::SetDataSize(u32 size, u32 align) -{ - if(align) shdr.sh_addralign = align; - if(shdr.sh_addralign) size = Memory.AlignAddr(size, shdr.sh_addralign); - - if(code.GetCount()) - { - for(u32 i=section_num + 1; iGetHWND(), WM_VSCROLL, SB_BOTTOM, 0); @@ -573,10 +214,12 @@ void CompilerELF::OnUpdate(wxCommandEvent& event) asm_list->Freeze(); asm_list->SetStyle(0, asm_list->GetValue().Len(), wxTextAttr("Black")); + /* for(u32 i=0; i m_code; - bool m_end_args; - Array m_branches; - s32 m_branch_pos; - u32 m_text_addr; - - struct SpData - { - wxString m_data; - u32 m_addr; - - SpData(const wxString& data, u32 addr) - : m_data(data) - , m_addr(addr) - { - } - }; - - Array m_sp_string; - - CompileProgram(const wxString& asm_, wxTextCtrl* asm_list, wxTextCtrl* hex_list, wxTextCtrl* err_list, bool analyze) - : m_asm(asm_) - , m_asm_list(*asm_list) - , m_hex_list(*hex_list) - , m_err_list(*err_list) - , m_analyze(analyze) - , p(0) - , m_error(false) - , m_line(1) - , m_end_args(false) - , m_branch_pos(0) - , m_text_addr(0) - { - } - - static bool IsSkip(const char c) { return c == ' ' || c == '\t'; } - static bool IsCommit(const char c) { return c == '#'; } - bool IsEnd() const { return p >= m_asm.Len(); } - bool IsEndLn(const char c) const { return c == '\n' || p - 1 >= m_asm.Len(); } - - char NextChar() { return *m_asm(p++, 1); } - void NextLn() { while( !IsEndLn(NextChar()) ); if(!IsEnd()) m_line++; } - void EndLn() - { - NextLn(); - p--; - m_line--; - } - - void FirstChar() - { - p = 0; - m_line = 1; - m_branch_pos = 0; - } - - void PrevArg() - { - while( --p >= 0 && (IsSkip(m_asm[p]) || m_asm[p] == ',')); - while( --p >= 0 && !IsSkip(m_asm[p]) && !IsEndLn(m_asm[p]) ); - if(IsEndLn(m_asm[p])) p++; - } - - bool GetOp(wxString& result) - { - s64 from = -1; - - for(;;) - { - const char cur_char = NextChar(); - - const bool skip = IsSkip(cur_char); - const bool commit = IsCommit(cur_char); - const bool endln = IsEndLn(cur_char); - - if(endln) p--; - - if(from == -1) - { - if(endln || commit) return false; - if(!skip) from = p - 1; - continue; - } - - if(skip || endln || commit) - { - const s64 to = (endln ? p : p - 1) - from; - result = m_asm(from, to); - - return true; - } - } - - return false; - } - - int GetArg(wxString& result, bool func = false) - { - s64 from = -1; - - for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) - { - const bool skip = IsSkip(cur_char); - const bool commit = IsCommit(cur_char); - const bool endln = IsEndLn(cur_char); - const bool end = cur_char == ',' || (func && cur_char == ']'); - - if(endln) p--; - - if(from == -1) - { - if(endln || commit || end) return 0; - if(!skip) from = p - 1; - continue; - } - - const bool text = m_asm[from] == '"'; - const bool end_text = cur_char == '"'; - - if((text ? end_text : (skip || commit || end)) || endln) - { - if(text && p > 2 && m_asm[p - 2] == '\\' && (p <= 3 || m_asm[p - 3] != '\\')) - { - continue; - } - - if(text && !end_text) - { - WriteError(wxString::Format("'\"' not found.")); - m_error = true; - } - - const s64 to = ((endln || text) ? p : p - 1) - from; - int ret = 1; - - if(skip || text) - { - for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) - { - const bool skip = IsSkip(cur_char); - const bool commit = IsCommit(cur_char); - const bool endln = IsEndLn(cur_char); - const bool end = cur_char == ',' || (func && cur_char == ']'); - - if(skip) continue; - if(end) break; - - if(commit) - { - EndLn(); - ret = -1; - break; - } - - if(endln) - { - p--; - break; - } - - WriteError(wxString::Format("Bad symbol '%c'", cur_char)); - m_error = true; - break; - } - } - - result = m_asm(from, to); - - if(text) - { - for(u32 pos = 0; (s32)(pos = result.find('\\', pos)) >= 0;) - { - if(pos + 1 < result.Len() && result[pos + 1] == '\\') - { - pos += 2; - continue; - } - - const char v = result[pos + 1]; - switch(v) - { - case 'n': result = result(0, pos) + '\n' + result(pos+2, result.Len()-(pos+2)); break; - case 'r': result = result(0, pos) + '\r' + result(pos+2, result.Len()-(pos+2)); break; - case 't': result = result(0, pos) + '\t' + result(pos+2, result.Len()-(pos+2)); break; - } - - pos++; - } - } - - return ret; - } - } - - return 0; - } - - bool CheckEnd(bool show_err = true) - { - if(m_error) - { - NextLn(); - return false; - } - - while(true) - { - const char cur_char = NextChar(); - const bool skip = IsSkip(cur_char); - const bool commit = IsCommit(cur_char); - const bool endln = IsEndLn(cur_char); - - if(skip) continue; - - if(commit) - { - NextLn(); - return true; - } - - if(endln) - { - p--; - NextLn(); - return true; - } - - WriteError(wxString::Format("Bad symbol '%c'", cur_char)); - NextLn(); - return false; - } - - return false; - } - - void WriteError(const wxString& error) - { - m_err_list.WriteText(wxString::Format("line %lld: %s\n", m_line, error)); - } - - Array m_args; - u32 m_cur_arg; - - void DetectArgInfo(Arg& arg) - { - const wxString str = arg.string; - - if(str.Len() <= 0) - { - arg.type = ARG_ERR; - return; - } - - if(GetInstruction(str).mask != MASK_ERROR) - { - arg.type = ARG_INSTR; - return; - } - - if(str.Len() > 1) - { - for(u32 i=0; i '9') - { - arg.type = ARG_ERR; - return; - } - } - - u32 reg; - sscanf(str(1, str.Len() - 1), "%d", ®); - - if(reg >= 32) - { - arg.type = ARG_ERR; - return; - } - - switch(str[0]) - { - case 'r': arg.type = ARG_REG_R; break; - case 'f': arg.type = ARG_REG_F; break; - case 'v': arg.type = ARG_REG_V; break; - default: arg.type = ARG_ERR; break; - } - - arg.value = reg; - return; - - case 'c': - if(str.Len() > 2 && str[1] == 'r') - { - for(u32 i=2; i '9') - { - arg.type = ARG_ERR; - return; - } - } - - u32 reg; - sscanf(str, "cr%d", ®); - - if(reg < 8) - { - arg.type = ARG_REG_CR; - arg.value = reg; - } - else - { - arg.type = ARG_ERR; - } - - return; - } - break; - - case '"': - if(str.Len() < 2) - { - arg.type = ARG_ERR; - return; - } - - if(str[str.Len() - 1] != '"') - { - arg.type = ARG_ERR; - return; - } - - arg.string = str(1, str.Len() - 2); - arg.type = ARG_TXT; - return; - } - - if(str.Len() > 2 && str(0, 2).Cmp("0x") == 0) - { - for(u32 i=2; i= '0' && str[i] <= '9') || - (str[i] >= 'a' && str[i] <= 'f') || - (str[i] >= 'A' && str[i] <= 'F') - ) continue; - - arg.type = ARG_ERR; - return; - } - - u32 val; - sscanf(str, "0x%x", &val); - - arg.type = ARG_NUM16; - arg.value = val; - return; - } - - for(u32 i= str[0] == '-' ? 1 : 0; i '9') - { - arg.type = ARG_ERR; - return; - } - } - - u32 val; - sscanf(str, "%d", &val); - - arg.type = ARG_NUM; - arg.value = val; - } - - void LoadArgs() - { - m_args.Clear(); - m_cur_arg = 0; - - wxString str; - while(int r = GetArg(str)) - { - Arg* arg = new Arg(str); - DetectArgInfo(*arg); - m_args.Add(arg); - if(r == -1) break; - } - - m_end_args = m_args.GetCount() > 0; - } - - u32 GetBranchValue(const wxString& branch) - { - for(u32 i=0; i= 0) return m_text_addr + m_branches[i].m_pos * 4; - - return m_branches[i].m_addr; - } - - return 0; - } - - bool SetNextArgType(u32 types, bool show_err = true) - { - if(m_error) return false; - - if(m_cur_arg >= m_args.GetCount()) - { - if(show_err) - { - WriteError(wxString::Format("%d arg not found", m_cur_arg + 1)); - m_error = true; - } - - return false; - } - - const Arg& arg = m_args[m_cur_arg]; - - if(arg.type & types) - { - m_cur_arg++; - return true; - } - - if(show_err) - { - WriteError(wxString::Format("Bad arg '%s'", arg.string)); - m_error = true; - } - - return false; - } - - bool SetNextArgBranch(u8 aa, bool show_err = true) - { - const u32 pos = m_cur_arg; - const bool ret = SetNextArgType(ARG_BRANCH | ARG_IMM, show_err); - - if(!aa && pos < m_args.GetCount()) - { - switch(m_args[pos].type) - { - case ARG_NUM: - m_args[pos].value += m_text_addr + m_branch_pos * 4; - break; - - case ARG_BRANCH: - m_args[pos].value -= m_text_addr + m_branch_pos * 4; - break; - } - } - - return ret; - } - - bool IsBranchOp(const wxString& op) const - { - return op.Len() > 1 && op[op.Len() - 1] == ':'; - } - - bool IsFuncOp(const wxString& op) const - { - return op.Len() >= 1 && op[0] == '['; - } - - enum SP_TYPE - { - SP_ERR, - SP_INT, - SP_STRING, - SP_STRLEN, - SP_BUF, - SP_SRL, - SP_SRR, - SP_MUL, - SP_DIV, - SP_ADD, - SP_SUB, - SP_AND, - SP_OR, - SP_XOR, - SP_NOT, - SP_NOR, - }; - - SP_TYPE GetSpType(const wxString& op) const - { - if(op.Cmp(".int") == 0) return SP_INT; - if(op.Cmp(".string") == 0) return SP_STRING; - if(op.Cmp(".strlen") == 0) return SP_STRLEN; - if(op.Cmp(".buf") == 0) return SP_BUF; - if(op.Cmp(".srl") == 0) return SP_SRL; - if(op.Cmp(".srr") == 0) return SP_SRR; - if(op.Cmp(".mul") == 0) return SP_MUL; - if(op.Cmp(".div") == 0) return SP_DIV; - if(op.Cmp(".add") == 0) return SP_ADD; - if(op.Cmp(".sub") == 0) return SP_SUB; - if(op.Cmp(".and") == 0) return SP_AND; - if(op.Cmp(".or") == 0) return SP_OR; - if(op.Cmp(".xor") == 0) return SP_XOR; - if(op.Cmp(".not") == 0) return SP_NOT; - if(op.Cmp(".nor") == 0) return SP_NOR; - - return SP_ERR; - } - - wxString GetSpStyle(const SP_TYPE sp) const - { - switch(sp) - { - case SP_INT: - case SP_STRING: - case SP_STRLEN: - case SP_NOT: - return "[dst, src]"; - - case SP_BUF: - return "[dst, size]"; - - case SP_SRL: - case SP_SRR: - case SP_MUL: - case SP_DIV: - case SP_ADD: - case SP_SUB: - case SP_AND: - case SP_OR: - case SP_XOR: - case SP_NOR: - return "[dst, src1, src2]"; - } - - return "error"; - } - - bool IsSpOp(const wxString& op) const - { - return GetSpType(op) != SP_ERR; - } - - Branch& GetBranch(const wxString& name) - { - for(u32 i=0; i 0 && m_asm[p] != '[') p--; - p++; - - wxString dst; - if(!GetArg(dst)) - { - if(m_analyze) m_hex_list.WriteText("error\n"); - WriteError(wxString::Format("dst not found. style: %s", GetSpStyle(sp))); - m_error = true; - NextLn(); - return; - } - - Arg a_dst(dst); - DetectArgInfo(a_dst); - - Branch* dst_branch = NULL; - - switch(a_dst.type) - { - case ARG_BRANCH: - { - Branch& b = GetBranch(dst); - if(b.m_addr >= 0 && b.m_id < 0 && b.m_pos < 0) dst_branch = &b; - } - break; - - case ARG_ERR: - { - m_branches.Move(new Branch(wxEmptyString, -1, 0)); - dst_branch = &m_branches[m_branches.GetCount() - 1]; - } - break; - } - - if(!dst_branch) - { - if(m_analyze) m_hex_list.WriteText("error\n"); - WriteError(wxString::Format("bad dst type. style: %s", GetSpStyle(sp))); - m_error = true; - NextLn(); - return; - } - - switch(sp) - { - case SP_INT: - case SP_STRING: - case SP_STRLEN: - case SP_BUF: - case SP_NOT: - { - wxString src1; - if(!GetArg(src1, true)) - { - if(m_analyze) m_hex_list.WriteText("error\n"); - WriteError(wxString::Format("src not found. style: %s", GetSpStyle(sp))); - m_error = true; - NextLn(); - return; - } - - Arg a_src1(src1); - DetectArgInfo(a_src1); - - if(sp == SP_STRLEN - ? ~(ARG_TXT | ARG_BRANCH) & a_src1.type - : sp == SP_STRING - ? ~ARG_TXT & a_src1.type - : ~(ARG_IMM | ARG_BRANCH) & a_src1.type) - { - if(m_analyze) m_hex_list.WriteText("error\n"); - WriteError(wxString::Format("bad src type. style: %s", GetSpStyle(sp))); - m_error = true; - NextLn(); - return; - } - - if(m_asm[p - 1] != ']') - { - if(m_analyze) m_hex_list.WriteText("error\n"); - WriteError(wxString::Format("']' not found. style: %s", GetSpStyle(sp))); - m_error = true; - NextLn(); - return; - } - - if(!CheckEnd()) - { - if(m_analyze) m_hex_list.WriteText("error\n"); - return; - } - - if(sp == SP_STRING) - { - src1 = src1(1, src1.Len()-2); - bool founded = false; - - for(u32 i=0; i> a_src2.value); break; - case SP_MUL: *dst_branch = Branch(dst, -1, a_src1.value * a_src2.value); break; - case SP_DIV: *dst_branch = Branch(dst, -1, a_src1.value / a_src2.value); break; - case SP_ADD: *dst_branch = Branch(dst, -1, a_src1.value + a_src2.value); break; - case SP_SUB: *dst_branch = Branch(dst, -1, a_src1.value - a_src2.value); break; - case SP_AND: *dst_branch = Branch(dst, -1, a_src1.value & a_src2.value); break; - case SP_OR: *dst_branch = Branch(dst, -1, a_src1.value | a_src2.value); break; - case SP_XOR: *dst_branch = Branch(dst, -1, a_src1.value ^ a_src2.value); break; - case SP_NOR: *dst_branch = Branch(dst, -1, ~(a_src1.value | a_src2.value)); break; - } - } - break; - } - - if(m_analyze) m_hex_list.WriteText("\n"); - } - - void Compile() - { - m_err_list.Freeze(); - m_err_list.Clear(); - - if(m_analyze) - { - m_hex_list.Freeze(); - m_hex_list.Clear(); - } - - m_code.Clear(); - - for(u32 i=0; i m_imports; - - Module(const wxString& name, u32 import) : m_name(name) - { - Add(import); - } - - void Add(u32 import) - { - m_imports.AddCpy(import); - } - - void Clear() - { - m_name.Clear(); - m_imports.Clear(); - } - }; - - Array modules; - - FirstChar(); - while(!IsEnd()) - { - wxString op; - if(!GetOp(op) || !IsFuncOp(op)) - { - NextLn(); - continue; - } - - while(p > 0 && m_asm[p] != '[') p--; - p++; - - wxString module, name, id; - - if(!GetArg(module)) - { - WriteError("module not found. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - Arg a_module(module); - DetectArgInfo(a_module); - - if(~ARG_ERR & a_module.type) - { - WriteError("bad module type. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - if(!GetArg(name)) - { - WriteError("name not found. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - Arg a_name(name); - DetectArgInfo(a_name); - - if(~ARG_ERR & a_name.type) - { - WriteError("bad name type. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - if(!GetArg(id, true)) - { - WriteError("id not found. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - Arg a_id(id); - DetectArgInfo(a_id); - - if(~ARG_IMM & a_id.type) - { - WriteError("bad id type. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - if(m_asm[p - 1] != ']') - { - WriteError("']' not found. style: [module, name, id]"); - m_error = true; - NextLn(); - continue; - } - - if(!CheckEnd()) continue; - - m_branches.Move(new Branch(name, a_id.value, 0)); - const u32 import = m_branches.GetCount() - 1; - - bool founded = false; - for(u32 i=0; i 0) - { - switch(m_args[0].type) - { - case ARG_REG_CR: - SetNextArgType(ARG_REG_R); - break; - - case ARG_REG_R: - m_args.Move(0, new Arg("cr0", 0, ARG_REG_CR)); - break; - } - } - - SetNextArgType(ARG_IMM); - break; - - case MASK_BO_BI_BD: - SetNextArgType(ARG_IMM); - SetNextArgType(ARG_REG_CR); - SetNextArgBranch(instr.smask & SMASK_AA); - break; - - case MASK_BI_BD: - if(!SetNextArgType(ARG_REG_CR, false)) - { - m_args.Move(0, new Arg("cr0", 0, ARG_REG_CR)); - } - SetNextArgBranch(instr.smask & SMASK_AA); - break; - - case MASK_SYS: - if(!SetNextArgType(ARG_IMM, false)) m_args.Move(new Arg("2", 2, ARG_IMM)); - break; - - case MASK_LL: - SetNextArgBranch(instr.smask & SMASK_AA); - break; - - case MASK_RA_RS_SH_MB_ME: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - SetNextArgType(ARG_IMM); - SetNextArgType(ARG_IMM); - break; - - case MASK_RA_RS_RB_MB_ME: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - SetNextArgType(ARG_IMM); - break; - - case MASK_RA_RS_RB: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - break; - - case MASK_RD_RA_RB: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - break; - - case MASK_RST_RA_D: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - break; - - case MASK_RST_RA_DS: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - break; - - case MASK_TO_RA_IMM16: - SetNextArgType(ARG_IMM); - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - break; - - case MASK_RSD_IMM16: - SetNextArgType(ARG_REG_R); - SetNextArgType(ARG_IMM); - break; - } - - CheckEnd(); - - if(m_error) - { - if(m_analyze) - { - m_hex_list.WriteText("error\n"); - m_error = false; - continue; - } - - break; - } - - const u32 code = CompileInstruction(instr, m_args); - - if(m_analyze) m_hex_list.WriteText(wxString::Format("0x%08x\n", code)); - - if(!m_analyze) m_code.AddCpy(code); - - m_branch_pos++; - } - - if(!m_analyze && !m_error) - { - s_opd.sh_size = Memory.AlignAddr(s_opd.sh_size, s_opd.sh_addralign); - section_offset += s_opd.sh_size; - - const u32 prog_load_1_end = section_offset; - - Elf64_Shdr s_shstrtab; - memset(&s_shstrtab, 0, sizeof(Elf64_Shdr)); - s_shstrtab.sh_addralign = 1; - section_offset = Memory.AlignAddr(section_offset, s_shstrtab.sh_addralign); - s_shstrtab.sh_name = section_name_offset; - s_shstrtab.sh_type = 3; - s_shstrtab.sh_offset = section_offset; - s_shstrtab.sh_addr = 0; - sections_names.Add(".shstrtab"); - section_name_offset += wxString(".shstrtab").Len() + 1; - s_shstrtab.sh_size = section_name_offset; - section_offset += s_shstrtab.sh_size; - - wxFile f("compiled.elf", wxFile::write); - - elf_info.e_magic = 0x7F454C46; - elf_info.e_class = 2; //ELF64 - elf_info.e_data = 2; - elf_info.e_curver = 1; //ver 1 - elf_info.e_os_abi = 0x66; //Cell OS LV-2 - elf_info.e_abi_ver = 0; - elf_info.e_type = 2; //EXEC (Executable file) - elf_info.e_machine = MACHINE_PPC64; //PowerPC64 - elf_info.e_version = 1; //ver 1 - elf_info.e_flags = 0x0; - elf_info.e_shoff = Memory.AlignAddr(section_offset, 4); - - u8* opd_data = new u8[s_opd.sh_size]; - u32 entry_point = s_text.sh_addr; - for(u32 i=0; i> 16)); //oris r12,r12,addr>>16 - Write32(f, ToOpcode(LWZ) | ToRD(12) | ToRA(12) | ToIMM16(addr)); //lwz r12,addr&0xffff(r12) - Write32(f, 0xf8410028); //std r2,40(r1) - Write32(f, ToOpcode(LWZ) | ToRD(0) | ToRA(12) | ToIMM16(0)); //lwz r0,0(r12) - Write32(f, ToOpcode(LWZ) | ToRD(2) | ToRA(12) | ToIMM16(4)); //lwz r2,4(r12) - Write32(f, 0x7c0903a6); //mtctr r0 - Write32(f, 0x4e800420); //bctr - } - - f.Seek(s_lib_stub_top.sh_offset); - f.Seek(s_lib_stub_top.sh_size, wxFromCurrent); - - f.Seek(s_lib_stub.sh_offset); - for(u32 i=0, nameoffs=4, dataoffs=0; i= text.Len() || text[i + op.Len()] == '\n' || - CompileProgram::IsSkip(text[i + op.Len()])) return i; - } - } - - return -1; -} - void CompilerELF::SetTextStyle(const wxString& text, const wxColour& color, bool bold) { for(int p=0; (p = asm_list->GetValue().find(text, p)) >= 0; p += text.Len()) @@ -2573,22 +409,16 @@ void CompilerELF::SetTextStyle(const wxString& text, const wxColour& color, bool void CompilerELF::SetOpStyle(const wxString& text, const wxColour& color, bool bold) { + /* for(int p=0; (p = FindOp(asm_list->GetValue(), text, p)) >= 0; p += text.Len()) { asm_list->SetStyle(p, p + text.Len(), wxTextAttr(color, wxNullColour, wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL))); } + */ } void CompilerELF::DoAnalyzeCode(bool compile) { - CompileProgram(asm_list->GetValue(), asm_list, hex_list, err_list, !compile).Compile(); - - /* - return; - - MTProgressDialog* progress_dial = - new MTProgressDialog(this, wxDefaultSize, "Analyze code...", "Loading...", wxArrayLong(), 1); - (new AnalyzeThread())->DoAnalyze(compile, progress_dial, this); - */ -} \ No newline at end of file + CompilePPUProgram(asm_list->GetValue(), "compiled.elf", asm_list, hex_list, err_list, !compile).Compile(); +} diff --git a/rpcs3/Gui/CompilerELF.h b/rpcs3/Gui/CompilerELF.h index cf078bc29d..55fac74790 100644 --- a/rpcs3/Gui/CompilerELF.h +++ b/rpcs3/Gui/CompilerELF.h @@ -5,38 +5,6 @@ #include "Loader/ELF64.h" #include -void Write8(wxFile& f, const u8 data); -void Write16(wxFile& f, const u16 data); -void Write32(wxFile& f, const u32 data); -void Write64(wxFile& f, const u64 data); - -struct SectionInfo -{ - Elf64_Shdr shdr; - wxString name; - Array code; - u32 section_num; - - SectionInfo(const wxString& name); - ~SectionInfo(); - - void SetDataSize(u32 size, u32 align = 0); -}; - -struct ProgramInfo -{ - Array code; - Elf64_Phdr phdr; - bool is_preload; - - ProgramInfo() - { - is_preload = false; - code.Clear(); - memset(&phdr, 0, sizeof(Elf64_Phdr)); - } -}; - class CompilerELF : public FrameBase { wxAuiManager m_aui_mgr; @@ -78,42 +46,3 @@ public: void UpdateStatus(int offset=0); }; - -static u32 SetField(u32 src, u32 from, u32 to) -{ - return (src & ((1 << ((to - from) + 1)) - 1)) << (31 - to); -} - -static u32 SetField(s32 src, u32 p) -{ - return (src & 0x1) << (31 - p); -} - -static u32 ToOpcode(u32 i) { return SetField(i, 0, 5); } -static u32 ToRS(u32 i) { return SetField(i, 6, 10); } -static u32 ToRD(u32 i) { return SetField(i, 6, 10); } -static u32 ToRA(u32 i) { return SetField(i, 11, 15); } -static u32 ToRB(u32 i) { return SetField(i, 16, 20); } -static u32 ToLL(u32 i) { return i & 0x03fffffc; } -static u32 ToAA(u32 i) { return SetField(i, 30); } -static u32 ToLK(u32 i) { return SetField(i, 31); } -static u32 ToIMM16(s32 i) { return SetField(i, 16, 31); } -static u32 ToD(s32 i) { return SetField(i, 16, 31); } -static u32 ToDS(s32 i) -{ - if(i < 0) return ToD(i + 1); - return ToD(i); -} -static u32 ToSYS(u32 i) { return SetField(i, 6, 31); } -static u32 ToBF(u32 i) { return SetField(i, 6, 10); } -static u32 ToBO(u32 i) { return SetField(i, 6, 10); } -static u32 ToBI(u32 i) { return SetField(i, 11, 15); } -static u32 ToBD(u32 i) { return i & 0xfffc; } -static u32 ToMB(u32 i) { return SetField(i, 21, 25); } -static u32 ToME(u32 i) { return SetField(i, 26, 30); } -static u32 ToSH(u32 i) { return SetField(i, 16, 20); } -static u32 ToRC(u32 i) { return SetField(i, 31); } -static u32 ToOE(u32 i) { return SetField(i, 21); } -static u32 ToL(u32 i) { return SetField(i, 10); } -static u32 ToCRFD(u32 i) { return SetField(i, 6, 8); } -static u32 ToTO(u32 i) { return SetField(i, 6, 10); } \ No newline at end of file diff --git a/rpcs3/Gui/DisAsmFrame.cpp b/rpcs3/Gui/DisAsmFrame.cpp index 808ec657f6..5feadd3490 100644 --- a/rpcs3/Gui/DisAsmFrame.cpp +++ b/rpcs3/Gui/DisAsmFrame.cpp @@ -113,8 +113,8 @@ bool ElfType64 = false; class DumperThread : public ThreadBase { volatile uint id; - DisAsm* disasm; - Decoder* decoder; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; volatile bool* done; volatile u8 cores; MTProgressDialog* prog_dial; @@ -338,8 +338,8 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event)) default: ConLog.Error("Corrupted ELF!"); return; } - DisAsm* disasm; - Decoder* decoder; + PPC_DisAsm* disasm; + PPC_Decoder* decoder; if(Emu.GetCPU().GetThreads()[0].IsSPU()) { diff --git a/rpcs3/Gui/GameViewer.cpp b/rpcs3/Gui/GameViewer.cpp index c559a41820..8ed62a0964 100644 --- a/rpcs3/Gui/GameViewer.cpp +++ b/rpcs3/Gui/GameViewer.cpp @@ -99,6 +99,6 @@ void GameViewer::DClick(wxListEvent& event) } Emu.Stop(); - Emu.SetElf(path); + Emu.SetPath(path); Emu.Run(); } \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index b8e18e8e98..9b951d4592 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -2,8 +2,6 @@ #include "InterpreterDisAsm.h" static const int show_lines = 30; -static const wxString& BreakPointsDBName = "BreakPoints.dat"; -static const u16 bpdb_version = 0x1000; u32 FixPc(const u32 pc) { @@ -85,73 +83,11 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu) m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this); WriteRegs(); - - Load(BreakPointsDBName); } InterpreterDisAsmFrame::~InterpreterDisAsmFrame() { ThreadBase::Stop(); - Save(BreakPointsDBName); -} - -void InterpreterDisAsmFrame::Save(const wxString& path) -{ - wxFile f(path, wxFile::write); - u32 break_count = m_break_points.GetCount(); - u32 marked_count = markedPC.GetCount(); - f.Write(&bpdb_version, sizeof(u16)); - f.Write(&break_count, sizeof(u32)); - f.Write(&marked_count, sizeof(u32)); - - for(u32 i=0; i 0) - { - m_break_points.SetCount(break_count); - - for(u32 i=0; i 0) - { - markedPC.SetCount(marked_count); - - for(u32 i=0; i mpc) remove_markedPC[i]--; } - markedPC.RemoveAt(mpc); + Emu.GetMarkedPoints().RemoveAt(mpc); } m_list->SetColumnWidth(0, -1); @@ -272,33 +208,50 @@ void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event) PPCThread* thr = (PPCThread*)event.GetClientData(); event.Skip(); - if(!thr || thr->GetId() != CPU.GetId()) return; - - switch(event.GetId()) + if(!thr) { - case DID_EXEC_THREAD: - case DID_REMOVE_THREAD: - case DID_RESUME_THREAD: - m_btn_step->Disable(); - m_btn_run->Disable(); - m_btn_pause->Enable(); - break; + switch(event.GetId()) + { + case DID_STOP_EMU: + case DID_PAUSE_EMU: + DoUpdate(); + break; + } + } + else if(thr->GetId() == CPU.GetId()) + { + switch(event.GetId()) + { + case DID_PAUSE_THREAD: + m_btn_run->Enable(); + m_btn_step->Enable(); + m_btn_pause->Disable(); - case DID_START_THREAD: - case DID_CREATE_THREAD: - case DID_PAUSE_THREAD: - case DID_STOP_THREAD: - m_btn_step->Enable(!Emu.IsReady()); - m_btn_run->Enable(!Emu.IsReady()); - m_btn_pause->Disable(); + case DID_CREATE_THREAD: + DoUpdate(); + break; - DoUpdate(); - break; - case DID_STOP_EMU: - case DID_PAUSE_EMU: - DoUpdate(); - break; + case DID_START_THREAD: + case DID_EXEC_THREAD: + case DID_RESUME_THREAD: + m_btn_run->Disable(); + m_btn_step->Disable(); + m_btn_pause->Enable(); + + if(event.GetId() == DID_START_THREAD) + { + DoUpdate(); + } + break; + + case DID_REMOVE_THREAD: + case DID_STOP_THREAD: + m_btn_run->Disable(); + m_btn_step->Disable(); + m_btn_pause->Disable(); + break; + } } } @@ -331,7 +284,7 @@ void InterpreterDisAsmFrame::Show_Val(wxCommandEvent& WXUNUSED(event)) { u64 pc = CPU.PC; sscanf(p_pc->GetLabel(), "%llx", &pc); - remove_markedPC.AddCpy(markedPC.AddCpy(pc)); + remove_markedPC.AddCpy(Emu.GetMarkedPoints().AddCpy(pc)); ShowAddr(FixPc(pc)); } } @@ -395,9 +348,9 @@ void InterpreterDisAsmFrame::MouseWheel(wxMouseEvent& event) bool InterpreterDisAsmFrame::IsBreakPoint(u64 pc) { - for(u32 i=0; i markedPC; Array remove_markedPC; wxTextCtrl* m_regs; - Array m_break_points; wxButton* m_btn_step; wxButton* m_btn_run; wxButton* m_btn_pause; @@ -29,9 +27,6 @@ public: InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu); ~InterpreterDisAsmFrame(); - void Save(const wxString& path); - void Load(const wxString& path); - void OnKeyDown(wxKeyEvent& event); void DoUpdate(); void ShowAddr(const u64 addr); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index e410335d0f..0a6b1c435f 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -50,10 +50,10 @@ MainFrame::MainFrame() menu_boot.Append(id_boot_elf, "Boot Elf"); //menu_boot.Append(id_boot_self, "Boot Self"); - menu_sys.Append(id_sys_pause, "Pause"); - menu_sys.Append(id_sys_stop, "Stop\tCtrl + S"); + menu_sys.Append(id_sys_pause, "Pause")->Enable(false); + menu_sys.Append(id_sys_stop, "Stop\tCtrl + S")->Enable(false); menu_sys.AppendSeparator(); - menu_sys.Append(id_sys_send_exit, "Send exit cmd"); + menu_sys.Append(id_sys_send_exit, "Send exit cmd")->Enable(false); menu_conf.Append(id_config_emu, "Settings"); @@ -73,8 +73,7 @@ MainFrame::MainFrame() Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); - - UpdateUI(); + m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(MainFrame::UpdateUI), (wxObject*)0, this); } MainFrame::~MainFrame() @@ -131,35 +130,35 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) if(wxFile::Access(elf0, wxFile::read)) { - Emu.SetElf(elf0); + Emu.SetPath(elf0); ConLog.Write("Elf: booting..."); } else if(wxFile::Access(elf1, wxFile::read)) { - Emu.SetElf(elf1); + Emu.SetPath(elf1); ConLog.Write("Elf: booting..."); } else if(wxFile::Access(elf2, wxFile::read)) { - Emu.SetElf(elf2); + Emu.SetPath(elf2); ConLog.Write("Elf: booting..."); } else if(wxFile::Access(self0, wxFile::read)) { goto _ELF_NOT_FOUND_; - Emu.SetSelf(self0); + Emu.SetPath(self0); ConLog.Warning("Self: booting..."); } else if(wxFile::Access(self1, wxFile::read)) { goto _ELF_NOT_FOUND_; - Emu.SetSelf(self1); + Emu.SetPath(self1); ConLog.Warning("Self: booting..."); } else if(wxFile::Access(self2, wxFile::read)) { goto _ELF_NOT_FOUND_; - Emu.SetSelf(self2); + Emu.SetPath(self2); ConLog.Warning("Self: booting..."); } else @@ -200,7 +199,7 @@ void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event)) Emu.Stop(); - Emu.SetElf(ctrl.GetPath()); + Emu.SetPath(ctrl.GetPath()); Emu.Load(); ConLog.Write("Elf: boot done."); @@ -229,7 +228,7 @@ void MainFrame::BootSelf(wxCommandEvent& WXUNUSED(event)) Emu.Stop(); - Emu.SetSelf(ctrl.GetPath()); + Emu.SetPath(ctrl.GetPath()); Emu.Load(); ConLog.Write("SELF: boot done."); @@ -367,9 +366,79 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) if(paused) Emu.Resume(); } -void MainFrame::UpdateUI(wxCommandEvent& WXUNUSED(event)) +void MainFrame::UpdateUI(wxCommandEvent& event) { - wxGetApp().m_debugger_frame->UpdateUI(); + event.Skip(); + + bool is_runned, is_stopped, is_ready; + + if(event.GetEventType() == wxEVT_DBG_COMMAND) + { + switch(event.GetId()) + { + case DID_START_EMU: + case DID_STARTED_EMU: + is_runned = true; + is_stopped = false; + is_ready = false; + break; + + case DID_STOP_EMU: + case DID_STOPED_EMU: + is_runned = false; + is_stopped = true; + is_ready = false; + break; + + case DID_PAUSE_EMU: + case DID_PAUSED_EMU: + is_runned = false; + is_stopped = false; + is_ready = false; + break; + + case DID_RESUME_EMU: + case DID_RESUMED_EMU: + is_runned = true; + is_stopped = false; + is_ready = false; + break; + + case DID_READY_EMU: + is_runned = false; + is_stopped = false; + is_ready = true; + break; + + default: + is_runned = Emu.IsRunned(); + is_stopped = Emu.IsStopped(); + is_ready = Emu.IsReady(); + break; + } + } + else + { + is_runned = Emu.IsRunned(); + is_stopped = Emu.IsStopped(); + is_ready = Emu.IsReady(); + } + + wxMenuBar& menubar( *GetMenuBar() ); + wxMenuItem& pause = *menubar.FindItem( id_sys_pause ); + wxMenuItem& stop = *menubar.FindItem( id_sys_stop ); + wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); + + pause.SetText(is_runned ? "Pause\tCtrl + P" : is_ready ? "Start\tCtrl + C" : "Resume\tCtrl + C"); + pause.Enable(!is_stopped); + stop.Enable(!is_stopped); + //send_exit.Enable(false); + send_exit.Enable(!is_stopped && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount()); + + m_aui_mgr.Update(); + + //wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg ); + //GetEventHandler()->AddPendingEvent( refit ); } void MainFrame::OnQuit(wxCloseEvent& event) @@ -434,22 +503,3 @@ void MainFrame::OnKeyDown(wxKeyEvent& event) event.Skip(); } - -void MainFrame::UpdateUI() -{ - wxMenuBar& menubar( *GetMenuBar() ); - wxMenuItem& pause = *menubar.FindItem( id_sys_pause ); - wxMenuItem& stop = *menubar.FindItem( id_sys_stop ); - wxMenuItem& send_exit = *menubar.FindItem( id_sys_send_exit ); - - pause.SetText(Emu.IsRunned() ? "Pause\tCtrl + P" : Emu.IsReady() ? "Start\tCtrl + C" : "Resume\tCtrl + C"); - pause.Enable(!Emu.IsStopped()); - stop.Enable(!Emu.IsStopped()); - //send_exit.Enable(false); - send_exit.Enable(!Emu.IsStopped() && Emu.GetCallbackManager().m_exit_callback.m_callbacks.GetCount()); - - m_aui_mgr.Update(); - - wxCommandEvent refit( wxEVT_COMMAND_MENU_SELECTED, id_update_dbg ); - GetEventHandler()->AddPendingEvent( refit ); -} \ No newline at end of file diff --git a/rpcs3/Gui/MainFrame.h b/rpcs3/Gui/MainFrame.h index acd7072708..b7e479a324 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -28,9 +28,6 @@ private: void UpdateUI(wxCommandEvent& event); void OnKeyDown(wxKeyEvent& event); -public: - void UpdateUI(); - private: DECLARE_EVENT_TABLE() }; \ No newline at end of file diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 817d115026..e12b58f923 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -1,7 +1,56 @@ #include "stdafx.h" #include "ELF64.h" -#include "Gui/CompilerELF.h" -using namespace PPU_opcodes; +#include "Emu/Cell/PPUInstrTable.h" +using namespace PPU_instr; + +void WriteEhdr(wxFile& f, Elf64_Ehdr& ehdr) +{ + Write32(f, ehdr.e_magic); + Write8(f, ehdr.e_class); + Write8(f, ehdr.e_data); + Write8(f, ehdr.e_curver); + Write8(f, ehdr.e_os_abi); + Write64(f, ehdr.e_abi_ver); + Write16(f, ehdr.e_type); + Write16(f, ehdr.e_machine); + Write32(f, ehdr.e_version); + Write64(f, ehdr.e_entry); + Write64(f, ehdr.e_phoff); + Write64(f, ehdr.e_shoff); + Write32(f, ehdr.e_flags); + Write16(f, ehdr.e_ehsize); + Write16(f, ehdr.e_phentsize); + Write16(f, ehdr.e_phnum); + Write16(f, ehdr.e_shentsize); + Write16(f, ehdr.e_shnum); + Write16(f, ehdr.e_shstrndx); +} + +void WritePhdr(wxFile& f, Elf64_Phdr& phdr) +{ + Write32(f, phdr.p_type); + Write32(f, phdr.p_flags); + Write64(f, phdr.p_offset); + Write64(f, phdr.p_vaddr); + Write64(f, phdr.p_paddr); + Write64(f, phdr.p_filesz); + Write64(f, phdr.p_memsz); + Write64(f, phdr.p_align); +} + +void WriteShdr(wxFile& f, Elf64_Shdr& shdr) +{ + Write32(f, shdr.sh_name); + Write32(f, shdr.sh_type); + Write64(f, shdr.sh_flags); + Write64(f, shdr.sh_addr); + Write64(f, shdr.sh_offset); + Write64(f, shdr.sh_size); + Write32(f, shdr.sh_link); + Write32(f, shdr.sh_info); + Write64(f, shdr.sh_addralign); + Write64(f, shdr.sh_entsize); +} ELF64Loader::ELF64Loader(vfsStream& f) : elf64_f(f) @@ -326,9 +375,9 @@ bool ELF64Loader::LoadPhdrData(u64 offset) out_tbl += nid; mem32_t out_dst(dst + i*section); - out_dst += ToOpcode(G_1f) | SetField(OR, 21, 30) | ToRA(11) | ToRS(2) | ToRB(2) | ToRC(0); - out_dst += ToOpcode(SC) | ToSYS(2); - out_dst += ToOpcode(G_13) | SetField(BCLR, 21, 30) | ToBO(0x10 | 0x04) | ToBI(0) | ToLK(0); + out_dst += OR(11, 2, 2, 0); + out_dst += SC(2); + out_dst += BCLR(0x10 | 0x04, 0, 0, 0); } } #ifdef LOADER_DEBUG diff --git a/rpcs3/Loader/ELF64.h b/rpcs3/Loader/ELF64.h index 0f3d0bcb95..00c96bf1ed 100644 --- a/rpcs3/Loader/ELF64.h +++ b/rpcs3/Loader/ELF64.h @@ -184,4 +184,8 @@ private: bool LoadShdrData(u64 offset); //bool LoadImports(); -}; \ No newline at end of file +}; + +void WriteEhdr(wxFile& f, Elf64_Ehdr& ehdr); +void WritePhdr(wxFile& f, Elf64_Phdr& phdr); +void WriteShdr(wxFile& f, Elf64_Shdr& shdr); \ No newline at end of file diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index 034c53dc29..d96d5b15b6 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -58,6 +58,30 @@ __forceinline static u64 Read64(vfsStream& f) return ((u64)Read32(f) << 32) | (u64)Read32(f); } +__forceinline static void Write8(wxFile& f, const u8 data) +{ + f.Write(&data, 1); +} + +__forceinline static void Write16(wxFile& f, const u16 data) +{ + Write8(f, data >> 8); + Write8(f, data); +} + +__forceinline static void Write32(wxFile& f, const u32 data) +{ + Write16(f, data >> 16); + Write16(f, data); +} + +__forceinline static void Write64(wxFile& f, const u64 data) +{ + Write32(f, data >> 32); + Write32(f, data); +} + + const wxString Ehdr_DataToString(const u8 data); const wxString Ehdr_TypeToString(const u16 type); const wxString Ehdr_OS_ABIToString(const u8 os_abi); diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index f716e8b532..8222acffc0 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -22,7 +22,15 @@ bool Rpcs3App::OnInit() SetTopWindow(m_MainFrame); Emu.Init(); - (new CompilerELF(m_MainFrame))->Show(); + try + { + (new CompilerELF(m_MainFrame))->Show(); + } + catch(...) + { + ConLog.Warning("CompilerELF is broken."); + } + m_debugger_frame = new DebuggerPanel(m_MainFrame); ConLogFrame = new LogFrame(m_MainFrame); diff --git a/rpcs3/rpcs3.h b/rpcs3/rpcs3.h index c44142c5ff..4f3a4649d4 100644 --- a/rpcs3/rpcs3.h +++ b/rpcs3/rpcs3.h @@ -22,17 +22,31 @@ enum DbgCommand DID_FIRST_COMMAND = 0x500, DID_START_EMU, + DID_STARTED_EMU, DID_STOP_EMU, + DID_STOPED_EMU, DID_PAUSE_EMU, + DID_PAUSED_EMU, DID_RESUME_EMU, + DID_RESUMED_EMU, + DID_READY_EMU, DID_CREATE_THREAD, + DID_CREATED_THREAD, DID_REMOVE_THREAD, + DID_REMOVED_THREAD, DID_RENAME_THREAD, + DID_RENAMED_THREAD, DID_START_THREAD, + DID_STARTED_THREAD, DID_STOP_THREAD, + DID_STOPED_THREAD, DID_PAUSE_THREAD, + DID_PAUSED_THREAD, DID_RESUME_THREAD, + DID_RESUMED_THREAD, DID_EXEC_THREAD, + DID_REGISTRED_CALLBACK, + DID_UNREGISTRED_CALLBACK, DID_LAST_COMMAND, }; diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index 09c1df82e0..b54b8ec505 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -197,6 +197,7 @@ + @@ -275,13 +276,17 @@ - + + + + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index b4d5f92feb..df23b4814f 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -247,6 +247,9 @@ rpcs3 + + Emu\CPU + @@ -270,9 +273,6 @@ Include - - Include - Include @@ -402,5 +402,20 @@ Utilities + + Include + + + Include + + + Include + + + Include + + + Include + \ No newline at end of file