diff --git a/Utilities/Array.h b/Utilities/Array.h index 09937423a5..44507c880f 100644 --- a/Utilities/Array.h +++ b/Utilities/Array.h @@ -23,6 +23,7 @@ public: const u32 to = from + count; if(to > GetCount()) return false; + for(u32 i=0; i() + { + return m_array; + } + protected: void _InsertRoomEnd(const u32 size) { @@ -180,7 +209,6 @@ template struct Stack : public Array } }; - template class ArrayF { u32 m_count; @@ -193,7 +221,7 @@ public: { } - ~ArrayF() + virtual ~ArrayF() { Clear(); } @@ -262,6 +290,53 @@ public: return *m_array[num]; } + T** operator + (u32 right) const + { + return m_array + right; + } + + T* operator ->() + { + return *m_array; + } + + inline T** GetPtr() + { + return m_array; + } + inline u32 GetCount() const { return m_count; } T& operator[](u32 num) const { return *m_array[num]; } }; + +template struct ScopedPtr +{ +private: + T* m_ptr; + +public: + ScopedPtr() : m_ptr(nullptr) + { + } + + ScopedPtr(T* ptr) : m_ptr(ptr) + { + } + + ~ScopedPtr() + { + Swap(nullptr); + } + + operator T*() { return m_ptr; } + operator const T*() const { return m_ptr; } + + T* operator ->() { return m_ptr; } + const T* operator ->() const { return m_ptr; } + + void Swap(T* ptr) + { + delete m_ptr; + m_ptr = ptr; + } +}; \ No newline at end of file diff --git a/Utilities/IdManager.h b/Utilities/IdManager.h index 75ada2b795..11a25f51b0 100644 --- a/Utilities/IdManager.h +++ b/Utilities/IdManager.h @@ -128,7 +128,7 @@ public: id.m_used = false; id.m_attr = 0; id.m_name.Clear(); - if(free_data) free(id.m_data); + if(free_data) delete id.m_data; id.m_data = NULL; if(IDToNum(_id) == IDs.GetCount()-1) Cleanup(); return true; diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index e53f9d8603..f46e890c5a 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1,6 +1,19 @@ #include "stdafx.h" #include "Thread.h" +ThreadBase* GetCurrentNamedThread() +{ + ThreadExec* thr = (ThreadExec*)::wxThread::This(); + return thr ? thr->m_parent : nullptr; +} + +ThreadBase::ThreadBase(bool detached, const wxString& name) + : m_detached(detached) + , m_name(name) + , m_executor(nullptr) +{ +} + void ThreadBase::Start() { if(m_executor) return; @@ -8,22 +21,77 @@ void ThreadBase::Start() m_executor = new ThreadExec(m_detached, this); } +void ThreadBase::Resume() +{ + if(m_executor) + { + m_executor->Resume(); + } +} + +void ThreadBase::Pause() +{ + if(m_executor) + { + m_executor->Pause(); + } +} + void ThreadBase::Stop(bool wait) { if(!m_executor) return; ThreadExec* exec = m_executor; m_executor = nullptr; - exec->Stop(wait); + + if(!m_detached) + { + if(wait) + { + exec->Wait(); + } + + exec->Stop(false); + delete exec; + } + else + { + exec->Stop(wait); + } } -bool ThreadBase::IsAlive() +bool ThreadBase::Wait() const +{ + return m_executor != nullptr && m_executor->Wait() != (wxThread::ExitCode)-1; +} + +bool ThreadBase::IsRunning() const +{ + return m_executor != nullptr && m_executor->IsRunning(); +} + +bool ThreadBase::IsPaused() const +{ + return m_executor != nullptr && m_executor->IsPaused(); +} + +bool ThreadBase::IsAlive() const { return m_executor != nullptr; } -bool ThreadBase::TestDestroy() +bool ThreadBase::TestDestroy() const { - if(!m_executor) return true; + if(!m_executor || !m_executor->m_parent) return true; return m_executor->TestDestroy(); +} + +wxString ThreadBase::GetThreadName() const +{ + return m_name; +} + +void ThreadBase::SetThreadName(const wxString& name) +{ + m_name = name; } \ No newline at end of file diff --git a/Utilities/Thread.h b/Utilities/Thread.h index dc8124c6e4..38f6807aeb 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -9,33 +9,41 @@ protected: wxString m_name; bool m_detached; +public: + wxMutex m_main_mutex; + protected: - ThreadBase(bool detached = true, const wxString& name = "Unknown ThreadBase") - : m_detached(detached) - , m_name(name) - , m_executor(nullptr) - { - } + ThreadBase(bool detached = true, const wxString& name = "Unknown ThreadBase"); public: ThreadExec* m_executor; virtual void Task()=0; - void Start(); - void Stop(bool wait = true); + virtual void Start(); + virtual void Resume(); + virtual void Pause(); + virtual void Stop(bool wait = true); - bool IsAlive(); - bool TestDestroy(); + virtual bool Wait() const; + virtual bool IsRunning() const; + virtual bool IsPaused() const; + virtual bool IsAlive() const; + virtual bool TestDestroy() const; + virtual wxString GetThreadName() const; + virtual void SetThreadName(const wxString& name); }; +ThreadBase* GetCurrentNamedThread(); + class ThreadExec : public wxThread { - ThreadBase* m_parent; - wxSemaphore m_wait_for_exit; + wxCriticalSection m_wait_for_exit; volatile bool m_alive; public: + ThreadBase* m_parent; + ThreadExec(bool detached, ThreadBase* parent) : wxThread(detached ? wxTHREAD_DETACHED : wxTHREAD_JOINABLE) , m_parent(parent) @@ -50,20 +58,26 @@ public: if(!m_alive) return; m_parent = nullptr; - Delete(); - if(wait && m_alive) m_wait_for_exit.Wait(); + + //if(wait) + { + Delete(); + //wxCriticalSectionLocker lock(m_wait_for_exit); + } } ExitCode Entry() { + //wxCriticalSectionLocker lock(m_wait_for_exit); m_parent->Task(); m_alive = false; - m_wait_for_exit.Post(); if(m_parent) m_parent->m_executor = nullptr; return (ExitCode)0; } }; +//ThreadBase* GetCurrentThread(); + template class MTPacketBuffer { protected: @@ -71,6 +85,7 @@ protected: volatile u32 m_put, m_get; Array m_buffer; u32 m_max_buffer_size; + mutable wxCriticalSection m_cs_main; void CheckBusy() { @@ -91,18 +106,43 @@ public: void Flush() { + wxCriticalSectionLocker lock(m_cs_main); m_put = m_get = 0; m_buffer.Clear(); m_busy = false; } - virtual void Push(const T& v) = 0; - virtual T Pop() = 0; +private: + virtual void _push(const T& v) = 0; + virtual T _pop() = 0; - bool HasNewPacket() const { return m_put != m_get; } +public: + void Push(const T& v) + { + wxCriticalSectionLocker lock(m_cs_main); + _push(v); + } + + T Pop() + { + wxCriticalSectionLocker lock(m_cs_main); + return _pop(); + } + + bool HasNewPacket() const { wxCriticalSectionLocker lock(m_cs_main); return m_put != m_get; } bool IsBusy() const { return m_busy; } }; +static __forceinline bool SemaphorePostAndWait(wxSemaphore& sem) +{ + if(sem.TryWait() != wxSEMA_BUSY) return false; + + sem.Post(); + sem.Wait(); + + return true; +} + /* class StepThread : public ThreadBase { diff --git a/bin/dev_hdd0/game/TEST12345/USRDIR/tetris.elf b/bin/dev_hdd0/game/TEST12345/USRDIR/tetris.elf index 1921a7701d..5ef2081a36 100644 Binary files a/bin/dev_hdd0/game/TEST12345/USRDIR/tetris.elf and b/bin/dev_hdd0/game/TEST12345/USRDIR/tetris.elf differ diff --git a/bin/make_fself.cmd b/bin/make_fself.cmd new file mode 100644 index 0000000000..34cee52250 --- /dev/null +++ b/bin/make_fself.cmd @@ -0,0 +1 @@ +make_fself compiled.elf EBOOT.BIN \ No newline at end of file diff --git a/rpcs3.sln b/rpcs3.sln index 492db8046e..7cbbc25353 100644 --- a/rpcs3.sln +++ b/rpcs3.sln @@ -2,60 +2,60 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}" ProjectSection(ProjectDependencies) = postProject - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34} = {2E26269D-8BFC-1A93-FD6E-E0CA16399B34} - {DB839A56-59B6-6430-99A9-51D08C6E33FD} = {DB839A56-59B6-6430-99A9-51D08C6E33FD} - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30} = {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30} - {0366B8AE-9D7B-A940-458C-A6B131A12AC8} = {0366B8AE-9D7B-A940-458C-A6B131A12AC8} - {B87F7202-6FA6-FC01-14FE-E92CE882F85B} = {B87F7202-6FA6-FC01-14FE-E92CE882F85B} - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214} = {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214} - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171} = {506026B2-9FD9-7F39-6E6E-55E0C2C8C171} - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495} = {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495} - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99} = {E1973C7F-F026-4596-C19D-6C8FBFAD2C99} - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA} = {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA} - {54994EB2-0674-8592-CF85-8E201FE680E2} = {54994EB2-0674-8592-CF85-8E201FE680E2} + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04} = {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04} + {156E1310-DA46-F664-E3C1-EE90B4CD92AE} = {156E1310-DA46-F664-E3C1-EE90B4CD92AE} + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF} = {90A67BD5-253F-CD50-BB9E-7002DA7D35CF} + {032DB7F5-755A-DF9E-5CBE-553BF92898EC} = {032DB7F5-755A-DF9E-5CBE-553BF92898EC} + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85} = {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85} + {7C123413-10B1-F29F-EEE5-B57A36827C70} = {7C123413-10B1-F29F-EEE5-B57A36827C70} + {F8EC63A1-40C4-541B-911E-3679CCA1132D} = {F8EC63A1-40C4-541B-911E-3679CCA1132D} + {CF3420B3-B31E-FDD0-4897-648FD5125566} = {CF3420B3-B31E-FDD0-4897-648FD5125566} + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6} = {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6} + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B} = {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B} + {350261DE-995E-5363-B942-85B09B015F2B} = {350261DE-995E-5363-B942-85B09B015F2B} EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wxWidgets", "wxWidgets", "{5812E712-6213-4372-B095-9EB9BAA1F2DF}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adv", "wxWidgets\build\msw\wx_adv.vcxproj", "{3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "adv", "wxWidgets\build\msw\wx_adv.vcxproj", "{7C123413-10B1-F29F-EEE5-B57A36827C70}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aui", "wxWidgets\build\msw\wx_aui.vcxproj", "{7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "aui", "wxWidgets\build\msw\wx_aui.vcxproj", "{0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "wxWidgets\build\msw\wx_base.vcxproj", "{2E26269D-8BFC-1A93-FD6E-E0CA16399B34}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "wxWidgets\build\msw\wx_base.vcxproj", "{7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "wxWidgets\build\msw\wx_core.vcxproj", "{E1973C7F-F026-4596-C19D-6C8FBFAD2C99}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "wxWidgets\build\msw\wx_core.vcxproj", "{8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dbgrid", "wxWidgets\build\msw\wx_dbgrid.vcxproj", "{13138455-15D7-0F02-57C4-083FE663B876}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dbgrid", "wxWidgets\build\msw\wx_dbgrid.vcxproj", "{16CD4B8D-C653-6AFD-426A-D10A768C1CE5}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gl", "wxWidgets\build\msw\wx_gl.vcxproj", "{B87F7202-6FA6-FC01-14FE-E92CE882F85B}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gl", "wxWidgets\build\msw\wx_gl.vcxproj", "{A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "html", "wxWidgets\build\msw\wx_html.vcxproj", "{B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "html", "wxWidgets\build\msw\wx_html.vcxproj", "{CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "media", "wxWidgets\build\msw\wx_media.vcxproj", "{03F61B23-19D0-F1E9-18D0-51504E42CC12}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "media", "wxWidgets\build\msw\wx_media.vcxproj", "{28365CAD-FDA4-E41A-7C13-FD86AC470A0D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net", "wxWidgets\build\msw\wx_net.vcxproj", "{73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "net", "wxWidgets\build\msw\wx_net.vcxproj", "{995774A7-FA69-E03D-1759-A4C33AE7FF7C}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "odbc", "wxWidgets\build\msw\wx_odbc.vcxproj", "{A0EBB666-81D6-8FDE-6279-E42B597CE104}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "odbc", "wxWidgets\build\msw\wx_odbc.vcxproj", "{EE9EE1EA-E48D-7B28-2825-6F014802A43B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qa", "wxWidgets\build\msw\wx_qa.vcxproj", "{6A708533-20DB-79A7-1DB4-B8DC76D5A105}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qa", "wxWidgets\build\msw\wx_qa.vcxproj", "{D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "richtext", "wxWidgets\build\msw\wx_richtext.vcxproj", "{5CEF975B-7E93-DFD0-C929-38EFBFCF640A}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "richtext", "wxWidgets\build\msw\wx_richtext.vcxproj", "{DCF03EA6-9806-338B-3B07-60273468D4A9}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxexpat", "wxWidgets\build\msw\wx_wxexpat.vcxproj", "{FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxexpat", "wxWidgets\build\msw\wx_wxexpat.vcxproj", "{90A67BD5-253F-CD50-BB9E-7002DA7D35CF}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxjpeg", "wxWidgets\build\msw\wx_wxjpeg.vcxproj", "{DB839A56-59B6-6430-99A9-51D08C6E33FD}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxjpeg", "wxWidgets\build\msw\wx_wxjpeg.vcxproj", "{156E1310-DA46-F664-E3C1-EE90B4CD92AE}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxpng", "wxWidgets\build\msw\wx_wxpng.vcxproj", "{B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxpng", "wxWidgets\build\msw\wx_wxpng.vcxproj", "{CF3420B3-B31E-FDD0-4897-648FD5125566}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxregex", "wxWidgets\build\msw\wx_wxregex.vcxproj", "{0366B8AE-9D7B-A940-458C-A6B131A12AC8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxregex", "wxWidgets\build\msw\wx_wxregex.vcxproj", "{032DB7F5-755A-DF9E-5CBE-553BF92898EC}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxtiff", "wxWidgets\build\msw\wx_wxtiff.vcxproj", "{506026B2-9FD9-7F39-6E6E-55E0C2C8C171}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxtiff", "wxWidgets\build\msw\wx_wxtiff.vcxproj", "{F8EC63A1-40C4-541B-911E-3679CCA1132D}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxzlib", "wxWidgets\build\msw\wx_wxzlib.vcxproj", "{54994EB2-0674-8592-CF85-8E201FE680E2}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wxzlib", "wxWidgets\build\msw\wx_wxzlib.vcxproj", "{350261DE-995E-5363-B942-85B09B015F2B}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xml", "wxWidgets\build\msw\wx_xml.vcxproj", "{D047D758-2B7F-D39A-B387-01064479E2DA}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xml", "wxWidgets\build\msw\wx_xml.vcxproj", "{503E4C3C-5D61-7928-7745-526C6EE2646F}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrc", "wxWidgets\build\msw\wx_xrc.vcxproj", "{F0D3A651-E58B-6E40-75DA-0882C2B5F987}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrc", "wxWidgets\build\msw\wx_xrc.vcxproj", "{EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -73,190 +73,190 @@ Global {70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|Win32.Build.0 = Release|Win32 {70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.ActiveCfg = Release|x64 {70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.Build.0 = Release|x64 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Debug|Win32.ActiveCfg = Debug|Win32 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Debug|Win32.Build.0 = Debug|Win32 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Debug|x64.ActiveCfg = Debug|x64 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Debug|x64.Build.0 = Debug|x64 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Release|Win32.ActiveCfg = Release|Win32 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Release|Win32.Build.0 = Release|Win32 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Release|x64.ActiveCfg = Release|x64 - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214}.Release|x64.Build.0 = Release|x64 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Debug|Win32.ActiveCfg = Debug|Win32 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Debug|Win32.Build.0 = Debug|Win32 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Debug|x64.ActiveCfg = Debug|x64 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Debug|x64.Build.0 = Debug|x64 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Release|Win32.ActiveCfg = Release|Win32 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Release|Win32.Build.0 = Release|Win32 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Release|x64.ActiveCfg = Release|x64 - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA}.Release|x64.Build.0 = Release|x64 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Debug|Win32.ActiveCfg = Debug|Win32 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Debug|Win32.Build.0 = Debug|Win32 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Debug|x64.ActiveCfg = Debug|x64 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Debug|x64.Build.0 = Debug|x64 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Release|Win32.ActiveCfg = Release|Win32 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Release|Win32.Build.0 = Release|Win32 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Release|x64.ActiveCfg = Release|x64 - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34}.Release|x64.Build.0 = Release|x64 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Debug|Win32.ActiveCfg = Debug|Win32 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Debug|Win32.Build.0 = Debug|Win32 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Debug|x64.ActiveCfg = Debug|x64 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Debug|x64.Build.0 = Debug|x64 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Release|Win32.ActiveCfg = Release|Win32 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Release|Win32.Build.0 = Release|Win32 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Release|x64.ActiveCfg = Release|x64 - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99}.Release|x64.Build.0 = Release|x64 - {13138455-15D7-0F02-57C4-083FE663B876}.Debug|Win32.ActiveCfg = Debug|Win32 - {13138455-15D7-0F02-57C4-083FE663B876}.Debug|Win32.Build.0 = Debug|Win32 - {13138455-15D7-0F02-57C4-083FE663B876}.Debug|x64.ActiveCfg = Debug|x64 - {13138455-15D7-0F02-57C4-083FE663B876}.Debug|x64.Build.0 = Debug|x64 - {13138455-15D7-0F02-57C4-083FE663B876}.Release|Win32.ActiveCfg = Release|Win32 - {13138455-15D7-0F02-57C4-083FE663B876}.Release|Win32.Build.0 = Release|Win32 - {13138455-15D7-0F02-57C4-083FE663B876}.Release|x64.ActiveCfg = Release|x64 - {13138455-15D7-0F02-57C4-083FE663B876}.Release|x64.Build.0 = Release|x64 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Debug|Win32.ActiveCfg = Debug|Win32 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Debug|Win32.Build.0 = Debug|Win32 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Debug|x64.ActiveCfg = Debug|x64 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Debug|x64.Build.0 = Debug|x64 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Release|Win32.ActiveCfg = Release|Win32 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Release|Win32.Build.0 = Release|Win32 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Release|x64.ActiveCfg = Release|x64 - {B87F7202-6FA6-FC01-14FE-E92CE882F85B}.Release|x64.Build.0 = Release|x64 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Debug|Win32.ActiveCfg = Debug|Win32 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Debug|Win32.Build.0 = Debug|Win32 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Debug|x64.ActiveCfg = Debug|x64 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Debug|x64.Build.0 = Debug|x64 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Release|Win32.ActiveCfg = Release|Win32 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Release|Win32.Build.0 = Release|Win32 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Release|x64.ActiveCfg = Release|x64 - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37}.Release|x64.Build.0 = Release|x64 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Debug|Win32.ActiveCfg = Debug|Win32 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Debug|Win32.Build.0 = Debug|Win32 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Debug|x64.ActiveCfg = Debug|x64 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Debug|x64.Build.0 = Debug|x64 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Release|Win32.ActiveCfg = Release|Win32 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Release|Win32.Build.0 = Release|Win32 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Release|x64.ActiveCfg = Release|x64 - {03F61B23-19D0-F1E9-18D0-51504E42CC12}.Release|x64.Build.0 = Release|x64 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Debug|Win32.ActiveCfg = Debug|Win32 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Debug|Win32.Build.0 = Debug|Win32 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Debug|x64.ActiveCfg = Debug|x64 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Debug|x64.Build.0 = Debug|x64 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Release|Win32.ActiveCfg = Release|Win32 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Release|Win32.Build.0 = Release|Win32 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Release|x64.ActiveCfg = Release|x64 - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78}.Release|x64.Build.0 = Release|x64 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Debug|Win32.ActiveCfg = Debug|Win32 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Debug|Win32.Build.0 = Debug|Win32 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Debug|x64.ActiveCfg = Debug|x64 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Debug|x64.Build.0 = Debug|x64 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Release|Win32.ActiveCfg = Release|Win32 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Release|Win32.Build.0 = Release|Win32 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Release|x64.ActiveCfg = Release|x64 - {A0EBB666-81D6-8FDE-6279-E42B597CE104}.Release|x64.Build.0 = Release|x64 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Debug|Win32.ActiveCfg = Debug|Win32 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Debug|Win32.Build.0 = Debug|Win32 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Debug|x64.ActiveCfg = Debug|x64 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Debug|x64.Build.0 = Debug|x64 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Release|Win32.ActiveCfg = Release|Win32 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Release|Win32.Build.0 = Release|Win32 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Release|x64.ActiveCfg = Release|x64 - {6A708533-20DB-79A7-1DB4-B8DC76D5A105}.Release|x64.Build.0 = Release|x64 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Debug|Win32.ActiveCfg = Debug|Win32 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Debug|Win32.Build.0 = Debug|Win32 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Debug|x64.ActiveCfg = Debug|x64 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Debug|x64.Build.0 = Debug|x64 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Release|Win32.ActiveCfg = Release|Win32 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Release|Win32.Build.0 = Release|Win32 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Release|x64.ActiveCfg = Release|x64 - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A}.Release|x64.Build.0 = Release|x64 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Debug|Win32.ActiveCfg = Debug|Win32 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Debug|Win32.Build.0 = Debug|Win32 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Debug|x64.ActiveCfg = Debug|x64 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Debug|x64.Build.0 = Debug|x64 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Release|Win32.ActiveCfg = Release|Win32 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Release|Win32.Build.0 = Release|Win32 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Release|x64.ActiveCfg = Release|x64 - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30}.Release|x64.Build.0 = Release|x64 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Debug|Win32.ActiveCfg = Debug|Win32 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Debug|Win32.Build.0 = Debug|Win32 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Debug|x64.ActiveCfg = Debug|x64 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Debug|x64.Build.0 = Debug|x64 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Release|Win32.ActiveCfg = Release|Win32 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Release|Win32.Build.0 = Release|Win32 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Release|x64.ActiveCfg = Release|x64 - {DB839A56-59B6-6430-99A9-51D08C6E33FD}.Release|x64.Build.0 = Release|x64 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Debug|Win32.ActiveCfg = Debug|Win32 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Debug|Win32.Build.0 = Debug|Win32 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Debug|x64.ActiveCfg = Debug|x64 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Debug|x64.Build.0 = Debug|x64 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Release|Win32.ActiveCfg = Release|Win32 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Release|Win32.Build.0 = Release|Win32 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Release|x64.ActiveCfg = Release|x64 - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495}.Release|x64.Build.0 = Release|x64 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Debug|Win32.ActiveCfg = Debug|Win32 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Debug|Win32.Build.0 = Debug|Win32 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Debug|x64.ActiveCfg = Debug|x64 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Debug|x64.Build.0 = Debug|x64 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Release|Win32.ActiveCfg = Release|Win32 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Release|Win32.Build.0 = Release|Win32 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Release|x64.ActiveCfg = Release|x64 - {0366B8AE-9D7B-A940-458C-A6B131A12AC8}.Release|x64.Build.0 = Release|x64 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Debug|Win32.ActiveCfg = Debug|Win32 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Debug|Win32.Build.0 = Debug|Win32 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Debug|x64.ActiveCfg = Debug|x64 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Debug|x64.Build.0 = Debug|x64 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Release|Win32.ActiveCfg = Release|Win32 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Release|Win32.Build.0 = Release|Win32 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Release|x64.ActiveCfg = Release|x64 - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171}.Release|x64.Build.0 = Release|x64 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Debug|Win32.ActiveCfg = Debug|Win32 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Debug|Win32.Build.0 = Debug|Win32 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Debug|x64.ActiveCfg = Debug|x64 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Debug|x64.Build.0 = Debug|x64 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Release|Win32.ActiveCfg = Release|Win32 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Release|Win32.Build.0 = Release|Win32 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Release|x64.ActiveCfg = Release|x64 - {54994EB2-0674-8592-CF85-8E201FE680E2}.Release|x64.Build.0 = Release|x64 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Debug|Win32.ActiveCfg = Debug|Win32 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Debug|Win32.Build.0 = Debug|Win32 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Debug|x64.ActiveCfg = Debug|x64 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Debug|x64.Build.0 = Debug|x64 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Release|Win32.ActiveCfg = Release|Win32 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Release|Win32.Build.0 = Release|Win32 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Release|x64.ActiveCfg = Release|x64 - {D047D758-2B7F-D39A-B387-01064479E2DA}.Release|x64.Build.0 = Release|x64 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Debug|Win32.ActiveCfg = Debug|Win32 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Debug|Win32.Build.0 = Debug|Win32 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Debug|x64.ActiveCfg = Debug|x64 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Debug|x64.Build.0 = Debug|x64 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Release|Win32.ActiveCfg = Release|Win32 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Release|Win32.Build.0 = Release|Win32 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Release|x64.ActiveCfg = Release|x64 - {F0D3A651-E58B-6E40-75DA-0882C2B5F987}.Release|x64.Build.0 = Release|x64 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Debug|Win32.Build.0 = Debug|Win32 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Debug|x64.ActiveCfg = Debug|x64 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Debug|x64.Build.0 = Debug|x64 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Release|Win32.ActiveCfg = Release|Win32 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Release|Win32.Build.0 = Release|Win32 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Release|x64.ActiveCfg = Release|x64 + {7C123413-10B1-F29F-EEE5-B57A36827C70}.Release|x64.Build.0 = Release|x64 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Debug|Win32.ActiveCfg = Debug|Win32 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Debug|Win32.Build.0 = Debug|Win32 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Debug|x64.ActiveCfg = Debug|x64 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Debug|x64.Build.0 = Debug|x64 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Release|Win32.ActiveCfg = Release|Win32 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Release|Win32.Build.0 = Release|Win32 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Release|x64.ActiveCfg = Release|x64 + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B}.Release|x64.Build.0 = Release|x64 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Debug|Win32.ActiveCfg = Debug|Win32 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Debug|Win32.Build.0 = Debug|Win32 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Debug|x64.ActiveCfg = Debug|x64 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Debug|x64.Build.0 = Debug|x64 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Release|Win32.ActiveCfg = Release|Win32 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Release|Win32.Build.0 = Release|Win32 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Release|x64.ActiveCfg = Release|x64 + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04}.Release|x64.Build.0 = Release|x64 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Debug|Win32.ActiveCfg = Debug|Win32 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Debug|Win32.Build.0 = Debug|Win32 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Debug|x64.ActiveCfg = Debug|x64 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Debug|x64.Build.0 = Debug|x64 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Release|Win32.ActiveCfg = Release|Win32 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Release|Win32.Build.0 = Release|Win32 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Release|x64.ActiveCfg = Release|x64 + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6}.Release|x64.Build.0 = Release|x64 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Debug|Win32.ActiveCfg = Debug|Win32 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Debug|Win32.Build.0 = Debug|Win32 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Debug|x64.ActiveCfg = Debug|x64 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Debug|x64.Build.0 = Debug|x64 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Release|Win32.ActiveCfg = Release|Win32 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Release|Win32.Build.0 = Release|Win32 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Release|x64.ActiveCfg = Release|x64 + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5}.Release|x64.Build.0 = Release|x64 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Debug|Win32.ActiveCfg = Debug|Win32 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Debug|Win32.Build.0 = Debug|Win32 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Debug|x64.ActiveCfg = Debug|x64 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Debug|x64.Build.0 = Debug|x64 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Release|Win32.ActiveCfg = Release|Win32 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Release|Win32.Build.0 = Release|Win32 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Release|x64.ActiveCfg = Release|x64 + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85}.Release|x64.Build.0 = Release|x64 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Debug|Win32.ActiveCfg = Debug|Win32 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Debug|Win32.Build.0 = Debug|Win32 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Debug|x64.ActiveCfg = Debug|x64 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Debug|x64.Build.0 = Debug|x64 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Release|Win32.ActiveCfg = Release|Win32 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Release|Win32.Build.0 = Release|Win32 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Release|x64.ActiveCfg = Release|x64 + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8}.Release|x64.Build.0 = Release|x64 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Debug|Win32.ActiveCfg = Debug|Win32 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Debug|Win32.Build.0 = Debug|Win32 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Debug|x64.ActiveCfg = Debug|x64 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Debug|x64.Build.0 = Debug|x64 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Release|Win32.ActiveCfg = Release|Win32 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Release|Win32.Build.0 = Release|Win32 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Release|x64.ActiveCfg = Release|x64 + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D}.Release|x64.Build.0 = Release|x64 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Debug|Win32.ActiveCfg = Debug|Win32 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Debug|Win32.Build.0 = Debug|Win32 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Debug|x64.ActiveCfg = Debug|x64 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Debug|x64.Build.0 = Debug|x64 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Release|Win32.ActiveCfg = Release|Win32 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Release|Win32.Build.0 = Release|Win32 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Release|x64.ActiveCfg = Release|x64 + {995774A7-FA69-E03D-1759-A4C33AE7FF7C}.Release|x64.Build.0 = Release|x64 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Debug|Win32.ActiveCfg = Debug|Win32 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Debug|Win32.Build.0 = Debug|Win32 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Debug|x64.ActiveCfg = Debug|x64 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Debug|x64.Build.0 = Debug|x64 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Release|Win32.ActiveCfg = Release|Win32 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Release|Win32.Build.0 = Release|Win32 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Release|x64.ActiveCfg = Release|x64 + {EE9EE1EA-E48D-7B28-2825-6F014802A43B}.Release|x64.Build.0 = Release|x64 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Debug|Win32.ActiveCfg = Debug|Win32 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Debug|Win32.Build.0 = Debug|Win32 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Debug|x64.ActiveCfg = Debug|x64 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Debug|x64.Build.0 = Debug|x64 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Release|Win32.ActiveCfg = Release|Win32 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Release|Win32.Build.0 = Release|Win32 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Release|x64.ActiveCfg = Release|x64 + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B}.Release|x64.Build.0 = Release|x64 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Debug|Win32.ActiveCfg = Debug|Win32 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Debug|Win32.Build.0 = Debug|Win32 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Debug|x64.ActiveCfg = Debug|x64 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Debug|x64.Build.0 = Debug|x64 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Release|Win32.ActiveCfg = Release|Win32 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Release|Win32.Build.0 = Release|Win32 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Release|x64.ActiveCfg = Release|x64 + {DCF03EA6-9806-338B-3B07-60273468D4A9}.Release|x64.Build.0 = Release|x64 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Debug|Win32.ActiveCfg = Debug|Win32 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Debug|Win32.Build.0 = Debug|Win32 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Debug|x64.ActiveCfg = Debug|x64 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Debug|x64.Build.0 = Debug|x64 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Release|Win32.ActiveCfg = Release|Win32 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Release|Win32.Build.0 = Release|Win32 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Release|x64.ActiveCfg = Release|x64 + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF}.Release|x64.Build.0 = Release|x64 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Debug|Win32.ActiveCfg = Debug|Win32 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Debug|Win32.Build.0 = Debug|Win32 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Debug|x64.ActiveCfg = Debug|x64 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Debug|x64.Build.0 = Debug|x64 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Release|Win32.ActiveCfg = Release|Win32 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Release|Win32.Build.0 = Release|Win32 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Release|x64.ActiveCfg = Release|x64 + {156E1310-DA46-F664-E3C1-EE90B4CD92AE}.Release|x64.Build.0 = Release|x64 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Debug|Win32.ActiveCfg = Debug|Win32 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Debug|Win32.Build.0 = Debug|Win32 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Debug|x64.ActiveCfg = Debug|x64 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Debug|x64.Build.0 = Debug|x64 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Release|Win32.ActiveCfg = Release|Win32 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Release|Win32.Build.0 = Release|Win32 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Release|x64.ActiveCfg = Release|x64 + {CF3420B3-B31E-FDD0-4897-648FD5125566}.Release|x64.Build.0 = Release|x64 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Debug|Win32.ActiveCfg = Debug|Win32 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Debug|Win32.Build.0 = Debug|Win32 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Debug|x64.ActiveCfg = Debug|x64 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Debug|x64.Build.0 = Debug|x64 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Release|Win32.ActiveCfg = Release|Win32 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Release|Win32.Build.0 = Release|Win32 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Release|x64.ActiveCfg = Release|x64 + {032DB7F5-755A-DF9E-5CBE-553BF92898EC}.Release|x64.Build.0 = Release|x64 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Debug|Win32.ActiveCfg = Debug|Win32 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Debug|Win32.Build.0 = Debug|Win32 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Debug|x64.ActiveCfg = Debug|x64 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Debug|x64.Build.0 = Debug|x64 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Release|Win32.ActiveCfg = Release|Win32 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Release|Win32.Build.0 = Release|Win32 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Release|x64.ActiveCfg = Release|x64 + {F8EC63A1-40C4-541B-911E-3679CCA1132D}.Release|x64.Build.0 = Release|x64 + {350261DE-995E-5363-B942-85B09B015F2B}.Debug|Win32.ActiveCfg = Debug|Win32 + {350261DE-995E-5363-B942-85B09B015F2B}.Debug|Win32.Build.0 = Debug|Win32 + {350261DE-995E-5363-B942-85B09B015F2B}.Debug|x64.ActiveCfg = Debug|x64 + {350261DE-995E-5363-B942-85B09B015F2B}.Debug|x64.Build.0 = Debug|x64 + {350261DE-995E-5363-B942-85B09B015F2B}.Release|Win32.ActiveCfg = Release|Win32 + {350261DE-995E-5363-B942-85B09B015F2B}.Release|Win32.Build.0 = Release|Win32 + {350261DE-995E-5363-B942-85B09B015F2B}.Release|x64.ActiveCfg = Release|x64 + {350261DE-995E-5363-B942-85B09B015F2B}.Release|x64.Build.0 = Release|x64 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Debug|Win32.ActiveCfg = Debug|Win32 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Debug|Win32.Build.0 = Debug|Win32 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Debug|x64.ActiveCfg = Debug|x64 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Debug|x64.Build.0 = Debug|x64 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Release|Win32.ActiveCfg = Release|Win32 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Release|Win32.Build.0 = Release|Win32 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Release|x64.ActiveCfg = Release|x64 + {503E4C3C-5D61-7928-7745-526C6EE2646F}.Release|x64.Build.0 = Release|x64 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Debug|Win32.ActiveCfg = Debug|Win32 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Debug|Win32.Build.0 = Debug|Win32 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Debug|x64.ActiveCfg = Debug|x64 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Debug|x64.Build.0 = Debug|x64 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Release|Win32.ActiveCfg = Release|Win32 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Release|Win32.Build.0 = Release|Win32 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Release|x64.ActiveCfg = Release|x64 + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {3B3A5736-72C8-C9BB-FC7C-8B3B096D0214} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {7B39DA9E-3F58-7A74-C4A9-E84F163B0FBA} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {2E26269D-8BFC-1A93-FD6E-E0CA16399B34} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {E1973C7F-F026-4596-C19D-6C8FBFAD2C99} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {13138455-15D7-0F02-57C4-083FE663B876} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {B87F7202-6FA6-FC01-14FE-E92CE882F85B} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {B3E441F3-C4A3-7816-FAAE-2E7B0CA1AD37} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {03F61B23-19D0-F1E9-18D0-51504E42CC12} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {73AF98D9-3335-CAFC-E7A9-9A20BA14EE78} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {A0EBB666-81D6-8FDE-6279-E42B597CE104} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {6A708533-20DB-79A7-1DB4-B8DC76D5A105} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {5CEF975B-7E93-DFD0-C929-38EFBFCF640A} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {FBFC91AB-EA5A-EF88-57EF-12A42BE15C30} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {DB839A56-59B6-6430-99A9-51D08C6E33FD} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {B52A4FC7-1A2C-4959-ACFD-8FF0E0AC7495} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {0366B8AE-9D7B-A940-458C-A6B131A12AC8} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {506026B2-9FD9-7F39-6E6E-55E0C2C8C171} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {54994EB2-0674-8592-CF85-8E201FE680E2} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {D047D758-2B7F-D39A-B387-01064479E2DA} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} - {F0D3A651-E58B-6E40-75DA-0882C2B5F987} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {7C123413-10B1-F29F-EEE5-B57A36827C70} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {0C1DDDB4-F751-0E8E-982C-A6B14886FC7B} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {7F6DB432-0C72-FFB1-DE82-D450DAD5CF04} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {8A8F7ACD-0DB7-90B1-F4F8-F31D60255FD6} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {16CD4B8D-C653-6AFD-426A-D10A768C1CE5} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {A66455C9-DAD3-9BB7-13E6-08E6E33D9B85} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {CABB82BE-DFB1-E556-0AC3-5FC4D6933AE8} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {28365CAD-FDA4-E41A-7C13-FD86AC470A0D} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {995774A7-FA69-E03D-1759-A4C33AE7FF7C} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {EE9EE1EA-E48D-7B28-2825-6F014802A43B} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {D78B0119-3CA8-C0A4-E1C2-4D646A68AC5B} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {DCF03EA6-9806-338B-3B07-60273468D4A9} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {90A67BD5-253F-CD50-BB9E-7002DA7D35CF} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {156E1310-DA46-F664-E3C1-EE90B4CD92AE} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {CF3420B3-B31E-FDD0-4897-648FD5125566} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {032DB7F5-755A-DF9E-5CBE-553BF92898EC} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {F8EC63A1-40C4-541B-911E-3679CCA1132D} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {350261DE-995E-5363-B942-85B09B015F2B} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {503E4C3C-5D61-7928-7745-526C6EE2646F} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} + {EB4E73BF-E88A-8B43-D654-EE1A4D88D10E} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} EndGlobalSection EndGlobal diff --git a/rpcs3/AppConnector.cpp b/rpcs3/AppConnector.cpp new file mode 100644 index 0000000000..b38ccd67c8 --- /dev/null +++ b/rpcs3/AppConnector.cpp @@ -0,0 +1,32 @@ +#include "stdafx.h" +#include "AppConnector.h" + +AppConnector::~AppConnector() +{ + for(uint i=0; i m_connect_arr; + +public: + ~AppConnector(); + + void Connect(int winid, int lastId, int eventType, wxObjectEventFunction func, wxObject* userData = nullptr, wxEvtHandler* eventSink = nullptr); + void Connect(int winid, int eventType, wxObjectEventFunction func, wxObject* userData = nullptr, wxEvtHandler* eventSink = nullptr); + void Connect(int eventType, wxObjectEventFunction func, wxObject* userData = nullptr, wxEvtHandler* eventSink = nullptr); +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/DisAsm.h b/rpcs3/Emu/Cell/DisAsm.h index c51b6b5506..5411e38dbe 100644 --- a/rpcs3/Emu/Cell/DisAsm.h +++ b/rpcs3/Emu/Cell/DisAsm.h @@ -76,10 +76,34 @@ protected: return op; } + void DisAsm_V4(const wxString& op, OP_REG v0, OP_REG v1, OP_REG v2, OP_REG v3) + { + Write(wxString::Format("%s v%d,v%d,v%d,v%d", FixOp(op), v0, v1, v2, v3)); + } + void DisAsm_V3_UIMM(const wxString& op, OP_REG v0, OP_REG v1, OP_REG v2, OP_uIMM uimm) + { + Write(wxString::Format("%s v%d,v%d,v%d,%u #%x", FixOp(op), v0, v1, v2, uimm, uimm)); + } void DisAsm_V3(const wxString& op, OP_REG v0, OP_REG v1, OP_REG v2) { Write(wxString::Format("%s v%d,v%d,v%d", FixOp(op), v0, v1, v2)); } + void DisAsm_V2_UIMM(const wxString& op, OP_REG v0, OP_REG v1, OP_uIMM uimm) + { + Write(wxString::Format("%s v%d,v%d,%u #%x", FixOp(op), v0, v1, uimm, uimm)); + } + void DisAsm_V2(const wxString& op, OP_REG v0, OP_REG v1) + { + Write(wxString::Format("%s v%d,v%d", FixOp(op), v0, v1)); + } + void DisAsm_V1_SIMM(const wxString& op, OP_REG v0, OP_sIMM simm) + { + Write(wxString::Format("%s v%d,%d #%x", FixOp(op), v0, simm, simm)); + } + void DisAsm_V1(const wxString& op, OP_REG v0) + { + Write(wxString::Format("%s v%d", FixOp(op), v0)); + } void DisAsm_V1_R2(const wxString& op, OP_REG v0, OP_REG r1, OP_REG r2) { Write(wxString::Format("%s v%d,r%d,r%d", FixOp(op), v0, r1, r2)); diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index 1e9867f83e..316f8e19ba 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -2,8 +2,14 @@ #include "PPCThread.h" #include "Gui/InterpreterDisAsm.h" +PPCThread* GetCurrentPPCThread() +{ + return (PPCThread*)GetCurrentNamedThread(); +} + PPCThread::PPCThread(PPCThreadType type) - : m_type(type) + : ThreadBase(true, "PPCThread") + , m_type(type) , DisAsmFrame(NULL) , m_arg(0) , m_dec(NULL) @@ -79,16 +85,11 @@ void PPCThread::SetId(const u32 id) m_id = id; ID& thread = Emu.GetIdManager().GetIDData(m_id); thread.m_name = GetName(); - - if(Ini.CPUDecoderMode.GetValue() != 1) return; - DisAsmFrame = new InterpreterDisAsmFrame(GetFName(), this); - (*(InterpreterDisAsmFrame*)DisAsmFrame).Show(); } void PPCThread::SetName(const wxString& name) { m_name = name; - if(DisAsmFrame) (*(InterpreterDisAsmFrame*)DisAsmFrame).SetTitle(GetFName()); } void PPCThread::NextBranchPc() @@ -119,6 +120,11 @@ void PPCThread::SetPc(const u64 pc) nPC = PC + 4; } +void PPCThread::SetEntry(const u64 pc) +{ + entry = pc; +} + void PPCThread::SetBranch(const u64 pc) { if(!Memory.IsGoodAddr(pc)) @@ -164,41 +170,95 @@ void PPCThread::Run() m_status = Runned; + SetPc(entry); InitStack(); InitRegs(); DoRun(); Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_START_THREAD, this); + if(DisAsmFrame) (*(InterpreterDisAsmFrame*)DisAsmFrame).DoUpdate(); } void PPCThread::Resume() { if(!IsPaused()) return; + m_status = Runned; DoResume(); Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_RESUME_THREAD, this); + + ThreadBase::Start(); } void PPCThread::Pause() { if(!IsRunned()) return; + m_status = Paused; DoPause(); Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, this); + + ThreadBase::Stop(false); } void PPCThread::Stop() { if(IsStopped()) return; + m_status = Stopped; Reset(); DoStop(); Emu.CheckStatus(); + + wxGetApp().SendDbgCommand(DID_STOP_THREAD, this); + + ThreadBase::Stop(); } void PPCThread::Exec() { - if(!IsRunned()) return; + wxGetApp().SendDbgCommand(DID_EXEC_THREAD, this); + ThreadBase::Start(); +} + +void PPCThread::ExecOnce() +{ DoCode(Memory.Read32(m_offset + PC)); NextPc(); -} \ No newline at end of file +} + +void PPCThread::Task() +{ + ConLog.Write("%s enter", PPCThread::GetFName()); + + try + { + while(!Emu.IsStopped() && !TestDestroy()) + { + if(Emu.IsPaused()) + { + Sleep(1); + continue; + } + + DoCode(Memory.Read32(m_offset + PC)); + NextPc(); + } + } + catch(const wxString& e) + { + ConLog.Error("Exception: %s", e); + } + catch(const char* e) + { + ConLog.Error("Exception: %s", e); + } + + ConLog.Write("%s leave", PPCThread::GetFName()); +} diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index c7164f581b..cde0d4c04d 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -8,7 +8,7 @@ enum PPCThreadType PPC_THREAD_SPU, }; -class PPCThread// : public StepThread +class PPCThread : public ThreadBase { protected: u32 m_status; @@ -19,7 +19,6 @@ protected: PPCThreadType m_type; u64 m_arg; u64 m_prio; - wxString m_name; bool m_joinable; bool m_joining; Array argv_addr; @@ -70,9 +69,15 @@ public: wxString GetTypeString() const { return PPCThreadTypeToString(m_type); } + virtual wxString GetThreadName() const + { + return GetFName() + wxString::Format("[0x%08llx]", PC); + } + public: bool isBranch; + u64 entry; u64 PC; u64 nPC; u64 cycle; @@ -88,6 +93,7 @@ public: void PrevPc(); void SetBranch(const u64 pc); void SetPc(const u64 pc); + void SetEntry(const u64 entry); void SetError(const u32 error); @@ -118,6 +124,7 @@ public: virtual wxString RegsToString() { return wxEmptyString; } virtual void Exec(); + void ExecOnce(); virtual void AddArgv(const wxString& arg) {} @@ -127,7 +134,11 @@ protected: virtual void DoPause()=0; virtual void DoResume()=0; virtual void DoStop()=0; + + virtual void Task(); private: virtual void DoCode(const s32 code)=0; -}; \ No newline at end of file +}; + +PPCThread* GetCurrentPPCThread(); \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCThreadManager.cpp b/rpcs3/Emu/Cell/PPCThreadManager.cpp index fb8371e86f..c14b1588a1 100644 --- a/rpcs3/Emu/Cell/PPCThreadManager.cpp +++ b/rpcs3/Emu/Cell/PPCThreadManager.cpp @@ -4,7 +4,6 @@ #include "SPUThread.h" PPCThreadManager::PPCThreadManager() - : ThreadBase(true, "PPCThreadManager") { } @@ -15,8 +14,6 @@ PPCThreadManager::~PPCThreadManager() void PPCThreadManager::Close() { - if(IsAlive()) Stop(); - while(m_threads.GetCount()) RemoveThread(m_threads[0].GetId()); } @@ -29,6 +26,7 @@ PPCThread& PPCThreadManager::AddThread(bool isPPU) ); m_threads.Add(new_thread); + wxGetApp().SendDbgCommand(DID_CREATE_THREAD, new_thread); return *new_thread; } @@ -39,6 +37,7 @@ void PPCThreadManager::RemoveThread(const u32 id) { if(m_threads[i].GetId() != id) continue; + wxGetApp().SendDbgCommand(DID_REMOVE_THREAD, &m_threads[i]); m_threads[i].Close(); m_threads.RemoveAt(i); @@ -62,19 +61,20 @@ s32 PPCThreadManager::GetThreadNumById(bool isPPU, u32 id) return -1; } -void PPCThreadManager::Exec() +PPCThread* PPCThreadManager::GetThread(u32 id) { - Start(); + for(u32 i=0; i m_ppu_threads; @@ -19,8 +19,8 @@ public: ArrayF& GetThreads() { return m_threads; } s32 GetThreadNumById(bool isPPU, u32 id); + PPCThread* GetThread(u32 id); //IdManager& GetIDs() {return m_threads_id;} void Exec(); - virtual void Task(); }; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUDecoder.h b/rpcs3/Emu/Cell/PPUDecoder.h index 1d759de82e..1b314972cc 100644 --- a/rpcs3/Emu/Cell/PPUDecoder.h +++ b/rpcs3/Emu/Cell/PPUDecoder.h @@ -10,6 +10,12 @@ switch(temp)\ { +#define START_OPCODES_SUB_GROUP(reg) \ + default:\ + temp=##reg##;\ + switch(temp)\ + { + #define END_OPCODES_GROUP(group) \ default:\ m_op.UNK(m_code, opcode, temp);\ @@ -17,6 +23,15 @@ }\ break +#define END_OPCODES_SUB_GROUP() \ + default:\ + m_op.UNK(m_code, opcode, temp);\ + break;\ + } +#define END_OPCODES_ND_GROUP(group) \ + } \ + break; + #define ADD_OPCODE(name, ...) case(##name##):m_op.##name##(__VA_ARGS__); break class PPU_Decoder : public Decoder @@ -36,6 +51,9 @@ class PPU_Decoder : public Decoder //This field is used to specify a special-purpose register for the mtspr and mfspr instructions OP_REG SPR() const { return GetField(11, 20); } + // + OP_REG VS() const { return GetField(6, 10); } + // OP_REG VD() const { return GetField(6, 10); } @@ -45,6 +63,20 @@ class PPU_Decoder : public Decoder // OP_REG VB() const { return GetField(16, 20); } + // + OP_REG VC() const { return GetField(21, 25); } + + // + OP_uIMM VUIMM() const { return GetField(11, 15); } + + // + OP_sIMM VSIMM() const { int i5 = GetField(11, 15); + if(i5 & 0x10) return i5 - 0x20; + return i5; } + + // + OP_uIMM VSH() const { return GetField(22, 25); } + //This field is used to specify a GPR to be used as a destination OP_REG RD() const { return GetField(6, 10); } @@ -174,8 +206,8 @@ class PPU_Decoder : public Decoder //This field is used to specify an FPR as a source OP_REG FRC() const { return GetField(21, 25); } - // - OP_REG FXM() const { return GetField(12, 19); } + //This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction. + OP_REG CRM() const { return GetField(12, 19); } // const s32 SYS() const { return GetField(6, 31); } @@ -211,6 +243,8 @@ class PPU_Decoder : public Decoder //Primary opcode field OP_uIMM OPCD() const { return GetField(0, 5); } + + OP_uIMM STRM() const { return GetField(9, 10); } __forceinline u32 GetField(const u32 p) const { @@ -234,24 +268,178 @@ public: virtual void Decode(const u32 code) { - if(code == 0) - { - m_op.NULL_OP(); - return; - } - m_code = code; - u32 opcode, temp; + using namespace PPU_opcodes; + static u32 opcode, temp; + switch((opcode = OPCD())) { - ADD_OPCODE(TDI, TO(), RA(), simm16()); ADD_OPCODE(TWI, TO(), RA(), simm16()); - START_OPCODES_GROUP(G_04, ((m_code >> 1) & 0x3ff)) - ADD_OPCODE(VXOR, VD(), VA(), VB()); - END_OPCODES_GROUP(G_04); + START_OPCODES_GROUP(G_04, m_code & 0x3f) + ADD_OPCODE(VMADDFP, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMHADDSHS, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMHRADDSHS, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMLADDUHM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMMBM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMSHM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMSHS, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMUBM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMUHM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VMSUMUHS, VD(), VA(), VB(), VC()); + ADD_OPCODE(VNMSUBFP, VD(), VA(), VB(), VC()); + ADD_OPCODE(VPERM, VD(), VA(), VB(), VC()); + ADD_OPCODE(VSEL, VD(), VA(), VB(), VC()); + ADD_OPCODE(VSLDOI, VD(), VA(), VB(), VSH()); + + START_OPCODES_SUB_GROUP(m_code & 0x7ff); + ADD_OPCODE(MFVSCR, VD()); + ADD_OPCODE(MTVSCR, VB()); + ADD_OPCODE(VADDCUW, VD(), VA(), VB()); + ADD_OPCODE(VADDFP, VD(), VA(), VB()); + ADD_OPCODE(VADDSBS, VD(), VA(), VB()); + ADD_OPCODE(VADDSHS, VD(), VA(), VB()); + ADD_OPCODE(VADDSWS, VD(), VA(), VB()); + ADD_OPCODE(VADDUBM, VD(), VA(), VB()); + ADD_OPCODE(VADDUBS, VD(), VA(), VB()); + ADD_OPCODE(VADDUHM, VD(), VA(), VB()); + ADD_OPCODE(VADDUHS, VD(), VA(), VB()); + ADD_OPCODE(VADDUWM, VD(), VA(), VB()); + ADD_OPCODE(VADDUWS, VD(), VA(), VB()); + ADD_OPCODE(VAND, VD(), VA(), VB()); + ADD_OPCODE(VANDC, VD(), VA(), VB()); + ADD_OPCODE(VAVGSB, VD(), VA(), VB()); + ADD_OPCODE(VAVGSH, VD(), VA(), VB()); + ADD_OPCODE(VAVGSW, VD(), VA(), VB()); + ADD_OPCODE(VAVGUB, VD(), VA(), VB()); + ADD_OPCODE(VAVGUH, VD(), VA(), VB()); + ADD_OPCODE(VAVGUW, VD(), VA(), VB()); + ADD_OPCODE(VCFSX, VD(), VUIMM(), VB()); + ADD_OPCODE(VCFUX, VD(), VUIMM(), VB()); + ADD_OPCODE(VCMPBFP, VD(), VA(), VB()); + ADD_OPCODE(VCMPBFP_, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQFP, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQFP_, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUB, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUB_, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUH, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUH_, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUW, VD(), VA(), VB()); + ADD_OPCODE(VCMPEQUW_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGEFP, VD(), VA(), VB()); + ADD_OPCODE(VCMPGEFP_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTFP, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTFP_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSB, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSB_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSH, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSH_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSW, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTSW_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUB, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUB_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUH, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUH_, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUW, VD(), VA(), VB()); + ADD_OPCODE(VCMPGTUW_, VD(), VA(), VB()); + ADD_OPCODE(VCTSXS, VD(), VUIMM(), VB()); + ADD_OPCODE(VCTUXS, VD(), VUIMM(), VB()); + ADD_OPCODE(VEXPTEFP, VD(), VB()); + ADD_OPCODE(VLOGEFP, VD(), VB()); + ADD_OPCODE(VMAXFP, VD(), VA(), VB()); + ADD_OPCODE(VMAXSB, VD(), VA(), VB()); + ADD_OPCODE(VMAXSH, VD(), VA(), VB()); + ADD_OPCODE(VMAXSW, VD(), VA(), VB()); + ADD_OPCODE(VMAXUB, VD(), VA(), VB()); + ADD_OPCODE(VMAXUH, VD(), VA(), VB()); + ADD_OPCODE(VMAXUW, VD(), VA(), VB()); + ADD_OPCODE(VMINFP, VD(), VA(), VB()); + ADD_OPCODE(VMINSB, VD(), VA(), VB()); + ADD_OPCODE(VMINSH, VD(), VA(), VB()); + ADD_OPCODE(VMINSW, VD(), VA(), VB()); + ADD_OPCODE(VMINUB, VD(), VA(), VB()); + ADD_OPCODE(VMINUH, VD(), VA(), VB()); + ADD_OPCODE(VMINUW, VD(), VA(), VB()); + ADD_OPCODE(VMRGHB, VD(), VA(), VB()); + ADD_OPCODE(VMRGHH, VD(), VA(), VB()); + ADD_OPCODE(VMRGHW, VD(), VA(), VB()); + ADD_OPCODE(VMRGLB, VD(), VA(), VB()); + ADD_OPCODE(VMRGLH, VD(), VA(), VB()); + ADD_OPCODE(VMRGLW, VD(), VA(), VB()); + ADD_OPCODE(VMULESB, VD(), VA(), VB()); + ADD_OPCODE(VMULESH, VD(), VA(), VB()); + ADD_OPCODE(VMULEUB, VD(), VA(), VB()); + ADD_OPCODE(VMULEUH, VD(), VA(), VB()); + ADD_OPCODE(VMULOSB, VD(), VA(), VB()); + ADD_OPCODE(VMULOSH, VD(), VA(), VB()); + ADD_OPCODE(VMULOUB, VD(), VA(), VB()); + ADD_OPCODE(VMULOUH, VD(), VA(), VB()); + ADD_OPCODE(VNOR, VD(), VA(), VB()); + ADD_OPCODE(VOR, VD(), VA(), VB()); + ADD_OPCODE(VPKPX, VD(), VA(), VB()); + ADD_OPCODE(VPKSHSS, VD(), VA(), VB()); + ADD_OPCODE(VPKSHUS, VD(), VA(), VB()); + ADD_OPCODE(VPKSWSS, VD(), VA(), VB()); + ADD_OPCODE(VPKSWUS, VD(), VA(), VB()); + ADD_OPCODE(VPKUHUM, VD(), VA(), VB()); + ADD_OPCODE(VPKUHUS, VD(), VA(), VB()); + ADD_OPCODE(VPKUWUM, VD(), VA(), VB()); + ADD_OPCODE(VPKUWUS, VD(), VA(), VB()); + ADD_OPCODE(VREFP, VD(), VB()); + ADD_OPCODE(VRFIM, VD(), VB()); + ADD_OPCODE(VRFIN, VD(), VB()); + ADD_OPCODE(VRFIP, VD(), VB()); + ADD_OPCODE(VRFIZ, VD(), VB()); + ADD_OPCODE(VRLB, VD(), VA(), VB()); + ADD_OPCODE(VRLH, VD(), VA(), VB()); + ADD_OPCODE(VRLW, VD(), VA(), VB()); + ADD_OPCODE(VRSQRTEFP, VD(), VB()); + ADD_OPCODE(VSL, VD(), VA(), VB()); + ADD_OPCODE(VSLB, VD(), VA(), VB()); + ADD_OPCODE(VSLH, VD(), VA(), VB()); + ADD_OPCODE(VSLO, VD(), VA(), VB()); + ADD_OPCODE(VSLW, VD(), VA(), VB()); + ADD_OPCODE(VSPLTB, VD(), VUIMM(), VB()); + ADD_OPCODE(VSPLTH, VD(), VUIMM(), VB()); + ADD_OPCODE(VSPLTISB, VD(), VSIMM()); + ADD_OPCODE(VSPLTISH, VD(), VSIMM()); + ADD_OPCODE(VSPLTISW, VD(), VSIMM()); + ADD_OPCODE(VSPLTW, VD(), VUIMM(), VB()); + ADD_OPCODE(VSR, VD(), VA(), VB()); + ADD_OPCODE(VSRAB, VD(), VA(), VB()); + ADD_OPCODE(VSRAH, VD(), VA(), VB()); + ADD_OPCODE(VSRAW, VD(), VA(), VB()); + ADD_OPCODE(VSRB, VD(), VA(), VB()); + ADD_OPCODE(VSRH, VD(), VA(), VB()); + ADD_OPCODE(VSRO, VD(), VA(), VB()); + ADD_OPCODE(VSRW, VD(), VA(), VB()); + ADD_OPCODE(VSUBCUW, VD(), VA(), VB()); + ADD_OPCODE(VSUBFP, VD(), VA(), VB()); + ADD_OPCODE(VSUBSBS, VD(), VA(), VB()); + ADD_OPCODE(VSUBSHS, VD(), VA(), VB()); + ADD_OPCODE(VSUBSWS, VD(), VA(), VB()); + ADD_OPCODE(VSUBUBM, VD(), VA(), VB()); + ADD_OPCODE(VSUBUBS, VD(), VA(), VB()); + ADD_OPCODE(VSUBUHM, VD(), VA(), VB()); + ADD_OPCODE(VSUBUHS, VD(), VA(), VB()); + ADD_OPCODE(VSUBUWM, VD(), VA(), VB()); + ADD_OPCODE(VSUBUWS, VD(), VA(), VB()); + ADD_OPCODE(VSUMSWS, VD(), VA(), VB()); + ADD_OPCODE(VSUM2SWS, VD(), VA(), VB()); + ADD_OPCODE(VSUM4SBS, VD(), VA(), VB()); + ADD_OPCODE(VSUM4SHS, VD(), VA(), VB()); + ADD_OPCODE(VSUM4UBS, VD(), VA(), VB()); + ADD_OPCODE(VUPKHPX, VD(), VB()); + ADD_OPCODE(VUPKHSB, VD(), VB()); + ADD_OPCODE(VUPKHSH, VD(), VB()); + ADD_OPCODE(VUPKLPX, VD(), VB()); + ADD_OPCODE(VUPKLSB, VD(), VB()); + ADD_OPCODE(VUPKLSH, VD(), VB()); + ADD_OPCODE(VXOR, VD(), VA(), VB()); + END_OPCODES_SUB_GROUP(); + END_OPCODES_ND_GROUP(G_04); ADD_OPCODE(MULLI, RD(), RA(), simm16()); ADD_OPCODE(SUBFIC, RD(), RA(), simm16()); @@ -300,12 +488,13 @@ public: START_OPCODES_GROUP(G_1f, GetField(21, 30)) /*0x000*/ADD_OPCODE(CMP, CRFD(), L(), RA(), RB()); /*0x004*/ADD_OPCODE(TW, TO(), RA(), RB()); + /*0x006*/ADD_OPCODE(LVSL, VD(), RA(), RB()); /*0x007*/ADD_OPCODE(LVEBX, VD(), RA(), RB()); /*0x008*/ADD_OPCODE(SUBFC, RD(), RA(), RB(), OE(), RC()); /*0x009*/ADD_OPCODE(MULHDU, RD(), RA(), RB(), RC()); /*0x00a*/ADD_OPCODE(ADDC, RD(), RA(), RB(), OE(), RC()); /*0x00b*/ADD_OPCODE(MULHWU, RD(), RA(), RB(), RC()); - /*0x013*/ADD_OPCODE(MFOCRF, GetField(11), FXM(), RD()); + /*0x013*/ADD_OPCODE(MFOCRF, GetField(11), RD(), CRM()); /*0x014*/ADD_OPCODE(LWARX, RD(), RA(), RB()); /*0x015*/ADD_OPCODE(LDX, RA(), RS(), RB()); /*0x017*/ADD_OPCODE(LWZX, RD(), RA(), RB()); @@ -314,11 +503,13 @@ public: /*0x01b*/ADD_OPCODE(SLD, RA(), RS(), RB(), RC()); /*0x01c*/ADD_OPCODE(AND, RA(), RS(), RB(), RC()); /*0x020*/ADD_OPCODE(CMPL, CRFD(), L(), RA(), RB()); + /*0x026*/ADD_OPCODE(LVSR, VD(), RA(), RB()); /*0x027*/ADD_OPCODE(LVEHX, VD(), RA(), RB()); /*0x028*/ADD_OPCODE(SUBF, RD(), RA(), RB(), OE(), RC()); /*0x036*/ADD_OPCODE(DCBST, RA(), RB()); /*0x03a*/ADD_OPCODE(CNTLZD, RA(), RS(), RC()); /*0x03c*/ADD_OPCODE(ANDC, RA(), RS(), RB(), RC()); + /*0x047*/ADD_OPCODE(LVEWX, VD(), RA(), RB()); /*0x049*/ADD_OPCODE(MULHD, RD(), RA(), RB(), RC()); /*0x04b*/ADD_OPCODE(MULHW, RD(), RA(), RB(), RC()); /*0x054*/ADD_OPCODE(LDARX, RD(), RA(), RB()); @@ -328,17 +519,20 @@ public: /*0x068*/ADD_OPCODE(NEG, RD(), RA(), OE(), RC()); /*0x077*/ADD_OPCODE(LBZUX, RD(), RA(), RB()); /*0x07c*/ADD_OPCODE(NOR, RA(), RS(), RB(), RC()); + /*0x087*/ADD_OPCODE(STVEBX, VS(), RA(), RB()); /*0x088*/ADD_OPCODE(SUBFE, RD(), RA(), RB(), OE(), RC()); /*0x08a*/ADD_OPCODE(ADDE, RD(), RA(), RB(), OE(), RC()); - /*0x090*/ADD_OPCODE(MTOCRF, FXM(), RS()); + /*0x090*/ADD_OPCODE(MTOCRF, CRM(), RS()); /*0x095*/ADD_OPCODE(STDX, RS(), RA(), RB()); /*0x096*/ADD_OPCODE(STWCX_, RS(), RA(), RB()); /*0x097*/ADD_OPCODE(STWX, RS(), RA(), RB()); + /*0x0a7*/ADD_OPCODE(STVEHX, VS(), RA(), RB()); /*0x0b5*/ADD_OPCODE(STDUX, RS(), RA(), RB()); + /*0x0c7*/ADD_OPCODE(STVEWX, VS(), RA(), RB()); /*0x0ca*/ADD_OPCODE(ADDZE, RD(), RA(), OE(), RC()); /*0x0d6*/ADD_OPCODE(STDCX_, RS(), RA(), RB()); /*0x0d7*/ADD_OPCODE(STBX, RS(), RA(), RB()); - /*0x0e7*/ADD_OPCODE(STVX, VD(), RA(), RB()); + /*0x0e7*/ADD_OPCODE(STVX, VS(), RA(), RB()); /*0x0e9*/ADD_OPCODE(MULLD, RD(), RA(), RB(), OE(), RC()); /*0x0ea*/ADD_OPCODE(ADDME, RD(), RA(), OE(), RC()); /*0x0eb*/ADD_OPCODE(MULLW, RD(), RA(), RB(), OE(), RC()); @@ -351,9 +545,12 @@ public: /*0x137*/ADD_OPCODE(LHZUX, RD(), RA(), RB()); /*0x13c*/ADD_OPCODE(XOR, RA(), RS(), RB(), RC()); /*0x153*/ADD_OPCODE(MFSPR, RD(), SPR()); + /*0x156*/ADD_OPCODE(DST, RA(), RB(), STRM(), GetField(6)); /*0x157*/ADD_OPCODE(LHAX, RD(), RA(), RB()); + /*0x167*/ADD_OPCODE(LVXL, VD(), RA(), RB()); /*0x168*/ADD_OPCODE(ABS, RD(), RA(), OE(), RC()); /*0x173*/ADD_OPCODE(MFTB, RD(), SPR()); + /*0x176*/ADD_OPCODE(DSTST, RA(), RB(), STRM(), GetField(6)); /*0x177*/ADD_OPCODE(LHAUX, RD(), RA(), RB()); /*0x197*/ADD_OPCODE(STHX, RS(), RA(), RB()); /*0x19c*/ADD_OPCODE(ORC, RA(), RS(), RB(), RC()); @@ -363,20 +560,30 @@ public: /*0x1cb*/ADD_OPCODE(DIVWU, RD(), RA(), RB(), OE(), RC()); /*0x1d3*/ADD_OPCODE(MTSPR, SPR(), RS()); /*0x1d6*///DCBI + /*0x1dc*/ADD_OPCODE(NAND, RA(), RS(), RB(), RC()); + /*0x1e7*/ADD_OPCODE(STVXL, RS(), RA(), RB()); /*0x1e9*/ADD_OPCODE(DIVD, RD(), RA(), RB(), OE(), RC()); /*0x1eb*/ADD_OPCODE(DIVW, RD(), RA(), RB(), OE(), RC()); + /*0x207*/ADD_OPCODE(LVLX, VD(), RA(), RB()); /*0x216*/ADD_OPCODE(LWBRX, RD(), RA(), RB()); /*0x217*/ADD_OPCODE(LFSX, FRD(), RA(), RB()); /*0x218*/ADD_OPCODE(SRW, RA(), RS(), RB(), RC()); /*0x21b*/ADD_OPCODE(SRD, RA(), RS(), RB(), RC()); + /*0x227*/ADD_OPCODE(LVRX, VD(), RA(), RB()); /*0x237*/ADD_OPCODE(LFSUX, FRD(), RA(), RB()); /*0x256*/ADD_OPCODE(SYNC, GetField(9, 10)); /*0x257*/ADD_OPCODE(LFDX, FRD(), RA(), RB()); /*0x277*/ADD_OPCODE(LFDUX, FRD(), RA(), RB()); + /*0x287*/ADD_OPCODE(STVLX, VS(), RA(), RB()); /*0x297*/ADD_OPCODE(STFSX, RS(), RA(), RB()); + /*0x2a7*/ADD_OPCODE(STVRX, VS(), RA(), RB()); + /*0x2d7*/ADD_OPCODE(STFDX, RS(), RA(), RB()); + /*0x307*/ADD_OPCODE(LVLXL, VD(), RA(), RB()); /*0x316*/ADD_OPCODE(LHBRX, RD(), RA(), RB()); /*0x318*/ADD_OPCODE(SRAW, RA(), RS(), RB(), RC()); - /*0x31A*/ADD_OPCODE(SRAD, RA(), RS(), RB(), RC()); + /*0x31a*/ADD_OPCODE(SRAD, RA(), RS(), RB(), RC()); + /*0x327*/ADD_OPCODE(LVRXL, VD(), RA(), RB()); + /*0x336*/ADD_OPCODE(DSS, STRM(), GetField(6)); /*0x338*/ADD_OPCODE(SRAWI, RA(), RS(), sh(), RC()); /*0x33a*/ADD_OPCODE(SRADI1, RA(), RS(), sh(), RC()); /*0x33b*/ADD_OPCODE(SRADI2, RA(), RS(), sh(), RC()); @@ -431,12 +638,11 @@ public: END_OPCODES_GROUP(G_3b); START_OPCODES_GROUP(G_3e, GetField(30, 31)) - ADD_OPCODE(STD, RS(), RA(), D()); + ADD_OPCODE(STD, RS(), RA(), D()); ADD_OPCODE(STDU, RS(), RA(), DS()); END_OPCODES_GROUP(G_3e); START_OPCODES_GROUP(G_3f, GetField(26, 30)) - ADD_OPCODE(FDIV, FRD(), FRA(), FRB(), RC()); ADD_OPCODE(FSUB, FRD(), FRA(), FRB(), RC()); ADD_OPCODE(FADD, FRD(), FRA(), FRB(), RC()); @@ -450,8 +656,7 @@ public: ADD_OPCODE(FNMADD, FRD(), FRA(), FRC(), FRB(), RC()); ADD_OPCODE(FCMPO, CRFD(), FRA(), FRB()); - default: - START_OPCODES_GROUP(0x8, GetField(21, 30)) + START_OPCODES_SUB_GROUP(GetField(21, 30)) ADD_OPCODE(FCMPU, CRFD(), FRA(), FRB()); ADD_OPCODE(FRSP, FRD(), FRB(), RC()); ADD_OPCODE(FCTIW, FRD(), FRB(), RC()); @@ -470,18 +675,26 @@ public: ADD_OPCODE(MTFSFI, CRFD(), I(), RC()); ADD_OPCODE(MFFS, FRD(), RC()); ADD_OPCODE(MTFSF, FLM(), FRB(), RC()); - END_OPCODES_GROUP(0x8); - break; - } - break; - //END_OPCODES_GROUP(G_3f); + END_OPCODES_SUB_GROUP(); + END_OPCODES_ND_GROUP(G_3f); - default: m_op.UNK(m_code, opcode, opcode); break; + default: + if(!code) + { + m_op.NULL_OP(); + break; + } + + m_op.UNK(m_code, opcode, opcode); + break; } } }; #undef START_OPCODES_GROUP +#undef START_OPCODES_SUB_GROUP #undef ADD_OPCODE #undef ADD_NULL_OPCODE -#undef END_OPCODES_GROUP \ No newline at end of file +#undef END_OPCODES_GROUP +#undef END_OPCODES_ND_GROUP +#undef END_OPCODES_SUB_GROUP \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUDisAsm.h b/rpcs3/Emu/Cell/PPUDisAsm.h index e84cbc362a..438bb49647 100644 --- a/rpcs3/Emu/Cell/PPUDisAsm.h +++ b/rpcs3/Emu/Cell/PPUDisAsm.h @@ -33,7 +33,7 @@ public: } private: - virtual void Exit() + void Exit() { if(m_mode == NormalMode && !disasm_frame->exit) { @@ -41,63 +41,687 @@ private: } } - virtual u32 DisAsmBranchTarget(const s32 imm) + u32 DisAsmBranchTarget(const s32 imm) { return branchTarget(m_mode == NormalMode ? CPU.PC : dump_pc, imm); } private: - virtual void NULL_OP() + void NULL_OP() { Write( "null" ); } - virtual void NOP() + void NOP() { Write( "nop" ); } - virtual void TDI(OP_REG to, OP_REG ra, OP_sIMM simm16) + void TDI(OP_REG to, OP_REG ra, OP_sIMM simm16) { DisAsm_INT1_R1_IMM("tdi", to, ra, simm16); } - virtual void TWI(OP_REG to, OP_REG ra, OP_sIMM simm16) + void TWI(OP_REG to, OP_REG ra, OP_sIMM simm16) { DisAsm_INT1_R1_IMM("twi", to, ra, simm16); } START_OPCODES_GROUP(G_04) - virtual void VXOR(OP_REG vrd, OP_REG vra, OP_REG vrb) + void MFVSCR(OP_REG vd) { - DisAsm_V3("vxor", vrd, vra, vrb); + DisAsm_V1("mfvscr", vd); + } + void MTVSCR(OP_REG vb) + { + DisAsm_V1("mtvscr", vb); + } + void VADDCUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddcuw", vd, va, vb); + } + void VADDFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddfp", vd, va, vb); + } + void VADDSBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddsbs", vd, va, vb); + } + void VADDSHS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddshs", vd, va, vb); + } + void VADDSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddsws", vd, va, vb); + } + void VADDUBM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddubm", vd, va, vb); + } + void VADDUBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vaddubs", vd, va, vb); + } + void VADDUHM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vadduhm", vd, va, vb); + } + void VADDUHS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vadduhs", vd, va, vb); + } + void VADDUWM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vadduwm", vd, va, vb); + } + void VADDUWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vadduws", vd, va, vb); + } + void VAND(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vand", vd, va, vb); + } + void VANDC(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vandc", vd, va, vb); + } + void VAVGSB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavgsb", vd, va, vb); + } + void VAVGSH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavgsh", vd, va, vb); + } + void VAVGSW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavgsw", vd, va, vb); + } + void VAVGUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavgub", vd, va, vb); + } + void VAVGUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavguh", vd, va, vb); + } + void VAVGUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vavguw", vd, va, vb); + } + void VCFSX(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vcfsx", vd, vb, uimm5); + } + void VCFUX(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vcfux", vd, vb, uimm5); + } + void VCMPBFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpbfp", vd, va, vb); + } + void VCMPBFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpbfp.", vd, va, vb); + } + void VCMPEQFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpeqfp", vd, va, vb); + } + void VCMPEQFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpeqfp.", vd, va, vb); + } + void VCMPEQUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequb", vd, va, vb); + } + void VCMPEQUB_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequb.", vd, va, vb); + } + void VCMPEQUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequh", vd, va, vb); + } + void VCMPEQUH_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequh.", vd, va, vb); + } + void VCMPEQUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequw", vd, va, vb); + } + void VCMPEQUW_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpequw.", vd, va, vb); + } + void VCMPGEFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgefp", vd, va, vb); + } + void VCMPGEFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgefp.", vd, va, vb); + } + void VCMPGTFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtfp", vd, va, vb); + } + void VCMPGTFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtfp.", vd, va, vb); + } + void VCMPGTSB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsb", vd, va, vb); + } + void VCMPGTSB_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsb.", vd, va, vb); + } + void VCMPGTSH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsh", vd, va, vb); + } + void VCMPGTSH_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsh.", vd, va, vb); + } + void VCMPGTSW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsw", vd, va, vb); + } + void VCMPGTSW_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtsw.", vd, va, vb); + } + void VCMPGTUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtub", vd, va, vb); + } + void VCMPGTUB_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtub.", vd, va, vb); + } + void VCMPGTUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtuh", vd, va, vb); + } + void VCMPGTUH_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtuh.", vd, va, vb); + } + void VCMPGTUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtuw", vd, va, vb); + } + void VCMPGTUW_(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vcmpgtuw.", vd, va, vb); + } + void VCTSXS(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vctsxs", vd, vb, uimm5); + } + void VCTUXS(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vctuxs", vd, vb, uimm5); + } + void VEXPTEFP(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vexptefp", vd, vb); + } + void VLOGEFP(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vlogefp", vd, vb); + } + void VMADDFP(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmaddfp", vd, va, vb, vc); + } + void VMAXFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxfp", vd, va, vb); + } + void VMAXSB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxsb", vd, va, vb); + } + void VMAXSH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxsh", vd, va, vb); + } + void VMAXSW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxsw", vd, va, vb); + } + void VMAXUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxub", vd, va, vb); + } + void VMAXUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxuh", vd, va, vb); + } + void VMAXUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmaxuw", vd, va, vb); + } + void VMHADDSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmhaddshs", vd, va, vb, vc); + } + void VMHRADDSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmhraddshs", vd, va, vb, vc); + } + void VMINFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminfp", vd, va, vb); + } + void VMINSB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminsb", vd, va, vb); + } + void VMINSH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminsh", vd, va, vb); + } + void VMINSW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminsw", vd, va, vb); + } + void VMINUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminub", vd, va, vb); + } + void VMINUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminuh", vd, va, vb); + } + void VMINUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vminuw", vd, va, vb); + } + void VMLADDUHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmladduhm", vd, va, vb, vc); + } + void VMRGHB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrghb", vd, va, vb); + } + void VMRGHH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrghh", vd, va, vb); + } + void VMRGHW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrghw", vd, va, vb); + } + void VMRGLB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrglb", vd, va, vb); + } + void VMRGLH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrglh", vd, va, vb); + } + void VMRGLW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmrglw", vd, va, vb); + } + void VMSUMMBM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsummbm", vd, va, vb, vc); + } + void VMSUMSHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsumshm", vd, va, vb, vc); + } + void VMSUMSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsumshs", vd, va, vb, vc); + } + void VMSUMUBM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsumubm", vd, va, vb, vc); + } + void VMSUMUHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsumuhm", vd, va, vb, vc); + } + void VMSUMUHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vmsumuhs", vd, va, vb, vc); + } + void VMULESB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmulesb", vd, va, vb); + } + void VMULESH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmulesh", vd, va, vb); + } + void VMULEUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmuleub", vd, va, vb); + } + void VMULEUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmuleuh", vd, va, vb); + } + void VMULOSB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmulosb", vd, va, vb); + } + void VMULOSH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmulosh", vd, va, vb); + } + void VMULOUB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmuloub", vd, va, vb); + } + void VMULOUH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vmulouh", vd, va, vb); + } + void VNMSUBFP(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vnmsubfp", vd, va, vb, vc); + } + void VNOR(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vnor", vd, va, vb); + } + void VOR(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vor", vd, va, vb); + } + void VPERM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vperm", vd, va, vb, vc); + } + void VPKPX(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkpx", vd, va, vb); + } + void VPKSHSS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkshss", vd, va, vb); + } + void VPKSHUS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkshus", vd, va, vb); + } + void VPKSWSS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkswss", vd, va, vb); + } + void VPKSWUS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkswus", vd, va, vb); + } + void VPKUHUM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkuhum", vd, va, vb); + } + void VPKUHUS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkuhus", vd, va, vb); + } + void VPKUWUM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkuwum", vd, va, vb); + } + void VPKUWUS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vpkuwus", vd, va, vb); + } + void VREFP(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrefp", vd, vb); + } + void VRFIM(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrfim", vd, vb); + } + void VRFIN(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrfin", vd, vb); + } + void VRFIP(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrfip", vd, vb); + } + void VRFIZ(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrfiz", vd, vb); + } + void VRLB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vrlb", vd, va, vb); + } + void VRLH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vrlh", vd, va, vb); + } + void VRLW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vrlw", vd, va, vb); + } + void VRSQRTEFP(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vrsqrtefp", vd, vb); + } + void VSEL(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + DisAsm_V4("vsel", vd, va, vb, vc); + } + void VSL(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsl", vd, va, vb); + } + void VSLB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vslb", vd, va, vb); + } + void VSLDOI(OP_REG vd, OP_REG va, OP_REG vb, OP_uIMM sh) + { + DisAsm_V3_UIMM("vsldoi", vd, va, vb, sh); + } + void VSLH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vslh", vd, va, vb); + } + void VSLO(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vslo", vd, va, vb); + } + void VSLW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vslw", vd, va, vb); + } + void VSPLTB(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vspltb", vd, vb, uimm5); + } + void VSPLTH(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vsplth", vd, vb, uimm5); + } + void VSPLTISB(OP_REG vd, OP_sIMM simm5) + { + DisAsm_V1_SIMM("vspltisb", vd, simm5); + } + void VSPLTISH(OP_REG vd, OP_sIMM simm5) + { + DisAsm_V1_SIMM("vspltish", vd, simm5); + } + void VSPLTISW(OP_REG vd, OP_sIMM simm5) + { + DisAsm_V1_SIMM("vspltisw", vd, simm5); + } + void VSPLTW(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + DisAsm_V2_UIMM("vspltw", vd, vb, uimm5); + } + void VSR(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsr", vd, va, vb); + } + void VSRAB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsrab", vd, va, vb); + } + void VSRAH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsrah", vd, va, vb); + } + void VSRAW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsraw", vd, va, vb); + } + void VSRB(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsrb", vd, va, vb); + } + void VSRH(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsrh", vd, va, vb); + } + void VSRO(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsro", vd, va, vb); + } + void VSRW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsrw", vd, va, vb); + } + void VSUBCUW(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubcuw", vd, va, vb); + } + void VSUBFP(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubfp", vd, va, vb); + } + void VSUBSBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubsbs", vd, va, vb); + } + void VSUBSHS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubshs", vd, va, vb); + } + void VSUBSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubsws", vd, va, vb); + } + void VSUBUBM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsububm", vd, va, vb); + } + void VSUBUBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsububs", vd, va, vb); + } + void VSUBUHM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubuhm", vd, va, vb); + } + void VSUBUHS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubuhs", vd, va, vb); + } + void VSUBUWM(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubuwm", vd, va, vb); + } + void VSUBUWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsubuws", vd, va, vb); + } + void VSUMSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsumsws", vd, va, vb); + } + void VSUM2SWS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsum2sws", vd, va, vb); + } + void VSUM4SBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsum4sbs", vd, va, vb); + } + void VSUM4SHS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsum4shs", vd, va, vb); + } + void VSUM4UBS(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vsum4ubs", vd, va, vb); + } + void VUPKHPX(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupkhpx", vd, vb); + } + void VUPKHSB(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupkhsb", vd, vb); + } + void VUPKHSH(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupkhsh", vd, vb); + } + void VUPKLPX(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupklpx", vd, vb); + } + void VUPKLSB(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupklsb", vd, vb); + } + void VUPKLSH(OP_REG vd, OP_REG vb) + { + DisAsm_V2("vupklsh", vd, vb); + } + void VXOR(OP_REG vd, OP_REG va, OP_REG vb) + { + DisAsm_V3("vxor", vd, va, vb); } END_OPCODES_GROUP(G_04); - virtual void MULLI(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void MULLI(OP_REG rd, OP_REG ra, OP_sIMM simm16) { DisAsm_R2_IMM("mulli", rd, ra, simm16); } - virtual void SUBFIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void SUBFIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) { DisAsm_R2_IMM("subfic", rd, ra, simm16); } - virtual void CMPLI(OP_REG crfd, OP_REG l, OP_REG ra, OP_uIMM uimm16) + void CMPLI(OP_REG crfd, OP_REG l, OP_REG ra, OP_uIMM uimm16) { DisAsm_CR1_R1_IMM(wxString::Format("cmpl%si", l ? "d" : "w"), crfd, ra, uimm16); } - virtual void CMPI(OP_REG crfd, OP_REG l, OP_REG ra, OP_sIMM simm16) + void CMPI(OP_REG crfd, OP_REG l, OP_REG ra, OP_sIMM simm16) { DisAsm_CR1_R1_IMM(wxString::Format("cmp%si", l ? "d" : "w"), crfd, ra, simm16); } - virtual void ADDIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) { DisAsm_R2_IMM("addic", rd, ra, simm16); } - virtual void ADDIC_(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIC_(OP_REG rd, OP_REG ra, OP_sIMM simm16) { DisAsm_R2_IMM("addic.", rd, ra, simm16); } - virtual void ADDI(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDI(OP_REG rd, OP_REG ra, OP_sIMM simm16) { if(ra == 0) { @@ -108,7 +732,7 @@ private: DisAsm_R2_IMM("addi", rd, ra, simm16); } } - virtual void ADDIS(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIS(OP_REG rd, OP_REG ra, OP_sIMM simm16) { if(ra == 0) { @@ -120,7 +744,7 @@ private: } } - virtual void BC(OP_REG bo, OP_REG bi, OP_sIMM bd, OP_REG aa, OP_REG lk) + void BC(OP_REG bo, OP_REG bi, OP_sIMM bd, OP_REG aa, OP_REG lk) { if(m_mode == CompilerElfMode) { @@ -216,7 +840,7 @@ private: Write(wxString::Format("bc [%x:%x:%x:%x:%x], cr%d[%x], 0x%x, %d, %d", bo0, bo1, bo2, bo3, bo4, bi/4, bi%4, bd, aa, lk)); } - virtual void SC(const s32 sc_code) + void SC(const s32 sc_code) { switch(sc_code) { @@ -226,7 +850,7 @@ private: default: Write(wxString::Format("Unknown sc: %x", sc_code)); } } - virtual void B(OP_sIMM ll, OP_REG aa, OP_REG lk) + void B(OP_sIMM ll, OP_REG aa, OP_REG lk) { if(m_mode == CompilerElfMode) { @@ -255,11 +879,11 @@ private: } START_OPCODES_GROUP(G_13) - virtual void MCRF(OP_REG crfd, OP_REG crfs) + void MCRF(OP_REG crfd, OP_REG crfs) { DisAsm_CR2("mcrf", crfd, crfs); } - virtual void BCLR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) + void BCLR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) { const u8 bo0 = (bo & 0x10) ? 1 : 0; const u8 bo1 = (bo & 0x08) ? 1 : 0; @@ -269,43 +893,43 @@ private: if(bo0 && !bo1 && bo2 && !bo3) {Write("blr"); return;} Write(wxString::Format("bclr [%x:%x:%x:%x], cr%d[%x], %d, %d", bo0, bo1, bo2, bo3, bi/4, bi%4, bh, lk)); } - virtual void CRNOR(OP_REG bt, OP_REG ba, OP_REG bb) + void CRNOR(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crnor", bt, ba, bb); } - virtual void CRANDC(OP_REG bt, OP_REG ba, OP_REG bb) + void CRANDC(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crandc", bt, ba, bb); } - virtual void ISYNC() + void ISYNC() { Write("isync"); } - virtual void CRXOR(OP_REG bt, OP_REG ba, OP_REG bb) + void CRXOR(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crxor", bt, ba, bb); } - virtual void CRNAND(OP_REG bt, OP_REG ba, OP_REG bb) + void CRNAND(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crnand", bt, ba, bb); } - virtual void CRAND(OP_REG bt, OP_REG ba, OP_REG bb) + void CRAND(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crand", bt, ba, bb); } - virtual void CREQV(OP_REG bt, OP_REG ba, OP_REG bb) + void CREQV(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("creqv", bt, ba, bb); } - virtual void CRORC(OP_REG bt, OP_REG ba, OP_REG bb) + void CRORC(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("crorc", bt, ba, bb); } - virtual void CROR(OP_REG bt, OP_REG ba, OP_REG bb) + void CROR(OP_REG bt, OP_REG ba, OP_REG bb) { DisAsm_INT3("cror", bt, ba, bb); } - virtual void BCCTR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) + void BCCTR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) { switch(lk) { @@ -313,30 +937,30 @@ private: case 1: DisAsm_INT3("bcctrl", bo, bi, bh); break; } } - virtual void BCTR() + void BCTR() { Write("bctr"); } - virtual void BCTRL() + void BCTRL() { Write("bctrl"); } END_OPCODES_GROUP(G_13); - virtual void RLWIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) + void RLWIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) { DisAsm_R2_INT3_RC("rlwimi", ra, rs, sh, mb, me, rc); } - virtual void RLWINM(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) + void RLWINM(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) { DisAsm_R2_INT3_RC("rlwinm", ra, rs, sh, mb, me, rc); } - virtual void RLWNM(OP_REG ra, OP_REG rs, OP_REG rb, OP_REG MB, OP_REG ME, bool rc) + void RLWNM(OP_REG ra, OP_REG rs, OP_REG rb, OP_REG MB, OP_REG ME, bool rc) { DisAsm_R3_INT2_RC("rlwnm", ra, rs, rb, MB, ME, rc); } - virtual void ORI(OP_REG rs, OP_REG ra, OP_uIMM uimm16) + void ORI(OP_REG rs, OP_REG ra, OP_uIMM uimm16) { if(rs == 0 && ra == 0 && uimm16 == 0) { @@ -345,7 +969,7 @@ private: } DisAsm_R2_IMM("ori", rs, ra, uimm16); } - virtual void ORIS(OP_REG rs, OP_REG ra, OP_uIMM uimm16) + void ORIS(OP_REG rs, OP_REG ra, OP_uIMM uimm16) { if(rs == 0 && ra == 0 && uimm16 == 0) { @@ -354,25 +978,25 @@ private: } DisAsm_R2_IMM("oris", rs, ra, uimm16); } - virtual void XORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void XORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { DisAsm_R2_IMM("xori", ra, rs, uimm16); } - virtual void XORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void XORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { DisAsm_R2_IMM("xoris", ra, rs, uimm16); } - virtual void ANDI_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ANDI_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { DisAsm_R2_IMM("andi.", ra, rs, uimm16); } - virtual void ANDIS_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ANDIS_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { DisAsm_R2_IMM("andis.", ra, rs, uimm16); } START_OPCODES_GROUP(G_1e) - virtual void RLDICL(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDICL(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { if(sh == 0) { @@ -391,153 +1015,161 @@ private: DisAsm_R2_INT2_RC("rldicl", ra, rs, sh, mb, rc); } } - virtual void RLDICR(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG me, bool rc) + void RLDICR(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG me, bool rc) { DisAsm_R2_INT2_RC("rldicr", ra, rs, sh, me, rc); } - virtual void RLDIC(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDIC(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { DisAsm_R2_INT2_RC("rldic", ra, rs, sh, mb, rc); } - virtual void RLDIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { DisAsm_R2_INT2_RC("rldimi", ra, rs, sh, mb, rc); } END_OPCODES_GROUP(G_1e); START_OPCODES_GROUP(G_1f) - virtual void CMP(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) + void CMP(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) { DisAsm_CR1_R2(wxString::Format("cmp%s", l ? "d" : "w"), crfd, ra, rb); } - virtual void TW(OP_REG to, OP_REG ra, OP_REG rb) + void TW(OP_REG to, OP_REG ra, OP_REG rb) { DisAsm_INT1_R2("tw", to, ra, rb); } - virtual void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVSL(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvsl", vd, ra, rb); + } + void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb) { DisAsm_V1_R2("lvebx", vd, ra, rb); } - virtual void SUBFC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void SUBFC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("subfc", rd, ra, rb, oe, rc); } - virtual void ADDC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADDC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("addc", rd, ra, rb, oe, rc); } - virtual void MULHDU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHDU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { DisAsm_R3_RC("mulhdu", rd, ra, rb, rc); } - virtual void MULHWU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHWU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { DisAsm_R3_RC("mulhwu", rd, ra, rb, rc); } - virtual void MFOCRF(OP_REG a, OP_REG fxm, OP_REG rd) + void MFOCRF(OP_uIMM a, OP_REG rd, OP_uIMM crm) { if(a) { - DisAsm_R1_IMM("mfocrf", rd, fxm); + DisAsm_R1_IMM("mfocrf", rd, crm); } else { DisAsm_R1("mfcr", rd); } } - virtual void LWARX(OP_REG rd, OP_REG ra, OP_REG rb) + void LWARX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lwarx", rd, ra, rb); } - virtual void LDX(OP_REG ra, OP_REG rs, OP_REG rb) + void LDX(OP_REG ra, OP_REG rs, OP_REG rb) { DisAsm_R3("ldx", ra, rs, rb); } - virtual void LWZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LWZX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lwzx", rd, ra, rb); } - virtual void SLW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SLW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("slw", ra, rs, rb, rc); } - virtual void CNTLZW(OP_REG ra, OP_REG rs, bool rc) + void CNTLZW(OP_REG ra, OP_REG rs, bool rc) { DisAsm_R2_RC("cntlzw", ra, rs, rc); } - virtual void SLD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SLD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("sld", ra, rs, rb, rc); } - virtual void AND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void AND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("and", ra, rs, rb, rc); } - virtual void CMPL(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) + void CMPL(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) { DisAsm_CR1_R2(wxString::Format("cmpl%s", l ? "d" : "w"), crfd, ra, rb); } - virtual void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVSR(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvsr", vd, ra, rb); + } + void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb) { DisAsm_V1_R2("lvehx", vd, ra, rb); } - virtual void SUBF(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void SUBF(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("subf", rd, ra, rb, oe, rc); } - virtual void LDUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LDUX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("ldux", rd, ra, rb); } - virtual void DCBST(OP_REG ra, OP_REG rb) + void DCBST(OP_REG ra, OP_REG rb) { DisAsm_R2("dcbst", ra, rb); } - virtual void CNTLZD(OP_REG ra, OP_REG rs, bool rc) + void CNTLZD(OP_REG ra, OP_REG rs, bool rc) { DisAsm_R2_RC("cntlzd", ra, rs, rc); } - virtual void ANDC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void ANDC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("andc", ra, rs, rb, rc); } - virtual void LVEWX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVEWX(OP_REG vd, OP_REG ra, OP_REG rb) { DisAsm_V1_R2("lvewx", vd, ra, rb); } - virtual void MULHD(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHD(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { DisAsm_R3_RC("mulhd", rd, ra, rb, rc); } - virtual void MULHW(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHW(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { DisAsm_R3_RC("mulhw", rd, ra, rb, rc); } - virtual void LDARX(OP_REG rd, OP_REG ra, OP_REG rb) + void LDARX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("ldarx", rd, ra, rb); } - virtual void DCBF(OP_REG ra, OP_REG rb) + void DCBF(OP_REG ra, OP_REG rb) { DisAsm_R2("dcbf", ra, rb); } - virtual void LBZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LBZX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lbzx", rd, ra, rb); } - virtual void LVX(OP_REG vrd, OP_REG ra, OP_REG rb) + void LVX(OP_REG vd, OP_REG ra, OP_REG rb) { - DisAsm_V1_R2("lvx", vrd, ra, rb); + DisAsm_V1_R2("lvx", vd, ra, rb); } - virtual void NEG(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void NEG(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { DisAsm_R2_OE_RC("neg", rd, ra, oe, rc); } - virtual void LBZUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LBZUX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lbzux", rd, ra, rb); } - virtual void NOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void NOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { if(rs == rb) { @@ -548,95 +1180,107 @@ private: DisAsm_R3_RC("nor", ra, rs, rb, rc); } } - virtual void SUBFE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void STVEBX(OP_REG vs, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvebx", vs, ra, rb); + } + void SUBFE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("subfe", rd, ra, rb, oe, rc); } - virtual void ADDE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADDE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("adde", rd, ra, rb, oe, rc); } - virtual void MTOCRF(OP_REG fxm, OP_REG rs) + void MTOCRF(OP_REG crm, OP_REG rs) { - DisAsm_INT1_R1("mtocrf", fxm, rs); + DisAsm_INT1_R1("mtocrf", crm, rs); } - virtual void STDX(OP_REG rs, OP_REG ra, OP_REG rb) + void STDX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stdx.", rs, ra, rb); } - virtual void STWCX_(OP_REG rs, OP_REG ra, OP_REG rb) + void STWCX_(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stwcx.", rs, ra, rb); } - virtual void STWX(OP_REG rs, OP_REG ra, OP_REG rb) + void STWX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stwx", rs, ra, rb); } - virtual void STDUX(OP_REG rs, OP_REG ra, OP_REG rb) + void STVEHX(OP_REG vs, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvehx", vs, ra, rb); + } + void STDUX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stdux", rs, ra, rb); } - virtual void ADDZE(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void STVEWX(OP_REG vs, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvewx", vs, ra, rb); + } + void ADDZE(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { DisAsm_R2_OE_RC("addze", rd, ra, oe, rc); } - virtual void STDCX_(OP_REG rs, OP_REG ra, OP_REG rb) + void STDCX_(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stdcx.", rs, ra, rb); } - virtual void STBX(OP_REG rs, OP_REG ra, OP_REG rb) + void STBX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("stbx", rs, ra, rb); } - virtual void STVX(OP_REG vrd, OP_REG ra, OP_REG rb) + void STVX(OP_REG vd, OP_REG ra, OP_REG rb) { - DisAsm_V1_R2("stvx", vrd, ra, rb); + DisAsm_V1_R2("stvx", vd, ra, rb); } - virtual void MULLD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void MULLD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("mulld", rd, ra, rb, oe, rc); } - virtual void ADDME(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void ADDME(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { DisAsm_R2_OE_RC("addme", rd, ra, oe, rc); } - virtual void MULLW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void MULLW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("mullw", rd, ra, rb, oe, rc); } - virtual void DCBTST(OP_REG th, OP_REG ra, OP_REG rb) + void DCBTST(OP_REG th, OP_REG ra, OP_REG rb) { DisAsm_R3("dcbtst", th, ra, rb); } - virtual void ADD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("add", rd, ra, rb, oe, rc); } - virtual void DCBT(OP_REG ra, OP_REG rb, OP_REG th) + void DCBT(OP_REG ra, OP_REG rb, OP_REG th) { DisAsm_R2("dcbt", ra, rb); } - virtual void LHZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LHZX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lhzx", rd, ra, rb); } - virtual void EQV(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void EQV(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("eqv", ra, rs, rb, rc); } - virtual void ECIWX(OP_REG rd, OP_REG ra, OP_REG rb) + void ECIWX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("eciwx", rd, ra, rb); } - virtual void LHZUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LHZUX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lhzux", rd, ra, rb); } - virtual void XOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void XOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("xor", ra, rs, rb, rc); } - virtual void MFSPR(OP_REG rd, OP_REG spr) + void MFSPR(OP_REG rd, OP_REG spr) { const u32 n = (spr >> 5) | ((spr & 0x1f) << 5); switch(n) @@ -647,15 +1291,30 @@ private: default: DisAsm_R1_IMM("mfspr", rd, spr); break; } } - virtual void LHAX(OP_REG rd, OP_REG ra, OP_REG rb) + void DST(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t) + { + if(t) + { + DisAsm_R2_INT1("dstt", ra, rb, strm); + } + else + { + DisAsm_R2_INT1("dst", ra, rb, strm); + } + } + void LHAX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lhax", rd, ra, rb); } - virtual void ABS(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void LVXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvxl", vd, ra, rb); + } + void ABS(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { DisAsm_R2_OE_RC("abs", rd, ra, oe, rc); } - virtual void MFTB(OP_REG rd, OP_REG spr) + void MFTB(OP_REG rd, OP_REG spr) { const u32 n = (spr >> 5) | ((spr & 0x1f) << 5); switch(n) @@ -665,23 +1324,34 @@ private: default: DisAsm_R1_IMM("mftb", rd, spr); break; } } - virtual void LHAUX(OP_REG rd, OP_REG ra, OP_REG rb) + void DSTST(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t) + { + if(t) + { + DisAsm_R2_INT1("dststt", ra, rb, strm); + } + else + { + DisAsm_R2_INT1("dstst", ra, rb, strm); + } + } + void LHAUX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lhaux", rd, ra, rb); } - virtual void STHX(OP_REG rs, OP_REG ra, OP_REG rb) + void STHX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("sthx", rs, ra, rb); } - virtual void ORC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void ORC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("orc", ra, rs, rb, rc); } - virtual void ECOWX(OP_REG rs, OP_REG ra, OP_REG rb) + void ECOWX(OP_REG rs, OP_REG ra, OP_REG rb) { DisAsm_R3("ecowx", rs, ra, rb); } - virtual void OR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void OR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { if(rs==rb) { @@ -692,15 +1362,15 @@ private: DisAsm_R3_RC("or", ra, rs, rb, rc); } } - virtual void DIVDU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVDU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("divdu", rd, ra, rb, oe, rc); } - virtual void DIVWU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVWU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("divwu", rd, ra, rb, oe, rc); } - virtual void MTSPR(OP_REG spr, OP_REG rs) + void MTSPR(OP_REG spr, OP_REG rs) { const u32 n = (spr & 0x1f) + ((spr >> 5) & 0x1f); @@ -713,375 +1383,430 @@ private: } } /*0x1d6*///DCBI - virtual void DIVD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void NAND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + { + DisAsm_R3_RC("nand", ra, rs, rb, rc); + } + void STVXL(OP_REG vs, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvxl", vs, ra, rb); + } + void DIVD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("divd", rd, ra, rb, oe, rc); } - virtual void DIVW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { DisAsm_R3_OE_RC("divw", rd, ra, rb, oe, rc); } - virtual void LWBRX(OP_REG rd, OP_REG ra, OP_REG rb) + void LVLX(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvlx", vd, ra, rb); + } + void LWBRX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lwbrx", rd, ra, rb); } - virtual void LFSX(OP_REG frd, OP_REG ra, OP_REG rb) + void LFSX(OP_REG frd, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("lfsx", frd, ra, rb); } - virtual void SRW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("srw", ra, rs, rb, rc); } - virtual void SRD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("srd", ra, rs, rb, rc); } - virtual void LFSUX(OP_REG frd, OP_REG ra, OP_REG rb) + void LVRX(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvrx", vd, ra, rb); + } + void LFSUX(OP_REG frd, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("lfsux", frd, ra, rb); } - virtual void SYNC(OP_REG l) + void SYNC(OP_REG l) { DisAsm_INT1("sync", l); } - virtual void LFDX(OP_REG frd, OP_REG ra, OP_REG rb) + void LFDX(OP_REG frd, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("lfdx", frd, ra, rb); } - virtual void LFDUX(OP_REG frd, OP_REG ra, OP_REG rb) + void LFDUX(OP_REG frd, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("lfdux", frd, ra, rb); } - virtual void STFSX(OP_REG frs, OP_REG ra, OP_REG rb) + void STVLX(OP_REG sd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvlx", sd, ra, rb); + } + void STFSX(OP_REG frs, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("stfsx", frs, ra, rb); } - virtual void LHBRX(OP_REG rd, OP_REG ra, OP_REG rb) + void STVRX(OP_REG sd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvrx", sd, ra, rb); + } + void STFDX(OP_REG frs, OP_REG ra, OP_REG rb) + { + DisAsm_F1_R2("stfdx", frs, ra, rb); + } + void LVLXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvlxl", vd, ra, rb); + } + void LHBRX(OP_REG rd, OP_REG ra, OP_REG rb) { DisAsm_R3("lhbrx", rd, ra, rb); } - virtual void SRAW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRAW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("sraw", ra, rs, rb, rc); } - virtual void SRAD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRAD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { DisAsm_R3_RC("srad", ra, rs, rb, rc); } - virtual void SRAWI(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void LVRXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("lvrxl", vd, ra, rb); + } + void DSS(OP_uIMM strm, OP_uIMM a) + { + if(a) + { + Write("dssall"); + } + else + { + DisAsm_INT1("dss", strm); + } + } + void SRAWI(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { DisAsm_R2_INT1_RC("srawi", ra, rs, sh, rc); } - virtual void SRADI1(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void SRADI1(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { DisAsm_R2_INT1_RC("sradi", ra, rs, sh, rc); } - virtual void SRADI2(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void SRADI2(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { DisAsm_R2_INT1_RC("sradi", ra, rs, sh, rc); } - virtual void EIEIO() + void EIEIO() { Write("eieio"); } - virtual void EXTSH(OP_REG ra, OP_REG rs, bool rc) + void STVLXL(OP_REG sd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvlxl", sd, ra, rb); + } + void EXTSH(OP_REG ra, OP_REG rs, bool rc) { DisAsm_R2_RC("extsh", ra, rs, rc); } - virtual void EXTSB(OP_REG ra, OP_REG rs, bool rc) + void STVRXL(OP_REG sd, OP_REG ra, OP_REG rb) + { + DisAsm_V1_R2("stvrxl", sd, ra, rb); + } + void EXTSB(OP_REG ra, OP_REG rs, bool rc) { DisAsm_R2_RC("extsb", ra, rs, rc); } - virtual void STFIWX(OP_REG frs, OP_REG ra, OP_REG rb) + void STFIWX(OP_REG frs, OP_REG ra, OP_REG rb) { DisAsm_F1_R2("stfiwx", frs, ra, rb); } - virtual void EXTSW(OP_REG ra, OP_REG rs, bool rc) + void EXTSW(OP_REG ra, OP_REG rs, bool rc) { DisAsm_R2_RC("extsw", ra, rs, rc); } /*0x3d6*///ICBI - virtual void DCBZ(OP_REG ra, OP_REG rs) + void DCBZ(OP_REG ra, OP_REG rs) { DisAsm_R2("dcbz", ra, rs); } END_OPCODES_GROUP(G_1f); - virtual void LWZ(OP_REG rd, OP_REG ra, OP_sIMM d) + void LWZ(OP_REG rd, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lwz", rd, ra, d); } - virtual void LWZU(OP_REG rd, OP_REG ra, OP_sIMM d) + void LWZU(OP_REG rd, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lwzu", rd, ra, d); } - virtual void LBZ(OP_REG rd, OP_REG ra, OP_sIMM d) + void LBZ(OP_REG rd, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lbz", rd, ra, d); } - virtual void LBZU(OP_REG rd, OP_REG ra, OP_sIMM d) + void LBZU(OP_REG rd, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lbzu", rd, ra, d); } - virtual void STW(OP_REG rs, OP_REG ra, OP_sIMM d) + void STW(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("stw", rs, ra, d); } - virtual void STWU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STWU(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("stwu", rs, ra, d); } - virtual void STB(OP_REG rs, OP_REG ra, OP_sIMM d) + void STB(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("stb", rs, ra, d); } - virtual void STBU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STBU(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("stbu", rs, ra, d); } - virtual void LHZ(OP_REG rs, OP_REG ra, OP_sIMM d) + void LHZ(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lhz", rs, ra, d); } - virtual void LHZU(OP_REG rs, OP_REG ra, OP_sIMM d) + void LHZU(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lhzu", rs, ra, d); } - virtual void STH(OP_REG rs, OP_REG ra, OP_sIMM d) + void STH(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("sth", rs, ra, d); } - virtual void STHU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STHU(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("sthu", rs, ra, d); } - virtual void LMW(OP_REG rd, OP_REG ra, OP_sIMM d) + void LMW(OP_REG rd, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("lmw", rd, ra, d); } - virtual void STMW(OP_REG rs, OP_REG ra, OP_sIMM d) + void STMW(OP_REG rs, OP_REG ra, OP_sIMM d) { DisAsm_R2_IMM("stmw", rs, ra, d); } - virtual void LFS(OP_REG frd, OP_REG ra, OP_sIMM d) + void LFS(OP_REG frd, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("lfs", frd, d, ra); } - virtual void LFSU(OP_REG frd, OP_REG ra, OP_sIMM ds) + void LFSU(OP_REG frd, OP_REG ra, OP_sIMM ds) { DisAsm_F1_IMM_R1("lfsu", frd, ds, ra); } - virtual void LFD(OP_REG frd, OP_REG ra, OP_sIMM d) + void LFD(OP_REG frd, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("lfd", frd, d, ra); } - virtual void LFDU(OP_REG frd, OP_REG ra, OP_sIMM ds) + void LFDU(OP_REG frd, OP_REG ra, OP_sIMM ds) { DisAsm_F1_IMM_R1("lfdu", frd, ds, ra); } - virtual void STFS(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFS(OP_REG frs, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("stfs", frs, d, ra); } - virtual void STFSU(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFSU(OP_REG frs, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("stfsu", frs, d, ra); } - virtual void STFD(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFD(OP_REG frs, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("stfd", frs, d, ra); } - virtual void STFDU(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFDU(OP_REG frs, OP_REG ra, OP_sIMM d) { DisAsm_F1_IMM_R1("stfdu", frs, d, ra); } START_OPCODES_GROUP(G_3a) - virtual void LD(OP_REG rd, OP_REG ra, OP_sIMM ds) + void LD(OP_REG rd, OP_REG ra, OP_sIMM ds) { DisAsm_R2_IMM("ld", rd, ra, ds); } - virtual void LDU(OP_REG rd, OP_REG ra, OP_sIMM ds) + void LDU(OP_REG rd, OP_REG ra, OP_sIMM ds) { DisAsm_R2_IMM("ldu", rd, ra, ds); } END_OPCODES_GROUP(G_3a); START_OPCODES_GROUP(G_3b) - virtual void FDIVS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FDIVS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fdivs", frd, fra, frb, rc); } - virtual void FSUBS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FSUBS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fsubs", frd, fra, frb, rc); } - virtual void FADDS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FADDS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fadds", frd, fra, frb, rc); } - virtual void FSQRTS(OP_REG frd, OP_REG frb, bool rc) + void FSQRTS(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fsqrts", frd, frb, rc); } - virtual void FRES(OP_REG frd, OP_REG frb, bool rc) + void FRES(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fres", frd, frb, rc); } - virtual void FMULS(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) + void FMULS(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) { DisAsm_F3_RC("fmuls", frd, fra, frc, rc); } - virtual void FMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fmadds", frd, fra, frc, frb, rc); } - virtual void FMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fmsubs", frd, fra, frc, frb, rc); } - virtual void FNMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fnmsubs", frd, fra, frc, frb, rc); } - virtual void FNMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fnmadds", frd, fra, frc, frb, rc); } END_OPCODES_GROUP(G_3b); START_OPCODES_GROUP(G_3e) - virtual void STD(OP_REG rs, OP_REG ra, OP_sIMM ds) + void STD(OP_REG rs, OP_REG ra, OP_sIMM ds) { DisAsm_R2_IMM("std", rs, ra, ds); } - virtual void STDU(OP_REG rs, OP_REG ra, OP_sIMM ds) + void STDU(OP_REG rs, OP_REG ra, OP_sIMM ds) { DisAsm_R2_IMM("stdu", rs, ra, ds); } END_OPCODES_GROUP(G_3e); START_OPCODES_GROUP(G_3f) - virtual void MTFSB1(OP_REG bt, bool rc) + void MTFSB1(OP_REG bt, bool rc) { DisAsm_F1_RC("mtfsb1", bt, rc); } - virtual void MCRFS(OP_REG bf, OP_REG bfa) + void MCRFS(OP_REG bf, OP_REG bfa) { DisAsm_F2("mcrfs", bf, bfa); } - virtual void MTFSB0(OP_REG bt, bool rc) + void MTFSB0(OP_REG bt, bool rc) { DisAsm_F1_RC("mtfsb0", bt, rc); } - virtual void MTFSFI(OP_REG crfd, OP_REG i, bool rc) + void MTFSFI(OP_REG crfd, OP_REG i, bool rc) { DisAsm_F2_RC("mtfsfi", crfd, i, rc); } - virtual void MFFS(OP_REG frd, bool rc) + void MFFS(OP_REG frd, bool rc) { DisAsm_F1_RC("mffs", frd, rc); } - virtual void MTFSF(OP_REG flm, OP_REG frb, bool rc) + void MTFSF(OP_REG flm, OP_REG frb, bool rc) { DisAsm_F2_RC("mtfsf", flm, frb, rc); } - virtual void FCMPU(OP_REG crfd, OP_REG fra, OP_REG frb) + void FCMPU(OP_REG crfd, OP_REG fra, OP_REG frb) { DisAsm_CR1_F2("fcmpu", crfd, fra, frb); } - virtual void FRSP(OP_REG frd, OP_REG frb, bool rc) + void FRSP(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("frsp", frd, frb, rc); } - virtual void FCTIW(OP_REG frd, OP_REG frb, bool rc) + void FCTIW(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fctiw", frd, frb, rc); } - virtual void FCTIWZ(OP_REG frd, OP_REG frb, bool rc) + void FCTIWZ(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fctiwz", frd, frb, rc); } - virtual void FDIV(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FDIV(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fdiv", frd, fra, frb, rc); } - virtual void FSUB(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FSUB(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fsub", frd, fra, frb, rc); } - virtual void FADD(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FADD(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { DisAsm_F3_RC("fadd", frd, fra, frb, rc); } - virtual void FSQRT(OP_REG frd, OP_REG frb, bool rc) + void FSQRT(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fsqrt", frd, frb, rc); } - virtual void FSEL(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FSEL(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fsel", frd, fra, frc, frb, rc); } - virtual void FMUL(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) + void FMUL(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) { DisAsm_F3_RC("fmul", frd, fra, frc, rc); } - virtual void FRSQRTE(OP_REG frd, OP_REG frb, bool rc) + void FRSQRTE(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("frsqrte", frd, frb, rc); } - virtual void FMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fmsub", frd, fra, frc, frb, rc); } - virtual void FMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fmadd", frd, fra, frc, frb, rc); } - virtual void FNMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fnmsub", frd, fra, frc, frb, rc); } - virtual void FNMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { DisAsm_F4_RC("fnmadd", frd, fra, frc, frb, rc); } - virtual void FCMPO(OP_REG crfd, OP_REG fra, OP_REG frb) + void FCMPO(OP_REG crfd, OP_REG fra, OP_REG frb) { DisAsm_F3("fcmpo", crfd, fra, frb); } - virtual void FNEG(OP_REG frd, OP_REG frb, bool rc) + void FNEG(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fneg", frd, frb, rc); } - virtual void FMR(OP_REG frd, OP_REG frb, bool rc) + void FMR(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fmr", frd, frb, rc); } - virtual void FNABS(OP_REG frd, OP_REG frb, bool rc) + void FNABS(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fnabs", frd, frb, rc); } - virtual void FABS(OP_REG frd, OP_REG frb, bool rc) + void FABS(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fabs", frd, frb, rc); } - virtual void FCTID(OP_REG frd, OP_REG frb, bool rc) + void FCTID(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fctid", frd, frb, rc); } - virtual void FCTIDZ(OP_REG frd, OP_REG frb, bool rc) + void FCTIDZ(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fctidz", frd, frb, rc); } - virtual void FCFID(OP_REG frd, OP_REG frb, bool rc) + void FCFID(OP_REG frd, OP_REG frb, bool rc) { DisAsm_F2_RC("fcfid", frd, frb, rc); } END_OPCODES_GROUP(G_3f); - virtual void UNK(const s32 code, const s32 opcode, const s32 gcode) + void UNK(const u32 code, const u32 opcode, const u32 gcode) { Write(wxString::Format("Unknown/Illegal opcode! (0x%08x : 0x%x : 0x%x)", code, opcode, gcode)); } diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index fe97ee9c9f..b186db9186 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -5,9 +5,11 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/SysCalls.h" #include "rpcs3.h" +#include #define START_OPCODES_GROUP(x) /*x*/ #define END_OPCODES_GROUP(x) /*x*/ +#define UNIMPLEMENTED() UNK(__FUNCTION__) #if 0//def _DEBUG #define HLE_CALL_DEBUG @@ -28,11 +30,16 @@ void InitRotateMask() inited = true; } +u8 rotl8(const u8 x, const u8 n) { return (x << n) | (x >> (8 - n)); } +u8 rotr8(const u8 x, const u8 n) { return (x >> n) | (x << (8 - n)); } + +u16 rotl16(const u16 x, const u8 n) { return (x << n) | (x >> (16 - n)); } +u16 rotr16(const u16 x, const u8 n) { return (x >> n) | (x << (16 - n)); } /* -u32 rotl32(const u32 x, const u8 n) const { return (x << n) | (x >> (32 - n)); } -u32 rotr32(const u32 x, const u8 n) const { return (x >> n) | (x << (32 - n)); } -u64 rotl64(const u64 x, const u8 n) const { return (x << n) | (x >> (64 - n)); } -u64 rotr64(const u64 x, const u8 n) const { return (x >> n) | (x << (64 - n)); } +u32 rotl32(const u32 x, const u8 n) { return (x << n) | (x >> (32 - n)); } +u32 rotr32(const u32 x, const u8 n) { return (x >> n) | (x << (32 - n)); } +u64 rotl64(const u64 x, const u8 n) { return (x << n) | (x >> (64 - n)); } +u64 rotr64(const u64 x, const u8 n) { return (x >> n) | (x << (64 - n)); } */ #define rotl32 _rotl @@ -52,29 +59,40 @@ public: } private: - virtual void Exit() {} + void Exit() {} - virtual void SysCall() + void SysCall() { - CPU.GPR[3] = SysCallsManager.DoSyscall(CPU.GPR[11], CPU); + CPU.GPR[3] = CPU.DoSyscall(CPU.GPR[11]); - if((s32)CPU.GPR[3] < 0) - ConLog.Warning("SysCall[%lld] done with code [0x%x]! #pc: 0x%llx", CPU.GPR[11], (u32)CPU.GPR[3], CPU.PC); + //if((s32)CPU.GPR[3] < 0) + //ConLog.Warning("SysCall[%lld] done with code [0x%x]! #pc: 0x%llx", CPU.GPR[11], (u32)CPU.GPR[3], CPU.PC); #ifdef HLE_CALL_DEBUG - else ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); + ConLog.Write("SysCall[%lld] done with code [0x%llx]! #pc: 0x%llx", CPU.GPR[11], CPU.GPR[3], CPU.PC); #endif } - virtual void NULL_OP() + void NULL_OP() { UNK("null"); } - virtual void NOP() + void NOP() { //__asm nop } + float CheckVSCR_NJ(const float v) const + { + if(!CPU.VSCR.NJ) return v; + + int fpc = _fpclass(v); + if(fpc & _FPCLASS_ND) return -0.0f; + if(fpc & _FPCLASS_PD) return 0.0f; + + return v; + } + bool CheckCondition(OP_uIMM bo, OP_uIMM bi) { const u8 bo0 = (bo & 0x10) ? 1 : 0; @@ -105,13 +123,14 @@ private: case 0x001: return CPU.XER.XER; case 0x008: return CPU.LR; case 0x009: return CPU.CTR; + case 0x100: return CPU.USPRG0; } - UNK(wxString::Format("GetRegBySPR error: Unknown spr %d!", n)); + UNK(wxString::Format("GetRegBySPR error: Unknown SPR 0x%x!", n)); return CPU.XER.XER; } - virtual void TDI(OP_uIMM to, OP_REG ra, OP_sIMM simm16) + void TDI(OP_uIMM to, OP_REG ra, OP_sIMM simm16) { s64 a = CPU.GPR[ra]; @@ -121,11 +140,11 @@ private: ((u64)a < (u64)simm16 && (to & 0x2)) || ((u64)a > (u64)simm16 && (to & 0x1)) ) { - UNK(wxString::Format("Trap! (tdi %x, r%d, %x)", to, ra, simm16), false); + UNK(wxString::Format("Trap! (tdi %x, r%d, %x)", to, ra, simm16)); } } - virtual void TWI(OP_uIMM to, OP_REG ra, OP_sIMM simm16) + void TWI(OP_uIMM to, OP_REG ra, OP_sIMM simm16) { s32 a = CPU.GPR[ra]; @@ -135,63 +154,1907 @@ private: ((u32)a < (u32)simm16 && (to & 0x2)) || ((u32)a > (u32)simm16 && (to & 0x1)) ) { - UNK(wxString::Format("Trap! (twi %x, r%d, %x)", to, ra, simm16), false); + UNK(wxString::Format("Trap! (twi %x, r%d, %x)", to, ra, simm16)); } } START_OPCODES_GROUP(G_04) - virtual void VXOR(OP_REG vrd, OP_REG vra, OP_REG vrb) + void MFVSCR(OP_REG vd) { - CPU.VPR[vrd] = CPU.VPR[vra] ^ CPU.VPR[vrb]; + CPU.VPR[vd].Clear(); + CPU.VPR[vd]._u32[0] = CPU.VSCR.VSCR; + } + void MTVSCR(OP_REG vb) + { + CPU.VSCR.VSCR = CPU.VPR[vb]._u32[0]; + CPU.VSCR.X = CPU.VSCR.Y = 0; + } + void VADDCUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = ~CPU.VPR[va]._u32[w] < CPU.VPR[vb]._u32[w]; + } + } + void VADDFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = CPU.VPR[va]._f[w] + CPU.VPR[vb]._f[w]; + } + } + void VADDSBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for(u32 b=0; b<16; ++b) + { + s16 result = (s16)CPU.VPR[va]._s8[b] + (s16)CPU.VPR[vb]._s8[b]; + + if (result > 0x7f) + { + CPU.VPR[vd]._s8[b] = 0x7f; + CPU.VSCR.SAT = 1; + } + else if (result < -0x80) + { + CPU.VPR[vd]._s8[b] = -0x80; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s8[b] = result; + } + } + void VADDSHS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + s32 result = (s32)CPU.VPR[va]._s16[h] + (s32)CPU.VPR[vb]._s16[h]; + + if (result > 0x7fff) + { + CPU.VPR[vd]._s16[h] = 0x7fff; + CPU.VSCR.SAT = 1; + } + else if (result < -0x8000) + { + CPU.VPR[vd]._s16[h] = -0x8000; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s16[h] = result; + } + } + void VADDSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + s64 result = (s64)CPU.VPR[va]._s32[w] + (s64)CPU.VPR[vb]._s32[w]; + + if (result > 0x7fffffff) + { + CPU.VPR[vd]._s32[w] = 0x7fffffff; + CPU.VSCR.SAT = 1; + } + else if (result < (s32)0x80000000) + { + CPU.VPR[vd]._s32[w] = 0x80000000; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[w] = result; + } + } + void VADDUBM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b] + CPU.VPR[vb]._u8[b]; + } + } + void VADDUBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + u16 result = (u16)CPU.VPR[va]._u8[b] + (u16)CPU.VPR[vb]._u8[b]; + + if (result > 0xff) + { + CPU.VPR[vd]._u8[b] = 0xff; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u8[b] = result; + } + } + void VADDUHM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] + CPU.VPR[vb]._u16[h]; + } + } + void VADDUHS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + u32 result = (u32)CPU.VPR[va]._u16[h] + (u32)CPU.VPR[vb]._u16[h]; + + if (result > 0xffff) + { + CPU.VPR[vd]._u16[h] = 0xffff; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u16[h] = result; + } + } + void VADDUWM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] + CPU.VPR[vb]._u32[w]; + } + } + void VADDUWS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + u64 result = (u64)CPU.VPR[va]._u32[w] + (u64)CPU.VPR[vb]._u32[w]; + + if (result > 0xffffffff) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u32[w] = result; + } + } + void VAND(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] & CPU.VPR[vb]._u32[w]; + } + } + void VANDC(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] & (~CPU.VPR[vb]._u32[w]); + } + } + void VAVGSB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._s8[b] = (CPU.VPR[va]._s8[b] + CPU.VPR[vb]._s8[b] + 1) >> 1; + } + } + void VAVGSH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = (CPU.VPR[va]._s16[h] + CPU.VPR[vb]._s16[h] + 1) >> 1; + } + } + void VAVGSW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = ((s64)CPU.VPR[va]._s32[w] + (s64)CPU.VPR[vb]._s32[w] + 1) >> 1; + } + } + void VAVGUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] + CPU.VPR[vb]._u8[b] + 1) >> 1; + } + void VAVGUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = (CPU.VPR[va]._u16[h] + CPU.VPR[vb]._u16[h] + 1) >> 1; + } + } + void VAVGUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = ((u64)CPU.VPR[va]._u32[w] + (u64)CPU.VPR[vb]._u32[w] + 1) >> 1; + } + } + void VCFSX(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + u32 scale = 1 << uimm5; + + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = ((float)CPU.VPR[vb]._s32[w]) / scale; + } + } + void VCFUX(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + u32 scale = 1 << uimm5; + + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = ((float)CPU.VPR[vb]._u32[w]) / scale; + } + } + void VCMPBFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + u32 mask = 0; + + const float A = CheckVSCR_NJ(CPU.VPR[va]._f[w]); + const float B = CheckVSCR_NJ(CPU.VPR[vb]._f[w]); + + if (A > B) mask |= 1 << 31; + if (A < -B) mask |= 1 << 30; + + CPU.VPR[vd]._u32[w] = mask; + } + } + void VCMPBFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + bool allInBounds = true; + + for (uint w = 0; w < 4; w++) + { + u32 mask = 0; + + const float A = CheckVSCR_NJ(CPU.VPR[va]._f[w]); + const float B = CheckVSCR_NJ(CPU.VPR[vb]._f[w]); + + if (A > B) mask |= 1 << 31; + if (A < -B) mask |= 1 << 30; + + CPU.VPR[vd]._u32[w] = mask; + + if (mask) + allInBounds = false; + } + + // Bit n°2 of CR6 + CPU.SetCRBit(6, 0x2, allInBounds); + } + void VCMPEQFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._f[w] == CPU.VPR[vb]._f[w] ? 0xffffffff : 0; + } + } + void VCMPEQFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_equal = 0x8; + int none_equal = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._f[w] == CPU.VPR[vb]._f[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_equal = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_equal = 0; + } + } + + CPU.CR.cr6 = all_equal | none_equal; + } + void VCMPEQUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b] == CPU.VPR[vb]._u8[b] ? 0xff : 0; + } + } + void VCMPEQUB_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_equal = 0x8; + int none_equal = 0x2; + + for (uint b = 0; b < 16; b++) + { + if (CPU.VPR[va]._u8[b] == CPU.VPR[vb]._u8[b]) + { + CPU.VPR[vd]._u8[b] = 0xff; + none_equal = 0; + } + else + { + CPU.VPR[vd]._u8[b] = 0; + all_equal = 0; + } + } + + CPU.CR.cr6 = all_equal | none_equal; + } + void VCMPEQUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] == CPU.VPR[vb]._u16[h] ? 0xffff : 0; + } + } + void VCMPEQUH_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_equal = 0x8; + int none_equal = 0x2; + + for (uint h = 0; h < 8; h++) + { + if (CPU.VPR[va]._u16[h] == CPU.VPR[vb]._u16[h]) + { + CPU.VPR[vd]._u16[h] = 0xffff; + none_equal = 0; + } + else + { + CPU.VPR[vd]._u16[h] = 0; + all_equal = 0; + } + } + + CPU.CR.cr6 = all_equal | none_equal; + } + void VCMPEQUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] == CPU.VPR[vb]._u32[w] ? 0xffffffff : 0; + } + } + void VCMPEQUW_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_equal = 0x8; + int none_equal = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._u32[w] == CPU.VPR[vb]._u32[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_equal = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_equal = 0; + } + } + + CPU.CR.cr6 = all_equal | none_equal; + } + void VCMPGEFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._f[w] >= CPU.VPR[vb]._f[w] ? 0xffffffff : 0; + } + } + void VCMPGEFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_ge = 0x8; + int none_ge = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._f[w] >= CPU.VPR[vb]._f[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_ge = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_ge = 0; + } + } + + CPU.CR.cr6 = all_ge | none_ge; + } + void VCMPGTFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._f[w] > CPU.VPR[vb]._f[w] ? 0xffffffff : 0; + } + } + void VCMPGTFP_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_ge = 0x8; + int none_ge = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._f[w] > CPU.VPR[vb]._f[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_ge = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_ge = 0; + } + } + + CPU.CR.cr6 = all_ge | none_ge; + } + void VCMPGTSB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._s8[b] > CPU.VPR[vb]._s8[b] ? 0xff : 0; + } + } + void VCMPGTSB_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint b = 0; b < 16; b++) + { + if (CPU.VPR[va]._s8[b] > CPU.VPR[vb]._s8[b]) + { + CPU.VPR[vd]._u8[b] = 0xff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u8[b] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCMPGTSH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._s16[h] > CPU.VPR[vb]._s16[h] ? 0xffff : 0; + } + } + void VCMPGTSH_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint h = 0; h < 8; h++) + { + if (CPU.VPR[va]._s16[h] > CPU.VPR[vb]._s16[h]) + { + CPU.VPR[vd]._u16[h] = 0xffff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u16[h] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCMPGTSW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._s32[w] > CPU.VPR[vb]._s32[w] ? 0xffffffff : 0; + } + } + void VCMPGTSW_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._s32[w] > CPU.VPR[vb]._s32[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCMPGTUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b] > CPU.VPR[vb]._u8[b] ? 0xff : 0; + } + } + void VCMPGTUB_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint b = 0; b < 16; b++) + { + if (CPU.VPR[va]._u8[b] > CPU.VPR[vb]._u8[b]) + { + CPU.VPR[vd]._u8[b] = 0xff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u8[b] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCMPGTUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] > CPU.VPR[vb]._u16[h] ? 0xffff : 0; + } + } + void VCMPGTUH_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint h = 0; h < 8; h++) + { + if (CPU.VPR[va]._u16[h] > CPU.VPR[vb]._u16[h]) + { + CPU.VPR[vd]._u16[h] = 0xffff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u16[h] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCMPGTUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] > CPU.VPR[vb]._u32[w] ? 0xffffffff : 0; + } + } + void VCMPGTUW_(OP_REG vd, OP_REG va, OP_REG vb) + { + int all_gt = 0x8; + int none_gt = 0x2; + + for (uint w = 0; w < 4; w++) + { + if (CPU.VPR[va]._u32[w] > CPU.VPR[vb]._u32[w]) + { + CPU.VPR[vd]._u32[w] = 0xffffffff; + none_gt = 0; + } + else + { + CPU.VPR[vd]._u32[w] = 0; + all_gt = 0; + } + } + + CPU.CR.cr6 = all_gt | none_gt; + } + void VCTSXS(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + int nScale = 1 << uimm5; + + for (uint w = 0; w < 4; w++) + { + // C rounding = Round towards 0 + s64 result = (s64)(CPU.VPR[vb]._f[w] * nScale); + + if (result > INT_MAX) + CPU.VPR[vd]._s32[w] = (int)INT_MAX; + else if (result < INT_MIN) + CPU.VPR[vd]._s32[w] = (int)INT_MIN; + else + CPU.VPR[vd]._s32[w] = (int)result; + } + } + void VCTUXS(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + int nScale = 1 << uimm5; + + for (uint w = 0; w < 4; w++) + { + // C rounding = Round towards 0 + s64 result = (s64)(CPU.VPR[vb]._f[w] * nScale); + + if (result > UINT_MAX) + CPU.VPR[vd]._u32[w] = (u32)UINT_MAX; + else if (result < 0) + CPU.VPR[vd]._u32[w] = 0; + else + CPU.VPR[vd]._u32[w] = (u32)result; + } + } + void VEXPTEFP(OP_REG vd, OP_REG vb) + { + // vd = exp(vb * log(2)) + // ISA : Note that the value placed into the element of vD may vary between implementations + // and between different executions on the same implementation. + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = exp(CPU.VPR[vb]._f[w] * log(2.0f)); + } + } + void VLOGEFP(OP_REG vd, OP_REG vb) + { + // ISA : Note that the value placed into the element of vD may vary between implementations + // and between different executions on the same implementation. + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = log(CPU.VPR[vb]._f[w]) / log(2.0f); + } + } + void VMADDFP(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = CPU.VPR[va]._f[w] * CPU.VPR[vc]._f[w] + CPU.VPR[vb]._f[w]; + } + } + void VMAXFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = max(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); + } + } + void VMAXSB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + CPU.VPR[vd]._s8[b] = max(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); + } + void VMAXSH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = max(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); + } + } + void VMAXSW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = max(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); + } + } + void VMAXUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + CPU.VPR[vd]._u8[b] = max(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); + } + void VMAXUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = max(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); + } + } + void VMAXUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = max(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); + } + } + void VMHADDSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint h = 0; h < 8; h++) + { + s32 result = (s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h] + (s32)CPU.VPR[vc]._s16[h]; + + if (result > INT16_MAX) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT16_MIN) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s16[h] = (s16)result; + } + } + void VMHRADDSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint h = 0; h < 8; h++) + { + s32 result = (s32)CPU.VPR[va]._s16[h] * (s32)CPU.VPR[vb]._s16[h] + (s32)CPU.VPR[vc]._s16[h] + 0x4000; + + if (result > INT16_MAX) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT16_MIN) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s16[h] = (s16)result; + } + } + void VMINFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = min(CPU.VPR[va]._f[w], CPU.VPR[vb]._f[w]); + } + } + void VMINSB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._s8[b] = min(CPU.VPR[va]._s8[b], CPU.VPR[vb]._s8[b]); + } + } + void VMINSH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = min(CPU.VPR[va]._s16[h], CPU.VPR[vb]._s16[h]); + } + } + void VMINSW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = min(CPU.VPR[va]._s32[w], CPU.VPR[vb]._s32[w]); + } + } + void VMINUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = min(CPU.VPR[va]._u8[b], CPU.VPR[vb]._u8[b]); + } + } + void VMINUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = min(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u16[h]); + } + } + void VMINUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = min(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u32[w]); + } + } + void VMLADDUHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] * CPU.VPR[vb]._u16[h] + CPU.VPR[vc]._u16[h]; + } + } + void VMRGHB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h]; + CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h]; + } + } + void VMRGHH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w]; + CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w]; + } + } + void VMRGHW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint d = 0; d < 2; d++) + { + CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d]; + CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d]; + } + } + void VMRGLB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u8[h*2] = CPU.VPR[va]._u8[h + 8]; + CPU.VPR[vd]._u8[h*2 + 1] = CPU.VPR[vb]._u8[h + 8]; + } + } + void VMRGLH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u16[w*2] = CPU.VPR[va]._u16[w + 4]; + CPU.VPR[vd]._u16[w*2 + 1] = CPU.VPR[vb]._u16[w + 4]; + } + } + void VMRGLW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint d = 0; d < 2; d++) + { + CPU.VPR[vd]._u32[d*2] = CPU.VPR[va]._u32[d + 2]; + CPU.VPR[vd]._u32[d*2 + 1] = CPU.VPR[vb]._u32[d + 2]; + } + } + void VMSUMMBM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + s32 result = 0; + + for (uint b = 0; b < 4; b++) + { + result += CPU.VPR[va]._s8[w*4 + b] * CPU.VPR[vb]._u8[w*4 + b]; + } + + result += CPU.VPR[vc]._s32[w]; + CPU.VPR[vd]._s32[w] = result; + } + } + void VMSUMSHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + s32 result = 0; + + for (uint h = 0; h < 2; h++) + { + result += CPU.VPR[va]._s16[w*2 + h] * CPU.VPR[vb]._s16[w*2 + h]; + } + + result += CPU.VPR[vc]._s32[w]; + CPU.VPR[vd]._s32[w] = result; + } + } + void VMSUMSHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + s64 result = 0; + s32 saturated = 0; + + for (uint h = 0; h < 2; h++) + { + result += CPU.VPR[va]._s16[w*2 + h] * CPU.VPR[vb]._s16[w*2 + h]; + } + + result += CPU.VPR[vc]._s32[w]; + + if (result > INT_MAX) + { + saturated = INT_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT_MIN) + { + saturated = INT_MIN; + CPU.VSCR.SAT = 1; + } + else + saturated = (s32)result; + + CPU.VPR[vd]._s32[w] = saturated; + } + } + void VMSUMUBM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + u32 result = 0; + + for (uint b = 0; b < 4; b++) + { + result += CPU.VPR[va]._u8[w*4 + b] * CPU.VPR[vb]._u8[w*4 + b]; + } + + result += CPU.VPR[vc]._u32[w]; + CPU.VPR[vd]._u32[w] = result; + } + } + void VMSUMUHM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + u32 result = 0; + + for (uint h = 0; h < 2; h++) + { + result += CPU.VPR[va]._u16[w*2 + h] * CPU.VPR[vb]._u16[w*2 + h]; + } + + result += CPU.VPR[vc]._u32[w]; + CPU.VPR[vd]._u32[w] = result; + } + } + void VMSUMUHS(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + u64 result = 0; + u32 saturated = 0; + + for (uint h = 0; h < 2; h++) + { + result += CPU.VPR[va]._u16[w*2 + h] * CPU.VPR[vb]._u16[w*2 + h]; + } + + result += CPU.VPR[vc]._u32[w]; + + if (result > UINT_MAX) + { + saturated = UINT_MAX; + CPU.VSCR.SAT = 1; + } + else + saturated = (u32)result; + + CPU.VPR[vd]._u32[w] = saturated; + } + } + void VMULESB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = (s16)CPU.VPR[va]._s8[h*2+1] * (s16)CPU.VPR[vb]._s8[h*2+1]; + } + } + void VMULESH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = (s32)CPU.VPR[va]._s16[w*2+1] * (s32)CPU.VPR[vb]._s16[w*2+1]; + } + } + void VMULEUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = (u16)CPU.VPR[va]._u8[h*2+1] * (u16)CPU.VPR[vb]._u8[h*2+1]; + } + } + void VMULEUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = (u32)CPU.VPR[va]._u16[w*2+1] * (u32)CPU.VPR[vb]._u16[w*2+1]; + } + } + void VMULOSB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = (s16)CPU.VPR[va]._s8[h*2] * (s16)CPU.VPR[vb]._s8[h*2]; + } + } + void VMULOSH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = (s32)CPU.VPR[va]._s16[w*2] * (s32)CPU.VPR[vb]._s16[w*2]; + } + } + void VMULOUB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = (u16)CPU.VPR[va]._u8[h*2] * (u16)CPU.VPR[vb]._u8[h*2]; + } + } + void VMULOUH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = (u32)CPU.VPR[va]._u16[w*2] * (u32)CPU.VPR[vb]._u16[w*2]; + } + } + void VNMSUBFP(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = (double)CPU.VPR[vb]._f[w] - (double)CPU.VPR[va]._f[w] * (double)CPU.VPR[vc]._f[w]; + } + } + void VNOR(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = ~(CPU.VPR[va]._u32[w] | CPU.VPR[vb]._u32[w]); + } + } + void VOR(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] | CPU.VPR[vb]._u32[w]; + } + } + void VPERM(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint b = 0; b < 16; b++) + { + u8 index = CPU.VPR[vc]._u8[b] & 0x1f; + + CPU.VPR[vd]._u8[b] = index < 0x10 ? CPU.VPR[va]._u8[0xf - index] : CPU.VPR[vb]._u8[0xf - (index - 0x10)]; + } + } + void VPKPX(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 4; h++) + { + u16 bb7 = CPU.VPR[vb]._u8[15 - (h*4 + 0)] & 0x1; + u16 bb8 = CPU.VPR[vb]._u8[15 - (h*4 + 1)] >> 3; + u16 bb16 = CPU.VPR[vb]._u8[15 - (h*4 + 2)] >> 3; + u16 bb24 = CPU.VPR[vb]._u8[15 - (h*4 + 3)] >> 3; + u16 ab7 = CPU.VPR[va]._u8[15 - (h*4 + 0)] & 0x1; + u16 ab8 = CPU.VPR[va]._u8[15 - (h*4 + 1)] >> 3; + u16 ab16 = CPU.VPR[va]._u8[15 - (h*4 + 2)] >> 3; + u16 ab24 = CPU.VPR[va]._u8[15 - (h*4 + 3)] >> 3; + + CPU.VPR[vd]._u16[3 - h] = (bb7 << 15) | (bb8 << 10) | (bb16 << 5) | bb24; + CPU.VPR[vd]._u16[4 + (3 - h)] = (ab7 << 15) | (ab8 << 10) | (ab16 << 5) | ab24; + } + } + void VPKSHSS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 8; b++) + { + s16 result = CPU.VPR[va]._s16[b]; + + if (result > INT8_MAX) + { + result = INT8_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT8_MIN) + { + result = INT8_MIN; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._s8[b+8] = result; + + result = CPU.VPR[vb]._s16[b]; + + if (result > INT8_MAX) + { + result = INT8_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT8_MIN) + { + result = INT8_MIN; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._s8[b] = result; + } + } + void VPKSHUS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 8; b++) + { + s16 result = CPU.VPR[va]._s16[b]; + + if (result > UINT8_MAX) + { + result = UINT8_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < 0) + { + result = 0; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u8[b+8] = result; + + result = CPU.VPR[vb]._s16[b]; + + if (result > UINT8_MAX) + { + result = UINT8_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < 0) + { + result = 0; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u8[b] = result; + } + } + void VPKSWSS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 4; h++) + { + s32 result = CPU.VPR[va]._s32[h]; + + if (result > INT16_MAX) + { + result = INT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT16_MIN) + { + result = INT16_MIN; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._s16[h+4] = result; + + result = CPU.VPR[vb]._s32[h]; + + if (result > INT16_MAX) + { + result = INT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < INT16_MIN) + { + result = INT16_MIN; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._s16[h] = result; + } + } + void VPKSWUS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 4; h++) + { + s32 result = CPU.VPR[va]._s32[h]; + + if (result > UINT16_MAX) + { + result = UINT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < 0) + { + result = 0; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u16[h+4] = result; + + result = CPU.VPR[vb]._s32[h]; + + if (result > UINT16_MAX) + { + result = UINT16_MAX; + CPU.VSCR.SAT = 1; + } + else if (result < 0) + { + result = 0; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u16[h] = result; + } + } + void VPKUHUM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 8; b++) + { + CPU.VPR[vd]._u8[b+8] = CPU.VPR[va]._u8[b*2]; + CPU.VPR[vd]._u8[b ] = CPU.VPR[vb]._u8[b*2]; + } + } + void VPKUHUS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 8; b++) + { + u16 result = CPU.VPR[va]._u16[b]; + + if (result > UINT8_MAX) + { + result = UINT8_MAX; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u8[b+8] = result; + + result = CPU.VPR[vb]._u16[b]; + + if (result > UINT8_MAX) + { + result = UINT8_MAX; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u8[b] = result; + } + } + void VPKUWUM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 4; h++) + { + CPU.VPR[vd]._u16[h+4] = CPU.VPR[va]._u16[h*2]; + CPU.VPR[vd]._u16[h ] = CPU.VPR[vb]._u16[h*2]; + } + } + void VPKUWUS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 4; h++) + { + u32 result = CPU.VPR[va]._u32[h]; + + if (result > UINT16_MAX) + { + result = UINT16_MAX; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u16[h+4] = result; + + result = CPU.VPR[vb]._u32[h]; + + if (result > UINT16_MAX) + { + result = UINT16_MAX; + CPU.VSCR.SAT = 1; + } + + CPU.VPR[vd]._u16[h] = result; + } + } + void VREFP(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = 1.0f / CPU.VPR[vb]._f[w]; + } + } + void VRFIM(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = floor(CPU.VPR[vb]._f[w]); + } + } + void VRFIN(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = floor(CPU.VPR[vb]._f[w] + 0.5f); + } + } + void VRFIP(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = ceil(CPU.VPR[vb]._f[w]); + } + } + void VRFIZ(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + float f; + modf(CPU.VPR[vb]._f[w], &f); + CPU.VPR[vd]._f[w] = f; + } + } + void VRLB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + int nRot = CPU.VPR[vb]._u8[b] & 0x7; + + CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] << nRot) | (CPU.VPR[va]._u8[b] >> (8 - nRot)); + } + } + void VRLH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = rotl16(CPU.VPR[va]._u16[h], CPU.VPR[vb]._u8[h*2] & 0xf); + } + } + void VRLW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = rotl32(CPU.VPR[va]._u32[w], CPU.VPR[vb]._u8[w*4] & 0x1f); + } + } + void VRSQRTEFP(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + //TODO: accurate div + CPU.VPR[vd]._f[w] = 1.0f / sqrtf(CPU.VPR[vb]._f[w]); + } + } + void VSEL(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = (CPU.VPR[vb]._u8[b] & CPU.VPR[vc]._u8[b]) | (CPU.VPR[va]._u8[b] & (~CPU.VPR[vc]._u8[b])); + } + } + void VSL(OP_REG vd, OP_REG va, OP_REG vb) + { + u8 sh = CPU.VPR[vb]._u8[0] & 0x7; + + u32 t = 1; + + for (uint b = 0; b < 16; b++) + { + t &= (CPU.VPR[vb]._u8[b] & 0x7) == sh; + } + + if(t) + { + CPU.VPR[vd]._u8[0] = CPU.VPR[va]._u8[0] << sh; + + for (uint b = 1; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = (CPU.VPR[va]._u8[b] << sh) | (CPU.VPR[va]._u8[b-1] >> (8 - sh)); + } + } + else + { + //undefined + CPU.VPR[vd]._u32[0] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); + CPU.VPR[vd]._u32[1] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); + CPU.VPR[vd]._u32[2] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); + CPU.VPR[vd]._u32[3] = ((rand() % 0x100) << 24) | ((rand() % 0x100) << 16) | ((rand() % 0x100) << 8) | (rand() % 0x100); + } + } + void VSLB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b] << (CPU.VPR[vb]._u8[b] & 0x7); + } + } + void VSLDOI(OP_REG vd, OP_REG va, OP_REG vb, OP_uIMM sh) + { + for (uint b = 0; b < 16 - sh; b++) + { + CPU.VPR[vd]._u8[15 - b] = CPU.VPR[va]._u8[15 - (b + sh)]; + } + for (uint b = 16 - sh; b < 16; b++) + { + CPU.VPR[vd]._u8[15 - b] = CPU.VPR[vb]._u8[15 - (b - (16 - sh))]; + } + } + void VSLH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] << (CPU.VPR[vb]._u8[h*2] & 0xf); + } + } + void VSLO(OP_REG vd, OP_REG va, OP_REG vb) + { + u8 nShift = (CPU.VPR[vb]._u8[0] >> 3) & 0xf; + + CPU.VPR[vd].Clear(); + + for (u8 b = 0; b < 16 - nShift; b++) + { + CPU.VPR[vd]._u8[15 - b] = CPU.VPR[va]._u8[15 - (b + nShift)]; + } + } + void VSLW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] << (CPU.VPR[vb]._u8[w*4] & 0x1f); + } + } + void VSPLTB(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + u8 byte = CPU.VPR[vb]._u8[15 - uimm5]; + + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = byte; + } + } + void VSPLTH(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + assert(uimm5 < 8); + + u16 hword = CPU.VPR[vb]._u16[7 - uimm5]; + + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = hword; + } + } + void VSPLTISB(OP_REG vd, OP_sIMM simm5) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = simm5; + } + } + void VSPLTISH(OP_REG vd, OP_sIMM simm5) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = (s16)simm5; + } + } + void VSPLTISW(OP_REG vd, OP_sIMM simm5) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = (s32)simm5; + } + } + void VSPLTW(OP_REG vd, OP_uIMM uimm5, OP_REG vb) + { + assert(uimm5 < 4); + + u32 word = CPU.VPR[vb]._u32[uimm5]; + + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = word; + } + } + void VSR(OP_REG vd, OP_REG va, OP_REG vb) + { + u8 sh = CPU.VPR[vb]._u8[15] & 0x7; + + CPU.VPR[vd]._u32[0] = CPU.VPR[va]._u32[0] >> sh; + + for (uint w = 1; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = (CPU.VPR[va]._u32[w] >> sh) | (CPU.VPR[va]._u32[w - 1] << (32 - sh)); + } + } + void VSRAB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._s8[b] = CPU.VPR[va]._s8[b] >> (CPU.VPR[vb]._u8[b] & 0x7); + } + } + void VSRAH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = CPU.VPR[va]._s16[h] >> (CPU.VPR[vb]._u8[h*2 + 1] & 0xf); + } + } + void VSRAW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = CPU.VPR[va]._s32[w] >> (CPU.VPR[vb]._u8[w*4 + 3] & 0x1f); + } + } + void VSRB(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b] >> (CPU.VPR[vb]._u8[b] & 0x7); + } + } + void VSRH(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] >> (CPU.VPR[vb]._u8[h*2 + 1] & 0xf); + } + } + void VSRO(OP_REG vd, OP_REG va, OP_REG vb) + { + u8 nShift = (CPU.VPR[vb]._u8[15] >> 3) & 0xf; + + CPU.VPR[vd].Clear(); + + for (u8 b = nShift; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = CPU.VPR[va]._u8[b - nShift]; + } + } + void VSRW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] >> (CPU.VPR[vb]._u8[w*4 + 3] & 0x1f); + } + } + void VSUBCUW(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] < CPU.VPR[vb]._u32[w] ? 0 : 1; + } + } + void VSUBFP(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._f[w] = CPU.VPR[va]._f[w] - CPU.VPR[vb]._f[w]; + } + } + void VSUBSBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + s16 result = (s16)CPU.VPR[va]._s8[b] - (s16)CPU.VPR[vb]._s8[b]; + + if (result < INT8_MIN) + { + CPU.VPR[vd]._s8[b] = INT8_MIN; + CPU.VSCR.SAT = 1; + } + else if (result > INT8_MAX) + { + CPU.VPR[vd]._s8[b] = INT8_MAX; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s8[b] = (s8)result; + } + } + void VSUBSHS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + s32 result = (s32)CPU.VPR[va]._s16[h] - (s32)CPU.VPR[vb]._s16[h]; + + if (result < INT16_MIN) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MIN; + CPU.VSCR.SAT = 1; + } + else if (result > INT16_MAX) + { + CPU.VPR[vd]._s16[h] = (s16)INT16_MAX; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s16[h] = (s16)result; + } + } + void VSUBSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + s64 result = (s64)CPU.VPR[va]._s32[w] - (s64)CPU.VPR[vb]._s32[w]; + + if (result < INT32_MIN) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MIN; + CPU.VSCR.SAT = 1; + } + else if (result > INT32_MAX) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MAX; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[w] = (s32)result; + } + } + void VSUBUBM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + CPU.VPR[vd]._u8[b] = (u8)((CPU.VPR[va]._u8[b] - CPU.VPR[vb]._u8[b]) & 0xff); + } + } + void VSUBUBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint b = 0; b < 16; b++) + { + s16 result = (s16)CPU.VPR[va]._u8[b] - (s16)CPU.VPR[vb]._u8[b]; + + if (result < 0) + { + CPU.VPR[vd]._u8[b] = 0; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u8[b] = (u8)result; + } + } + void VSUBUHM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._u16[h] = CPU.VPR[va]._u16[h] - CPU.VPR[vb]._u16[h]; + } + } + void VSUBUHS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + s32 result = (s32)CPU.VPR[va]._u16[h] - (s32)CPU.VPR[vb]._u16[h]; + + if (result < 0) + { + CPU.VPR[vd]._u16[h] = 0; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u16[h] = (u16)result; + } + } + void VSUBUWM(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._u32[w] = CPU.VPR[va]._u32[w] - CPU.VPR[vb]._u32[w]; + } + } + void VSUBUWS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + s64 result = (s64)CPU.VPR[va]._u32[w] - (s64)CPU.VPR[vb]._u32[w]; + + if (result < 0) + { + CPU.VPR[vd]._u32[w] = 0; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u32[w] = (u32)result; + } + } + void VSUMSWS(OP_REG vd, OP_REG va, OP_REG vb) + { + CPU.VPR[vd].Clear(); + + s64 sum = CPU.VPR[vb]._s32[3]; + + for (uint w = 0; w < 4; w++) + { + sum += CPU.VPR[va]._s32[w]; + } + + if (sum > INT32_MAX) + { + CPU.VPR[vd]._s32[3] = (s32)INT32_MAX; + CPU.VSCR.SAT = 1; + } + else if (sum < INT32_MIN) + { + CPU.VPR[vd]._s32[3] = (s32)INT32_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[3] = (s32)sum; + } + void VSUM2SWS(OP_REG vd, OP_REG va, OP_REG vb) + { + CPU.VPR[vd].Clear(); + + for (uint n = 0; n < 2; n++) + { + s64 sum = CPU.VPR[vb]._s32[n*2 + 1]; + + for (uint w = 0; w < 2; w++) + { + sum += CPU.VPR[va]._s32[n*2 + w]; + } + + if (sum > INT32_MAX) + { + CPU.VPR[vd]._s32[n*2 + 1] = (s32)INT32_MAX; + CPU.VSCR.SAT = 1; + } + else if (sum < INT32_MIN) + { + CPU.VPR[vd]._s32[n*2 + 1] = (s32)INT32_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[n*2 + 1] = (s32)sum; + } + } + void VSUM4SBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + s64 sum = CPU.VPR[vb]._s32[w]; + + for (uint b = 0; b < 4; b++) + { + sum += CPU.VPR[va]._s8[w*4 + b]; + } + + if (sum > INT32_MAX) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MAX; + CPU.VSCR.SAT = 1; + } + else if (sum < INT32_MIN) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[w] = (s32)sum; + } + } + void VSUM4SHS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + s64 sum = CPU.VPR[vb]._s32[w]; + + for (uint h = 0; h < 2; h++) + { + sum += CPU.VPR[va]._s16[w*2 + h]; + } + + if (sum > INT32_MAX) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MAX; + CPU.VSCR.SAT = 1; + } + else if (sum < INT32_MIN) + { + CPU.VPR[vd]._s32[w] = (s32)INT32_MIN; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._s32[w] = (s32)sum; + } + } + void VSUM4UBS(OP_REG vd, OP_REG va, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + u64 sum = CPU.VPR[vb]._u32[w]; + + for (uint b = 0; b < 4; b++) + { + sum += CPU.VPR[va]._u8[w*4 + b]; + } + + if (sum > UINT32_MAX) + { + CPU.VPR[vd]._u32[w] = (u32)UINT32_MAX; + CPU.VSCR.SAT = 1; + } + else + CPU.VPR[vd]._u32[w] = (u32)sum; + } + } + void VUPKHPX(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s8[w*4 + 0] = CPU.VPR[vb]._s8[w*2 + 0] >> 7; // signed shift sign extends + CPU.VPR[vd]._u8[w*4 + 1] = (CPU.VPR[vb]._u8[w*2 + 0] >> 2) & 0x1f; + CPU.VPR[vd]._u8[w*4 + 2] = ((CPU.VPR[vb]._u8[w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[w*2 + 1] >> 5) & 0x7); + CPU.VPR[vd]._u8[w*4 + 3] = CPU.VPR[vb]._u8[w*2 + 1] & 0x1f; + } + } + void VUPKHSB(OP_REG vd, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = CPU.VPR[vb]._s8[h]; + } + } + void VUPKHSH(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = CPU.VPR[vb]._s16[w]; + } + } + void VUPKLPX(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s8[w*4 + 0] = CPU.VPR[vb]._s8[8 + w*2 + 0] >> 7; // signed shift sign extends + CPU.VPR[vd]._u8[w*4 + 1] = (CPU.VPR[vb]._u8[8 + w*2 + 0] >> 2) & 0x1f; + CPU.VPR[vd]._u8[w*4 + 2] = ((CPU.VPR[vb]._u8[8 + w*2 + 0] & 0x3) << 3) | ((CPU.VPR[vb]._u8[8 + w*2 + 1] >> 5) & 0x7); + CPU.VPR[vd]._u8[w*4 + 3] = CPU.VPR[vb]._u8[8 + w*2 + 1] & 0x1f; + } + } + void VUPKLSB(OP_REG vd, OP_REG vb) + { + for (uint h = 0; h < 8; h++) + { + CPU.VPR[vd]._s16[h] = CPU.VPR[vb]._s8[8 + h]; + } + } + void VUPKLSH(OP_REG vd, OP_REG vb) + { + for (uint w = 0; w < 4; w++) + { + CPU.VPR[vd]._s32[w] = CPU.VPR[vb]._s16[4 + w]; + } + } + void VXOR(OP_REG vd, OP_REG va, OP_REG vb) + { + CPU.VPR[vd]._u32[0] = CPU.VPR[va]._u32[0] ^ CPU.VPR[vb]._u32[0]; + CPU.VPR[vd]._u32[1] = CPU.VPR[va]._u32[1] ^ CPU.VPR[vb]._u32[1]; + CPU.VPR[vd]._u32[2] = CPU.VPR[va]._u32[2] ^ CPU.VPR[vb]._u32[2]; + CPU.VPR[vd]._u32[3] = CPU.VPR[va]._u32[3] ^ CPU.VPR[vb]._u32[3]; } END_OPCODES_GROUP(G_04); - virtual void MULLI(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void MULLI(OP_REG rd, OP_REG ra, OP_sIMM simm16) { CPU.GPR[rd] = (s64)CPU.GPR[ra] * simm16; } - virtual void SUBFIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void SUBFIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) { s64 RA = CPU.GPR[ra]; CPU.GPR[rd] = (s64)simm16 - RA; CPU.XER.CA = RA <= simm16; } - virtual void CMPLI(OP_REG crfd, OP_REG l, OP_REG ra, OP_uIMM uimm16) + void CMPLI(OP_REG crfd, OP_REG l, OP_REG ra, OP_uIMM uimm16) { CPU.UpdateCRn(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], uimm16); } - virtual void CMPI(OP_REG crfd, OP_REG l, OP_REG ra, OP_sIMM simm16) + void CMPI(OP_REG crfd, OP_REG l, OP_REG ra, OP_sIMM simm16) { CPU.UpdateCRn(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], simm16); } - virtual void ADDIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIC(OP_REG rd, OP_REG ra, OP_sIMM simm16) { const u64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + simm16; CPU.XER.CA = CPU.IsCarry(RA, simm16); } - virtual void ADDIC_(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIC_(OP_REG rd, OP_REG ra, OP_sIMM simm16) { const u64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + simm16; CPU.XER.CA = CPU.IsCarry(RA, simm16); CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void ADDI(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDI(OP_REG rd, OP_REG ra, OP_sIMM simm16) { CPU.GPR[rd] = ra ? ((s64)CPU.GPR[ra] + simm16) : simm16; } - virtual void ADDIS(OP_REG rd, OP_REG ra, OP_sIMM simm16) + void ADDIS(OP_REG rd, OP_REG ra, OP_sIMM simm16) { CPU.GPR[rd] = ra ? ((s64)CPU.GPR[ra] + (simm16 << 16)) : (simm16 << 16); } - virtual void BC(OP_REG bo, OP_REG bi, OP_sIMM bd, OP_REG aa, OP_REG lk) + void BC(OP_REG bo, OP_REG bi, OP_sIMM bd, OP_REG aa, OP_REG lk) { if(!CheckCondition(bo, bi)) return; CPU.SetBranch(branchTarget((aa ? 0 : CPU.PC), bd)); if(lk) CPU.LR = CPU.PC + 4; } - virtual void SC(const s32 sc_code) + void SC(const s32 sc_code) { switch(sc_code) { @@ -201,67 +2064,67 @@ private: default: UNK(wxString::Format("Unknown sc: %x", sc_code)); } } - virtual void B(OP_sIMM ll, OP_REG aa, OP_REG lk) + void B(OP_sIMM ll, OP_REG aa, OP_REG lk) { CPU.SetBranch(branchTarget(aa ? 0 : CPU.PC, ll)); if(lk) CPU.LR = CPU.PC + 4; } START_OPCODES_GROUP(G_13) - virtual void MCRF(OP_REG crfd, OP_REG crfs) + void MCRF(OP_REG crfd, OP_REG crfs) { CPU.SetCR(crfd, CPU.GetCR(crfs)); } - virtual void BCLR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) + void BCLR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) { if(!CheckCondition(bo, bi)) return; CPU.SetBranch(branchTarget(0, CPU.LR)); if(lk) CPU.LR = CPU.PC + 4; } - virtual void CRNOR(OP_REG bt, OP_REG ba, OP_REG bb) + void CRNOR(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = 1 ^ (CPU.IsCR(ba) | CPU.IsCR(bb)); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CRANDC(OP_REG bt, OP_REG ba, OP_REG bb) + void CRANDC(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = CPU.IsCR(ba) & (1 ^ CPU.IsCR(bb)); CPU.SetCRBit2(bt, v & 0x1); } - virtual void ISYNC() + void ISYNC() { } - virtual void CRXOR(OP_REG bt, OP_REG ba, OP_REG bb) + void CRXOR(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = CPU.IsCR(ba) ^ CPU.IsCR(bb); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CRNAND(OP_REG bt, OP_REG ba, OP_REG bb) + void CRNAND(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = 1 ^ (CPU.IsCR(ba) & CPU.IsCR(bb)); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CRAND(OP_REG bt, OP_REG ba, OP_REG bb) + void CRAND(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = CPU.IsCR(ba) & CPU.IsCR(bb); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CREQV(OP_REG bt, OP_REG ba, OP_REG bb) + void CREQV(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = 1 ^ (CPU.IsCR(ba) ^ CPU.IsCR(bb)); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CRORC(OP_REG bt, OP_REG ba, OP_REG bb) + void CRORC(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = CPU.IsCR(ba) | (1 ^ CPU.IsCR(bb)); CPU.SetCRBit2(bt, v & 0x1); } - virtual void CROR(OP_REG bt, OP_REG ba, OP_REG bb) + void CROR(OP_REG bt, OP_REG ba, OP_REG bb) { const u8 v = CPU.IsCR(ba) | CPU.IsCR(bb); CPU.SetCRBit2(bt, v & 0x1); } - virtual void BCCTR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) + void BCCTR(OP_REG bo, OP_REG bi, OP_REG bh, OP_REG lk) { if(bo & 0x10 || CPU.IsCR(bi) == (bo & 0x8)) { @@ -271,66 +2134,66 @@ private: } END_OPCODES_GROUP(G_13); - virtual void RLWIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) + void RLWIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) { const u32 mask = rotate_mask[32 + mb][32 + me]; CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl32(CPU.GPR[rs], sh) & mask); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void RLWINM(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) + void RLWINM(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, OP_REG me, bool rc) { CPU.GPR[ra] = rotl32(CPU.GPR[rs], sh) & rotate_mask[32 + mb][32 + me]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void RLWNM(OP_REG ra, OP_REG rs, OP_REG rb, OP_REG mb, OP_REG me, bool rc) + void RLWNM(OP_REG ra, OP_REG rs, OP_REG rb, OP_REG mb, OP_REG me, bool rc) { CPU.GPR[ra] = rotl32(CPU.GPR[rs], CPU.GPR[rb] & 0x1f) & rotate_mask[32 + mb][32 + me]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void ORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] | uimm16; } - virtual void ORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] | (uimm16 << 16); } - virtual void XORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void XORI(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] ^ uimm16; } - virtual void XORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void XORIS(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] ^ (uimm16 << 16); } - virtual void ANDI_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ANDI_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] & uimm16; CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void ANDIS_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) + void ANDIS_(OP_REG ra, OP_REG rs, OP_uIMM uimm16) { CPU.GPR[ra] = CPU.GPR[rs] & (uimm16 << 16); CPU.UpdateCR0(CPU.GPR[ra]); } START_OPCODES_GROUP(G_1e) - virtual void RLDICL(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDICL(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[mb][63]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void RLDICR(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG me, bool rc) + void RLDICR(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG me, bool rc) { CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[0][me]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void RLDIC(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDIC(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[mb][63-sh]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void RLDIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) + void RLDIMI(OP_REG ra, OP_REG rs, OP_REG sh, OP_REG mb, bool rc) { const u64 mask = rotate_mask[mb][63-sh]; CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl64(CPU.GPR[rs], sh) & mask); @@ -339,11 +2202,11 @@ private: END_OPCODES_GROUP(G_1e); START_OPCODES_GROUP(G_1f) - virtual void CMP(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) + void CMP(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) { CPU.UpdateCRn(crfd, l ? CPU.GPR[ra] : (s32)CPU.GPR[ra], l ? CPU.GPR[rb] : (s32)CPU.GPR[rb]); } - virtual void TW(OP_uIMM to, OP_REG ra, OP_REG rb) + void TW(OP_uIMM to, OP_REG ra, OP_REG rb) { s32 a = CPU.GPR[ra]; s32 b = CPU.GPR[rb]; @@ -354,16 +2217,41 @@ private: ((u32)a < (u32)b && (to & 0x2)) || ((u32)a > (u32)b && (to & 0x1)) ) { - UNK(wxString::Format("Trap! (tw %x, r%d, r%d)", to, ra, rb), false); + UNK(wxString::Format("Trap! (tw %x, r%d, r%d)", to, ra, rb)); } } - virtual void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVSL(OP_REG vd, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - CPU.VPR[vd].Clear(); - CPU.VPR[vd].b(addr & 0xf) = Memory.Read8(addr); + + switch(addr & 0xf) + { + case 0x0: CPU.VPR[vd]._u64[1] = 0x0001020304050607; CPU.VPR[vd]._u64[0] = 0x08090A0B0C0D0E0F; break; + case 0x1: CPU.VPR[vd]._u64[1] = 0x0102030405060708; CPU.VPR[vd]._u64[0] = 0x090A0B0C0D0E0F10; break; + case 0x2: CPU.VPR[vd]._u64[1] = 0x0203040506070809; CPU.VPR[vd]._u64[0] = 0x0A0B0C0D0E0F1011; break; + case 0x3: CPU.VPR[vd]._u64[1] = 0x030405060708090A; CPU.VPR[vd]._u64[0] = 0x0B0C0D0E0F101112; break; + case 0x4: CPU.VPR[vd]._u64[1] = 0x0405060708090A0B; CPU.VPR[vd]._u64[0] = 0x0C0D0E0F10111213; break; + case 0x5: CPU.VPR[vd]._u64[1] = 0x05060708090A0B0C; CPU.VPR[vd]._u64[0] = 0x0D0E0F1011121314; break; + case 0x6: CPU.VPR[vd]._u64[1] = 0x060708090A0B0C0D; CPU.VPR[vd]._u64[0] = 0x0E0F101112131415; break; + case 0x7: CPU.VPR[vd]._u64[1] = 0x0708090A0B0C0D0E; CPU.VPR[vd]._u64[0] = 0x0F10111213141516; break; + case 0x8: CPU.VPR[vd]._u64[1] = 0x08090A0B0C0D0E0F; CPU.VPR[vd]._u64[0] = 0x1011121314151617; break; + case 0x9: CPU.VPR[vd]._u64[1] = 0x090A0B0C0D0E0F10; CPU.VPR[vd]._u64[0] = 0x1112131415161718; break; + case 0xa: CPU.VPR[vd]._u64[1] = 0x0A0B0C0D0E0F1011; CPU.VPR[vd]._u64[0] = 0x1213141516171819; break; + case 0xb: CPU.VPR[vd]._u64[1] = 0x0B0C0D0E0F101112; CPU.VPR[vd]._u64[0] = 0x131415161718191A; break; + case 0xc: CPU.VPR[vd]._u64[1] = 0x0C0D0E0F10111213; CPU.VPR[vd]._u64[0] = 0x1415161718191A1B; break; + case 0xd: CPU.VPR[vd]._u64[1] = 0x0D0E0F1011121314; CPU.VPR[vd]._u64[0] = 0x15161718191A1B1C; break; + case 0xe: CPU.VPR[vd]._u64[1] = 0x0E0F101112131415; CPU.VPR[vd]._u64[0] = 0x161718191A1B1C1D; break; + case 0xf: CPU.VPR[vd]._u64[1] = 0x0F10111213141516; CPU.VPR[vd]._u64[0] = 0x1718191A1B1C1D1E; break; + } } - virtual void SUBFC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void LVEBX(OP_REG vd, OP_REG ra, OP_REG rb) + { + //const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + //CPU.VPR[vd].Clear(); + //CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read8(addr); + CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + } + void SUBFC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -372,7 +2260,7 @@ private: if(oe) UNK("subfco"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void ADDC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADDC(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -381,7 +2269,7 @@ private: if(oe) UNK("addco"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MULHDU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHDU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { const u64 RA = CPU.GPR[ra]; const u64 RB = CPU.GPR[rb]; @@ -406,19 +2294,19 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MULHWU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHWU(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { CPU.GPR[rd] = (CPU.GPR[ra] * CPU.GPR[rb]) >> 32; if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MFOCRF(OP_REG a, OP_REG fxm, OP_REG rd) + void MFOCRF(OP_uIMM a, OP_REG rd, OP_uIMM crm) { if(a) { u32 n = 0, count = 0; for(u32 i = 0; i < 8; ++i) { - if(fxm & (1 << i)) + if(crm & (1 << i)) { n = i; count++; @@ -427,32 +2315,33 @@ private: if(count == 1) { - //RT[32+4*n : 32+4*n+3] = CR[4*n : 4*n+3]; + //RD[32+4*n : 32+4*n+3] = CR[4*n : 4*n+3]; CPU.GPR[rd] = (u64)CPU.GetCR(n) << (n * 4); } - else CPU.GPR[rd] = 0; + else + CPU.GPR[rd] = 0; } else { CPU.GPR[rd] = CPU.CR.CR; } } - virtual void LWARX(OP_REG rd, OP_REG ra, OP_REG rb) + void LWARX(OP_REG rd, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; CPU.reserve_addr = addr; CPU.reserve = true; CPU.GPR[rd] = Memory.Read32(addr); } - virtual void LDX(OP_REG ra, OP_REG rs, OP_REG rb) + void LDX(OP_REG ra, OP_REG rs, OP_REG rb) { CPU.GPR[ra] = Memory.Read64(rs ? CPU.GPR[rs] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void LWZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LWZX(OP_REG rd, OP_REG ra, OP_REG rb) { CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void SLW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SLW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { const u32 n = CPU.GPR[rb] & 0x1f; const u32 r = rotl32((u32)CPU.GPR[rs], n); @@ -462,7 +2351,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void CNTLZW(OP_REG ra, OP_REG rs, bool rc) + void CNTLZW(OP_REG ra, OP_REG rs, bool rc) { u32 i; for(i=0; i < 32; i++) @@ -474,43 +2363,68 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SLD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SLD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] << (CPU.GPR[rb] & 0x3f); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void AND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void AND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rs] & CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void CMPL(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) + void CMPL(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb) { CPU.UpdateCRn(crfd, l ? CPU.GPR[ra] : (u32)CPU.GPR[ra], l ? CPU.GPR[rb] : (u32)CPU.GPR[rb]); } - virtual void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVSR(OP_REG vd, OP_REG ra, OP_REG rb) { - const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; - CPU.VPR[vd].Clear(); - CPU.VPR[vd].h((addr & 0xf) >> 1) = Memory.Read16(addr); + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + + switch(addr & 0xf) + { + case 0x0: CPU.VPR[vd]._u64[1] = 0x1011121314151617; CPU.VPR[vd]._u64[0] = 0x18191A1B1C1D1E1F; break; + case 0x1: CPU.VPR[vd]._u64[1] = 0x0F10111213141516; CPU.VPR[vd]._u64[0] = 0x1718191A1B1C1D1E; break; + case 0x2: CPU.VPR[vd]._u64[1] = 0x0E0F101112131415; CPU.VPR[vd]._u64[0] = 0x161718191A1B1C1D; break; + case 0x3: CPU.VPR[vd]._u64[1] = 0x0D0E0F1011121314; CPU.VPR[vd]._u64[0] = 0x15161718191A1B1C; break; + case 0x4: CPU.VPR[vd]._u64[1] = 0x0C0D0E0F10111213; CPU.VPR[vd]._u64[0] = 0x1415161718191A1B; break; + case 0x5: CPU.VPR[vd]._u64[1] = 0x0B0C0D0E0F101112; CPU.VPR[vd]._u64[0] = 0x131415161718191A; break; + case 0x6: CPU.VPR[vd]._u64[1] = 0x0A0B0C0D0E0F1011; CPU.VPR[vd]._u64[0] = 0x1213141516171819; break; + case 0x7: CPU.VPR[vd]._u64[1] = 0x090A0B0C0D0E0F10; CPU.VPR[vd]._u64[0] = 0x1112131415161718; break; + case 0x8: CPU.VPR[vd]._u64[1] = 0x08090A0B0C0D0E0F; CPU.VPR[vd]._u64[0] = 0x1011121314151617; break; + case 0x9: CPU.VPR[vd]._u64[1] = 0x0708090A0B0C0D0E; CPU.VPR[vd]._u64[0] = 0x0F10111213141516; break; + case 0xa: CPU.VPR[vd]._u64[1] = 0x060708090A0B0C0D; CPU.VPR[vd]._u64[0] = 0x0E0F101112131415; break; + case 0xb: CPU.VPR[vd]._u64[1] = 0x05060708090A0B0C; CPU.VPR[vd]._u64[0] = 0x0D0E0F1011121314; break; + case 0xc: CPU.VPR[vd]._u64[1] = 0x0405060708090A0B; CPU.VPR[vd]._u64[0] = 0x0C0D0E0F10111213; break; + case 0xd: CPU.VPR[vd]._u64[1] = 0x030405060708090A; CPU.VPR[vd]._u64[0] = 0x0B0C0D0E0F101112; break; + case 0xe: CPU.VPR[vd]._u64[1] = 0x0203040506070809; CPU.VPR[vd]._u64[0] = 0x0A0B0C0D0E0F1011; break; + case 0xf: CPU.VPR[vd]._u64[1] = 0x0102030405060708; CPU.VPR[vd]._u64[0] = 0x090A0B0C0D0E0F10; break; + } } - virtual void SUBF(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void LVEHX(OP_REG vd, OP_REG ra, OP_REG rb) + { + //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; + //CPU.VPR[vd].Clear(); + //(u16&)CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read16(addr); + CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + } + void SUBF(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { CPU.GPR[rd] = CPU.GPR[rb] - CPU.GPR[ra]; if(oe) UNK("subfo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void LDUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LDUX(OP_REG rd, OP_REG ra, OP_REG rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; CPU.GPR[rd] = Memory.Read64(addr); CPU.GPR[ra] = addr; } - virtual void DCBST(OP_REG ra, OP_REG rb) + void DCBST(OP_REG ra, OP_REG rb) { //UNK("dcbst", false); } - virtual void CNTLZD(OP_REG ra, OP_REG rs, bool rc) + void CNTLZD(OP_REG ra, OP_REG rs, bool rc) { u32 i = 0; @@ -522,18 +2436,19 @@ private: CPU.GPR[ra] = i; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void ANDC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void ANDC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rs] & ~CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void LVEWX(OP_REG vd, OP_REG ra, OP_REG rb) + void LVEWX(OP_REG vd, OP_REG ra, OP_REG rb) { - const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; - CPU.VPR[vd].Clear(); - CPU.VPR[vd].w((addr & 0xf) >> 2) = Memory.Read32(addr); + //const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; + //CPU.VPR[vd].Clear(); + //(u32&)CPU.VPR[vd]._u8[addr & 0xf] = Memory.Read32(addr); + CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } - virtual void MULHD(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHD(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -558,37 +2473,37 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MULHW(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) + void MULHW(OP_REG rd, OP_REG ra, OP_REG rb, bool rc) { CPU.GPR[rd] = (s64)(s32)((CPU.GPR[ra] * CPU.GPR[rb]) >> 32); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void LDARX(OP_REG rd, OP_REG ra, OP_REG rb) + void LDARX(OP_REG rd, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; CPU.reserve_addr = addr; CPU.reserve = true; CPU.GPR[rd] = Memory.Read64(addr); } - virtual void DCBF(OP_REG ra, OP_REG rb) + void DCBF(OP_REG ra, OP_REG rb) { //UNK("dcbf", false); } - virtual void LBZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LBZX(OP_REG rd, OP_REG ra, OP_REG rb) { CPU.GPR[rd] = Memory.Read8(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void LVX(OP_REG vrd, OP_REG ra, OP_REG rb) + void LVX(OP_REG vd, OP_REG ra, OP_REG rb) { - CPU.VPR[vrd] = Memory.Read128(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); } - virtual void NEG(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void NEG(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { CPU.GPR[rd] = 0-CPU.GPR[ra]; if(oe) UNK("nego"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void LBZUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LBZUX(OP_REG rd, OP_REG ra, OP_REG rb) { //if(ra == 0 || ra == rd) throw "Bad instruction [LBZUX]"; @@ -596,12 +2511,18 @@ private: CPU.GPR[rd] = Memory.Read8(addr); CPU.GPR[ra] = addr; } - virtual void NOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void NOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = ~(CPU.GPR[rs] | CPU.GPR[rb]); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SUBFE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void STVEBX(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + Memory.Write8(addr, CPU.VPR[vs]._u8[15 - eb]); + } + void SUBFE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -610,7 +2531,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("subfeo"); } - virtual void ADDE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADDE(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -619,12 +2540,12 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("addeo"); } - virtual void MTOCRF(OP_REG fxm, OP_REG rs) + void MTOCRF(OP_REG crm, OP_REG rs) { u32 n = 0, count = 0; for(u32 i=0; i<8; ++i) { - if(fxm & (1 << i)) + if(crm & (1 << i)) { n = i; count++; @@ -638,11 +2559,11 @@ private: } else CPU.CR.CR = 0; } - virtual void STDX(OP_REG rs, OP_REG ra, OP_REG rb) + void STDX(OP_REG rs, OP_REG ra, OP_REG rb) { Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); } - virtual void STWCX_(OP_REG rs, OP_REG ra, OP_REG rb) + void STWCX_(OP_REG rs, OP_REG ra, OP_REG rb) { CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0); if(!CPU.reserve) return; @@ -662,17 +2583,29 @@ private: CPU.reserve = false; } } - virtual void STWX(OP_REG rs, OP_REG ra, OP_REG rb) + void STWX(OP_REG rs, OP_REG ra, OP_REG rb) { Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); } - virtual void STDUX(OP_REG rs, OP_REG ra, OP_REG rb) + void STVEHX(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~1ULL; + const u8 eb = (addr & 0xf) >> 1; + Memory.Write16(addr, CPU.VPR[vs]._u16[7 - eb]); + } + void STDUX(OP_REG rs, OP_REG ra, OP_REG rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; Memory.Write64(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } - virtual void ADDZE(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void STVEWX(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~3ULL; + const u8 eb = (addr & 0xf) >> 2; + Memory.Write32(addr, CPU.VPR[vs]._u32[3 - eb]); + } + void ADDZE(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + CPU.XER.CA; @@ -681,7 +2614,7 @@ private: if(oe) ConLog.Warning("addzeo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void STDCX_(OP_REG rs, OP_REG ra, OP_REG rb) + void STDCX_(OP_REG rs, OP_REG ra, OP_REG rb) { CPU.SetCR(0, CPU.XER.SO ? CR_SO : 0); if(!CPU.reserve) return; @@ -701,21 +2634,21 @@ private: CPU.reserve = false; } } - virtual void STBX(OP_REG rs, OP_REG ra, OP_REG rb) + void STBX(OP_REG rs, OP_REG ra, OP_REG rb) { Memory.Write8((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); } - virtual void STVX(OP_REG vrd, OP_REG ra, OP_REG rb) + void STVX(OP_REG vs, OP_REG ra, OP_REG rb) { - Memory.Write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.VPR[vrd]); + Memory.Write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]._u128); } - virtual void MULLD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void MULLD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { CPU.GPR[rd] = CPU.GPR[ra] * CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("mulldo"); } - virtual void ADDME(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void ADDME(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; CPU.GPR[rd] = RA + CPU.XER.CA - 1; @@ -724,17 +2657,17 @@ private: if(oe) UNK("addmeo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MULLW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void MULLW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { CPU.GPR[rd] = (s64)(s32)((s32)CPU.GPR[ra] * (s32)CPU.GPR[rb]); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); if(oe) UNK("mullwo"); } - virtual void DCBTST(OP_REG th, OP_REG ra, OP_REG rb) + void DCBTST(OP_REG th, OP_REG ra, OP_REG rb) { //UNK("dcbtst", false); } - virtual void ADD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void ADD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const u64 RA = CPU.GPR[ra]; const u64 RB = CPU.GPR[rb]; @@ -743,50 +2676,57 @@ private: if(oe) UNK("addo"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void DCBT(OP_REG ra, OP_REG rb, OP_REG th) + void DCBT(OP_REG ra, OP_REG rb, OP_REG th) { //UNK("dcbt", false); } - virtual void LHZX(OP_REG rd, OP_REG ra, OP_REG rb) + void LHZX(OP_REG rd, OP_REG ra, OP_REG rb) { CPU.GPR[rd] = Memory.Read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void EQV(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void EQV(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = ~(CPU.GPR[rs] ^ CPU.GPR[rb]); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void ECIWX(OP_REG rd, OP_REG ra, OP_REG rb) + void ECIWX(OP_REG rd, OP_REG ra, OP_REG rb) { //HACK! CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void LHZUX(OP_REG rd, OP_REG ra, OP_REG rb) + void LHZUX(OP_REG rd, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; CPU.GPR[rd] = Memory.Read16(addr); CPU.GPR[ra] = addr; } - virtual void XOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void XOR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rs] ^ CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void MFSPR(OP_REG rd, OP_REG spr) + void MFSPR(OP_REG rd, OP_REG spr) { CPU.GPR[rd] = GetRegBySPR(spr); } - virtual void LHAX(OP_REG rd, OP_REG ra, OP_REG rb) + void DST(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t) + { + } + void LHAX(OP_REG rd, OP_REG ra, OP_REG rb) { CPU.GPR[rd] = (s64)(s16)Memory.Read16(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void ABS(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) + void LVXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + CPU.VPR[vd]._u128 = Memory.Read128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL); + } + void ABS(OP_REG rd, OP_REG ra, OP_REG oe, bool rc) { CPU.GPR[rd] = abs((s64)CPU.GPR[ra]); if(oe) UNK("abso"); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MFTB(OP_REG rd, OP_REG spr) + void MFTB(OP_REG rd, OP_REG spr) { const u32 n = (spr >> 5) | ((spr & 0x1f) << 5); @@ -797,33 +2737,36 @@ private: default: UNK(wxString::Format("mftb r%d, %d", rd, spr)); break; } } - virtual void LHAUX(OP_REG rd, OP_REG ra, OP_REG rb) + void DSTST(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t) + { + } + void LHAUX(OP_REG rd, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; CPU.GPR[rd] = (s64)(s16)Memory.Read16(addr); CPU.GPR[ra] = addr; } - virtual void STHX(OP_REG rs, OP_REG ra, OP_REG rb) + void STHX(OP_REG rs, OP_REG ra, OP_REG rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; Memory.Write16(addr, CPU.GPR[rs]); } - virtual void ORC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void ORC(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rs] | ~CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void ECOWX(OP_REG rs, OP_REG ra, OP_REG rb) + void ECOWX(OP_REG rs, OP_REG ra, OP_REG rb) { //HACK! Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), CPU.GPR[rs]); } - virtual void OR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void OR(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rs] | CPU.GPR[rb]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void DIVDU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVDU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const u64 RA = CPU.GPR[ra]; const u64 RB = CPU.GPR[rb]; @@ -840,7 +2783,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void DIVWU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVWU(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const u32 RA = CPU.GPR[ra]; const u32 RB = CPU.GPR[rb]; @@ -857,12 +2800,22 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void MTSPR(OP_REG spr, OP_REG rs) + void MTSPR(OP_REG spr, OP_REG rs) { GetRegBySPR(spr) = CPU.GPR[rs]; } /*0x1d6*///DCBI - virtual void DIVD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void NAND(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + { + CPU.GPR[ra] = ~(CPU.GPR[rs] & CPU.GPR[rb]); + + if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + } + void STVXL(OP_REG vs, OP_REG ra, OP_REG rb) + { + Memory.Write128((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfULL, CPU.VPR[vs]._u128); + } + void DIVD(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s64 RA = CPU.GPR[ra]; const s64 RB = CPU.GPR[rb]; @@ -879,7 +2832,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void DIVW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) + void DIVW(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc) { const s32 RA = CPU.GPR[ra]; const s32 RB = CPU.GPR[rb]; @@ -896,54 +2849,93 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - virtual void LWBRX(OP_REG rd, OP_REG ra, OP_REG rb) + void LVLX(OP_REG vd, OP_REG ra, OP_REG rb) { - CPU.GPR[rd] = *(u32*)&Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb); } - virtual void LFSX(OP_REG frd, OP_REG ra, OP_REG rb) + void LWBRX(OP_REG rd, OP_REG ra, OP_REG rb) { - *(u64*)&CPU.FPR[frd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); - CPU.FPR[frd] = *(float*)&CPU.FPR[frd]; + CPU.GPR[rd] = (u32&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; } - virtual void SRW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void LFSX(OP_REG frd, OP_REG ra, OP_REG rb) + { + (u32&)CPU.FPR[frd] = Memory.Read32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + CPU.FPR[frd] = (float&)CPU.FPR[frd]; + } + void SRW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rb] & 0x20 ? 0 : (u32)CPU.GPR[rs] >> (CPU.GPR[rb] & 0x1f); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SRD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { CPU.GPR[ra] = CPU.GPR[rb] & 0x40 ? 0 : CPU.GPR[rs] >> (CPU.GPR[rb] & 0x3f); if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void LFSUX(OP_REG frd, OP_REG ra, OP_REG rb) + void LVRX(OP_REG vd, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.ReadRight(CPU.VPR[vd]._u8, addr & ~0xf, eb); + } + void LFSUX(OP_REG frd, OP_REG ra, OP_REG rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - *(u64*)&CPU.FPR[frd] = Memory.Read32(addr); - CPU.FPR[frd] = *(float*)&CPU.FPR[frd]; + (u64&)CPU.FPR[frd] = Memory.Read32(addr); + CPU.FPR[frd] = (float&)CPU.FPR[frd]; CPU.GPR[ra] = addr; } - virtual void SYNC(OP_REG l) + void SYNC(OP_REG l) { } - virtual void LFDX(OP_REG frd, OP_REG ra, OP_REG rb) + void LFDX(OP_REG frd, OP_REG ra, OP_REG rb) { - *(u64*)&CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); + (u64&)CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]); } - virtual void LFDUX(OP_REG frd, OP_REG ra, OP_REG rb) + void LFDUX(OP_REG frd, OP_REG ra, OP_REG rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; - *(u64*)&CPU.FPR[frd] = Memory.Read64(addr); + (u64&)CPU.FPR[frd] = Memory.Read64(addr); CPU.GPR[ra] = addr; } - virtual void STFSX(OP_REG rs, OP_REG ra, OP_REG rb) + void STVLX(OP_REG vs, OP_REG ra, OP_REG rb) { - Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), PPCdouble(CPU.GPR[rs]).To32()); + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.WriteLeft(addr, 16 - eb, CPU.VPR[vs]._u8 + eb); } - virtual void LHBRX(OP_REG rd, OP_REG ra, OP_REG rb) + void STFSX(OP_REG frs, OP_REG ra, OP_REG rb) { - CPU.GPR[rd] = *(u16*)&Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + Memory.Write32((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), PPCdouble(CPU.FPR[frs]).To32()); } - virtual void SRAW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void STVRX(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.WriteRight(addr - eb, eb, CPU.VPR[vs]._u8); + } + void STFDX(OP_REG frs, OP_REG ra, OP_REG rb) + { + Memory.Write64((ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]), (u64&)CPU.FPR[frs]); + } + void LVLXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.ReadLeft(CPU.VPR[vd]._u8 + eb, addr, 16 - eb); + } + void LHBRX(OP_REG rd, OP_REG ra, OP_REG rb) + { + CPU.GPR[rd] = (u16&)Memory[ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]]; + } + void SRAW(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { s32 RS = CPU.GPR[rs]; s32 RB = CPU.GPR[rb]; @@ -952,7 +2944,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SRAD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) + void SRAD(OP_REG ra, OP_REG rs, OP_REG rb, bool rc) { s64 RS = CPU.GPR[rs]; s64 RB = CPU.GPR[rb]; @@ -961,7 +2953,17 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SRAWI(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void LVRXL(OP_REG vd, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.ReadRight(CPU.VPR[vd]._u8, addr & ~0xf, eb); + } + void DSS(OP_uIMM strm, OP_uIMM a) + { + } + void SRAWI(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { s32 RS = CPU.GPR[rs]; CPU.GPR[ra] = RS >> sh; @@ -969,7 +2971,7 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SRADI1(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void SRADI1(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { s64 RS = CPU.GPR[rs]; CPU.GPR[ra] = RS >> sh; @@ -977,100 +2979,114 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void SRADI2(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) + void SRADI2(OP_REG ra, OP_REG rs, OP_REG sh, bool rc) { SRADI1(ra, rs, sh, rc); } - virtual void EIEIO() + void EIEIO() { } - virtual void EXTSH(OP_REG ra, OP_REG rs, bool rc) + void STVLXL(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.WriteLeft(addr, 16 - eb, CPU.VPR[vs]._u8 + eb); + } + void EXTSH(OP_REG ra, OP_REG rs, bool rc) { CPU.GPR[ra] = (s64)(s16)CPU.GPR[rs]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void EXTSB(OP_REG ra, OP_REG rs, bool rc) + void STVRXL(OP_REG vs, OP_REG ra, OP_REG rb) + { + const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + const u8 eb = addr & 0xf; + + Memory.WriteRight(addr - eb, eb, CPU.VPR[vs]._u8); + } + void EXTSB(OP_REG ra, OP_REG rs, bool rc) { CPU.GPR[ra] = (s64)(s8)CPU.GPR[rs]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - virtual void STFIWX(OP_REG frs, OP_REG ra, OP_REG rb) + void STFIWX(OP_REG frs, OP_REG ra, OP_REG rb) { - Memory.Write32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], *(u32*)&CPU.FPR[frs]); + Memory.Write32(ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb], (u32&)CPU.FPR[frs]); } - virtual void EXTSW(OP_REG ra, OP_REG rs, bool rc) + void EXTSW(OP_REG ra, OP_REG rs, bool rc) { CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs]; if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } /*0x3d6*///ICBI - virtual void DCBZ(OP_REG ra, OP_REG rs) + void DCBZ(OP_REG ra, OP_REG rs) { //UNK("dcbz", false); } END_OPCODES_GROUP(G_1f); - virtual void LWZ(OP_REG rd, OP_REG ra, OP_sIMM d) + void LWZ(OP_REG rd, OP_REG ra, OP_sIMM d) { CPU.GPR[rd] = Memory.Read32(ra ? CPU.GPR[ra] + d : d); } - virtual void LWZU(OP_REG rd, OP_REG ra, OP_sIMM d) + void LWZU(OP_REG rd, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; CPU.GPR[rd] = Memory.Read32(addr); CPU.GPR[ra] = addr; } - virtual void LBZ(OP_REG rd, OP_REG ra, OP_sIMM d) + void LBZ(OP_REG rd, OP_REG ra, OP_sIMM d) { CPU.GPR[rd] = Memory.Read8(ra ? CPU.GPR[ra] + d : d); } - virtual void LBZU(OP_REG rd, OP_REG ra, OP_sIMM d) + void LBZU(OP_REG rd, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; CPU.GPR[rd] = Memory.Read8(addr); CPU.GPR[ra] = addr; } - virtual void STW(OP_REG rs, OP_REG ra, OP_sIMM d) + void STW(OP_REG rs, OP_REG ra, OP_sIMM d) { Memory.Write32(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); } - virtual void STWU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STWU(OP_REG rs, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; Memory.Write32(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } - virtual void STB(OP_REG rs, OP_REG ra, OP_sIMM d) + void STB(OP_REG rs, OP_REG ra, OP_sIMM d) { Memory.Write8(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); } - virtual void STBU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STBU(OP_REG rs, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; Memory.Write8(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } - virtual void LHZ(OP_REG rd, OP_REG ra, OP_sIMM d) + void LHZ(OP_REG rd, OP_REG ra, OP_sIMM d) { CPU.GPR[rd] = Memory.Read16(ra ? CPU.GPR[ra] + d : d); } - virtual void LHZU(OP_REG rd, OP_REG ra, OP_sIMM d) + void LHZU(OP_REG rd, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; CPU.GPR[rd] = Memory.Read16(addr); CPU.GPR[ra] = addr; } - virtual void STH(OP_REG rs, OP_REG ra, OP_sIMM d) + void STH(OP_REG rs, OP_REG ra, OP_sIMM d) { Memory.Write16(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); } - virtual void STHU(OP_REG rs, OP_REG ra, OP_sIMM d) + void STHU(OP_REG rs, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; Memory.Write16(addr, CPU.GPR[rs]); CPU.GPR[ra] = addr; } - virtual void LMW(OP_REG rd, OP_REG ra, OP_sIMM d) + void LMW(OP_REG rd, OP_REG ra, OP_sIMM d) { u64 addr = ra ? CPU.GPR[ra] + d : d; for(u32 i=rd; i<32; ++i, addr += 4) @@ -1078,7 +3094,7 @@ private: CPU.GPR[i] = Memory.Read32(addr); } } - virtual void STMW(OP_REG rs, OP_REG ra, OP_sIMM d) + void STMW(OP_REG rs, OP_REG ra, OP_sIMM d) { u64 addr = ra ? CPU.GPR[ra] + d : d; for(u32 i=rs; i<32; ++i, addr += 4) @@ -1086,55 +3102,55 @@ private: Memory.Write32(addr, CPU.GPR[i]); } } - virtual void LFS(OP_REG frd, OP_REG ra, OP_sIMM d) + void LFS(OP_REG frd, OP_REG ra, OP_sIMM d) { const u32 v = Memory.Read32(ra ? CPU.GPR[ra] + d : d); - CPU.FPR[frd] = *(float*)&v; + CPU.FPR[frd] = (float&)v; } - virtual void LFSU(OP_REG frd, OP_REG ra, OP_sIMM ds) + void LFSU(OP_REG frd, OP_REG ra, OP_sIMM ds) { const u64 addr = CPU.GPR[ra] + ds; const u32 v = Memory.Read32(addr); - CPU.FPR[frd] = *(float*)&v; + CPU.FPR[frd] = (float&)v; CPU.GPR[ra] = addr; } - virtual void LFD(OP_REG frd, OP_REG ra, OP_sIMM d) + void LFD(OP_REG frd, OP_REG ra, OP_sIMM d) { - *(u64*)&CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + d : d); + (u64&)CPU.FPR[frd] = Memory.Read64(ra ? CPU.GPR[ra] + d : d); } - virtual void LFDU(OP_REG frd, OP_REG ra, OP_sIMM ds) + void LFDU(OP_REG frd, OP_REG ra, OP_sIMM ds) { const u64 addr = CPU.GPR[ra] + ds; - *(u64*)&CPU.FPR[frd] = Memory.Read64(addr); + (u64&)CPU.FPR[frd] = Memory.Read64(addr); CPU.GPR[ra] = addr; } - virtual void STFS(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFS(OP_REG frs, OP_REG ra, OP_sIMM d) { Memory.Write32(ra ? CPU.GPR[ra] + d : d, PPCdouble(CPU.FPR[frs]).To32()); } - virtual void STFSU(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFSU(OP_REG frs, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; Memory.Write32(addr, PPCdouble(CPU.FPR[frs]).To32()); CPU.GPR[ra] = addr; } - virtual void STFD(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFD(OP_REG frs, OP_REG ra, OP_sIMM d) { - Memory.Write64(ra ? CPU.GPR[ra] + d : d, *(u64*)&CPU.FPR[frs]); + Memory.Write64(ra ? CPU.GPR[ra] + d : d, (u64&)CPU.FPR[frs]); } - virtual void STFDU(OP_REG frs, OP_REG ra, OP_sIMM d) + void STFDU(OP_REG frs, OP_REG ra, OP_sIMM d) { const u64 addr = CPU.GPR[ra] + d; - Memory.Write64(addr, *(u64*)&CPU.FPR[frs]); + Memory.Write64(addr, (u64&)CPU.FPR[frs]); CPU.GPR[ra] = addr; } START_OPCODES_GROUP(G_3a) - virtual void LD(OP_REG rd, OP_REG ra, OP_sIMM ds) + void LD(OP_REG rd, OP_REG ra, OP_sIMM ds) { CPU.GPR[rd] = Memory.Read64(ra ? CPU.GPR[ra] + ds : ds); } - virtual void LDU(OP_REG rd, OP_REG ra, OP_sIMM ds) + void LDU(OP_REG rd, OP_REG ra, OP_sIMM ds) { //if(ra == 0 || rt == ra) return; const u64 addr = CPU.GPR[ra] + ds; @@ -1144,37 +3160,37 @@ private: END_OPCODES_GROUP(G_3a); START_OPCODES_GROUP(G_3b) - virtual void FDIVS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FDIVS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX); CPU.FPR[frd] = static_cast(CPU.FPR[fra] / CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fdivs.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FSUBS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FSUBS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(CPU.FPR[fra] - CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fsubs.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FADDS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FADDS(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(CPU.FPR[fra] + CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fadds.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FSQRTS(OP_REG frd, OP_REG frb, bool rc) + void FSQRTS(OP_REG frd, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(sqrt((float)CPU.FPR[frb])); if(rc) UNK("fsqrts.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FRES(OP_REG frd, OP_REG frb, bool rc) + void FRES(OP_REG frd, OP_REG frb, bool rc) { if(CPU.FPR[frb] == 0.0) CPU.SetFPSCRException(FPSCR_ZX); CPU.FPR[frd] = static_cast(1.0f/CPU.FPR[frb]); if(rc) UNK("fres.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMULS(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) + void FMULS(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) { CPU.FPR[frd] = static_cast(CPU.FPR[fra] * CPU.FPR[frc]); CPU.FPSCR.FI = 0; @@ -1182,25 +3198,25 @@ private: CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmuls.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmadds.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmsubs.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FNMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMSUBS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(-(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb])); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fnmsubs.");////CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FNMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMADDS(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = static_cast(-(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb])); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); @@ -1209,11 +3225,11 @@ private: END_OPCODES_GROUP(G_3b); START_OPCODES_GROUP(G_3e) - virtual void STD(OP_REG rs, OP_REG ra, OP_sIMM d) + void STD(OP_REG rs, OP_REG ra, OP_sIMM d) { Memory.Write64(ra ? CPU.GPR[ra] + d : d, CPU.GPR[rs]); } - virtual void STDU(OP_REG rs, OP_REG ra, OP_sIMM ds) + void STDU(OP_REG rs, OP_REG ra, OP_sIMM ds) { //if(ra == 0 || rs == ra) return; const u64 addr = CPU.GPR[ra] + ds; @@ -1223,28 +3239,28 @@ private: END_OPCODES_GROUP(G_3e); START_OPCODES_GROUP(G_3f) - virtual void MTFSB1(OP_REG bt, bool rc) + void MTFSB1(OP_REG bt, bool rc) { - UNK("mtfsb1"); + UNIMPLEMENTED(); } - virtual void MCRFS(OP_REG bf, OP_REG bfa) + void MCRFS(OP_REG bf, OP_REG bfa) { - UNK("mcrfs"); + UNIMPLEMENTED(); } - virtual void MTFSB0(OP_REG bt, bool rc) + void MTFSB0(OP_REG bt, bool rc) { - UNK("mtfsb0"); + UNIMPLEMENTED(); } - virtual void MTFSFI(OP_REG crfd, OP_REG i, bool rc) + void MTFSFI(OP_REG crfd, OP_REG i, bool rc) { - UNK("mtfsfi"); + UNIMPLEMENTED(); } - virtual void MFFS(OP_REG frd, bool rc) + void MFFS(OP_REG frd, bool rc) { - *(u64*)&CPU.FPR[frd] = CPU.FPSCR.FPSCR; + (u64&)CPU.FPR[frd] = CPU.FPSCR.FPSCR; if(rc) UNK("mffs."); } - virtual void MTFSF(OP_REG flm, OP_REG frb, bool rc) + void MTFSF(OP_REG flm, OP_REG frb, bool rc) { u32 mask = 0; for(u32 i=0; i<8; ++i) @@ -1252,10 +3268,10 @@ private: if(flm & (1 << i)) mask |= 0xf << (i * 4); } - CPU.FPSCR.FPSCR = (CPU.FPSCR.FPSCR & ~mask) | (*(u32*)&CPU.FPR[frb] & mask); + CPU.FPSCR.FPSCR = (CPU.FPSCR.FPSCR & ~mask) | ((u32&)CPU.FPR[frb] & mask); if(rc) UNK("mtfsf."); } - virtual void FCMPU(OP_REG crfd, OP_REG fra, OP_REG frb) + void FCMPU(OP_REG crfd, OP_REG fra, OP_REG frb) { if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1) { @@ -1267,13 +3283,13 @@ private: CPU.SetCR(crfd, CPU.FPSCR.FPRF); } - virtual void FRSP(OP_REG frd, OP_REG frb, bool rc) + void FRSP(OP_REG frd, OP_REG frb, bool rc) { const double b = CPU.FPR[frb]; double b0 = b; if(CPU.FPSCR.NI) { - if ((*(u64*)&b0 & DOUBLE_EXP) < 0x3800000000000000ULL) *(u64*)&b0 &= DOUBLE_SIGN; + if (((u64&)b0 & DOUBLE_EXP) < 0x3800000000000000ULL) (u64&)b0 &= DOUBLE_SIGN; } const double r = static_cast(b0); CPU.FPSCR.FR = fabs(r) > fabs(b); @@ -1281,7 +3297,7 @@ private: CPU.FPSCR.FPRF = PPCdouble(r).GetType(); CPU.FPR[frd] = r; } - virtual void FCTIW(OP_REG frd, OP_REG frb, bool rc) + void FCTIW(OP_REG frd, OP_REG frb, bool rc) { const double b = CPU.FPR[frb]; u32 r; @@ -1337,12 +3353,12 @@ private: } } - *(u64*)&CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (*(u64*)&b) & DOUBLE_SIGN )) *(u64*)&CPU.FPR[frd] |= 0x100000000ull; + (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; + if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; if(rc) UNK("fctiw."); } - virtual void FCTIWZ(OP_REG frd, OP_REG frb, bool rc) + void FCTIWZ(OP_REG frd, OP_REG frb, bool rc) { const double b = CPU.FPR[frb]; u32 value; @@ -1377,71 +3393,55 @@ private: value = (u32)i; } - *(u64*)&CPU.FPR[frd] = 0xfff8000000000000ull | value; - if (value == 0 && ( (*(u64*)&b) & DOUBLE_SIGN )) - *(u64*)&CPU.FPR[frd] |= 0x100000000ull; + (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | value; + if (value == 0 && ( (u64&)b & DOUBLE_SIGN )) + (u64&)CPU.FPR[frd] |= 0x100000000ull; - /* - CPU.FPR[frd] = (double)*(u64*)&CPU.FPR[frb]; - return; - PPCdouble b = FPRdouble::ConvertToIntegerMode(CPU.FPR[frb], CPU.FPSCR, false, FPSCR_RN_ZERO); - CPU.FPR[frd] = b._double;//FPRdouble::ToInt(b, CPU.FPSCR.RN); - //PPCdouble b = FPRdouble::ConvertToIntegerMode(CPU.FPR[frb]); - //CPU.FPR[frd] = FPRdouble::ToInt(b, FPSCR_RN_ZERO); - */ if(rc) UNK("fctiwz."); } - virtual void FDIV(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FDIV(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { - /* - PPCdouble a = FPRdouble::ConvertToIntegerMode(CPU.FPR[fra]); - PPCdouble b = FPRdouble::ConvertToIntegerMode(CPU.FPR[frb]); - - if(a.type == FPR_ZERO && b.type == FPR_ZERO) + if(FPRdouble::IsINF(CPU.FPR[fra]) == 0.0 && CPU.FPR[frb] == 0.0) { CPU.FPSCR.VXZDZ = 1; } - else if(a.type == FPR_INF && b.type == FPR_INF) + else if(FPRdouble::IsINF(CPU.FPR[fra]) && FPRdouble::IsINF(CPU.FPR[frb])) { CPU.FPSCR.VXIDI = 1; } - else if(a.type != FPR_ZERO && b.type == FPR_ZERO) + else if(CPU.FPR[fra] != 0.0 && CPU.FPR[frb] == 0.0) { CPU.SetFPSCRException(FPSCR_ZX); } - PPCdouble d = a.div(b); - CPU.FPSCR.FPSCR |= FPRdouble::ConvertToFloatMode(d, CPU.FPSCR.RN); - CPU.GPR[frd] = d._double; - */ - CPU.FPR[frd] = CPU.FPR[fra] / CPU.FPR[frb]; + CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fdiv.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FSUB(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FSUB(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] - CPU.FPR[frb]; CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fsub.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FADD(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) + void FADD(OP_REG frd, OP_REG fra, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] + CPU.FPR[frb]; CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fadd.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FSQRT(OP_REG frd, OP_REG frb, bool rc) + void FSQRT(OP_REG frd, OP_REG frb, bool rc) { CPU.FPR[frd] = sqrt(CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fsqrt.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FSEL(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FSEL(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] < 0.0 ? CPU.FPR[frc] : CPU.FPR[frb]; if(rc) UNK("fsel.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMUL(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) + void FMUL(OP_REG frd, OP_REG fra, OP_REG frc, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc]; CPU.FPSCR.FI = 0; @@ -1449,35 +3449,35 @@ private: CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmul.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FRSQRTE(OP_REG frd, OP_REG frb, bool rc) + void FRSQRTE(OP_REG frd, OP_REG frb, bool rc) { - UNK("frsqrte"); + UNIMPLEMENTED(); } - virtual void FMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]; CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmsub.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]; CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fmadd.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FNMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMSUB(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] - CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fnmsub.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FNMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) + void FNMADD(OP_REG frd, OP_REG fra, OP_REG frc, OP_REG frb, bool rc) { CPU.FPR[frd] = -(CPU.FPR[fra] * CPU.FPR[frc] + CPU.FPR[frb]); CPU.FPSCR.FPRF = PPCdouble(CPU.FPR[frd]).GetType(); if(rc) UNK("fnmadd.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FCMPO(OP_REG crfd, OP_REG fra, OP_REG frb) + void FCMPO(OP_REG crfd, OP_REG fra, OP_REG frb) { if((CPU.FPSCR.FPRF = FPRdouble::Cmp(CPU.FPR[fra], CPU.FPR[frb])) == 1) { @@ -1496,27 +3496,27 @@ private: CPU.SetCR(crfd, CPU.FPSCR.FPRF); } - virtual void FNEG(OP_REG frd, OP_REG frb, bool rc) + void FNEG(OP_REG frd, OP_REG frb, bool rc) { CPU.FPR[frd] = -CPU.FPR[frb]; if(rc) UNK("fneg.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FMR(OP_REG frd, OP_REG frb, bool rc) + void FMR(OP_REG frd, OP_REG frb, bool rc) { CPU.FPR[frd] = CPU.FPR[frb]; if(rc) UNK("fmr.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FNABS(OP_REG frd, OP_REG frb, bool rc) + void FNABS(OP_REG frd, OP_REG frb, bool rc) { - *(u64*)&CPU.FPR[frd] = *(u64*)&CPU.FPR[frb] | 0x8000000000000000ULL; + (u64&)CPU.FPR[frd] = (u64&)CPU.FPR[frb] | 0x8000000000000000ULL; if(rc) UNK("fnabs.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FABS(OP_REG frd, OP_REG frb, bool rc) + void FABS(OP_REG frd, OP_REG frb, bool rc) { CPU.FPR[frd] = fabs(CPU.FPR[frb]); if(rc) UNK("fabs.");//CPU.UpdateCR1(CPU.FPR[frd]); } - virtual void FCTID(OP_REG frd, OP_REG frb, bool rc) + void FCTID(OP_REG frd, OP_REG frb, bool rc) { const double b = CPU.FPR[frb]; u64 r; @@ -1572,12 +3572,12 @@ private: } } - *(u64*)&CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (*(u64*)&b) & DOUBLE_SIGN )) *(u64*)&CPU.FPR[frd] |= 0x100000000ull; + (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; + if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; if(rc) UNK("fctid."); } - virtual void FCTIDZ(OP_REG frd, OP_REG frb, bool rc) + void FCTIDZ(OP_REG frd, OP_REG frb, bool rc) { const double b = CPU.FPR[frb]; u64 r; @@ -1612,35 +3612,21 @@ private: r = (u64)i; } - *(u64*)&CPU.FPR[frd] = 0xfff8000000000000ull | r; - if(r == 0 && ( (*(u64*)&b) & DOUBLE_SIGN )) *(u64*)&CPU.FPR[frd] |= 0x100000000ull; + (u64&)CPU.FPR[frd] = 0xfff8000000000000ull | r; + if(r == 0 && ( (u64&)b & DOUBLE_SIGN )) (u64&)CPU.FPR[frd] |= 0x100000000ull; if(rc) UNK("fctidz."); } - virtual void FCFID(OP_REG frd, OP_REG frb, bool rc) + void FCFID(OP_REG frd, OP_REG frb, bool rc) { - CPU.FPR[frd] = (double)*(u64*)&CPU.FPR[frb]; + CPU.FPR[frd] = (double)(u64&)CPU.FPR[frb]; if(rc) UNK("fcfid.");//CPU.UpdateCR1(CPU.FPR[frd]); } END_OPCODES_GROUP(G_3f); - bool IsVecGcode(const u32 gcode) + void UNK(const u32 code, const u32 opcode, const u32 gcode) { - switch(gcode) - { - case 0x47: case 0x67: case 0x7: - case 0x26: case 0xe7: case 0x207: - case 0xc7: case 0x6: - return true; - } - - return false; - } - - virtual void UNK(const s32 code, const s32 opcode, const s32 gcode) - { - UNK(wxString::Format("Unknown/Illegal opcode! (0x%08x : 0x%x : 0x%x)", code, opcode, gcode), - opcode != 0x4 && !(opcode == 0x1f && IsVecGcode(gcode))); + UNK(wxString::Format("Unknown/Illegal opcode! (0x%08x : 0x%x : 0x%x)", code, opcode, gcode)); } void UNK(const wxString& err, bool pause = true) @@ -1653,11 +3639,24 @@ private: for(uint i=0; i<32; ++i) ConLog.Write("r%d = 0x%llx", i, CPU.GPR[i]); for(uint i=0; i<32; ++i) ConLog.Write("f%d = %llf", i, CPU.FPR[i]); - for(uint i=0; i<32; ++i) ConLog.Write("v%d = 0x%s", i, CPU.VPR[i].ToString()); + for(uint i=0; i<32; ++i) ConLog.Write("v%d = 0x%s [%s]", i, CPU.VPR[i].ToString(true), CPU.VPR[i].ToString()); ConLog.Write("CR = 0x%08x", CPU.CR); ConLog.Write("LR = 0x%llx", CPU.LR); ConLog.Write("CTR = 0x%llx", CPU.CTR); - ConLog.Write("XER = 0x%llx", CPU.XER); + ConLog.Write("XER = 0x%llx [CA=%lld | OV=%lld | SO=%lld]", CPU.XER, CPU.XER.CA, CPU.XER.OV, CPU.XER.SO); + ConLog.Write("FPSCR = 0x%x " + "[RN=%d | NI=%d | XE=%d | ZE=%d | UE=%d | OE=%d | VE=%d | " + "VXCVI=%d | VXSQRT=%d | VXSOFT=%d | FPRF=%d | " + "FI=%d | FR=%d | VXVC=%d | VXIMZ=%d | " + "VXZDZ=%d | VXIDI=%d | VXISI=%d | VXSNAN=%d | " + "XX=%d | ZX=%d | UX=%d | OX=%d | VX=%d | FEX=%d | FX=%d]", + CPU.FPSCR, + CPU.FPSCR.RN, + CPU.FPSCR.NI, CPU.FPSCR.XE, CPU.FPSCR.ZE, CPU.FPSCR.UE, CPU.FPSCR.OE, CPU.FPSCR.VE, + CPU.FPSCR.VXCVI, CPU.FPSCR.VXSQRT, CPU.FPSCR.VXSOFT, CPU.FPSCR.FPRF, + CPU.FPSCR.FI, CPU.FPSCR.FR, CPU.FPSCR.VXVC, CPU.FPSCR.VXIMZ, + CPU.FPSCR.VXZDZ, CPU.FPSCR.VXIDI, CPU.FPSCR.VXISI, CPU.FPSCR.VXSNAN, + CPU.FPSCR.XX, CPU.FPSCR.ZX, CPU.FPSCR.UX, CPU.FPSCR.OX, CPU.FPSCR.VX, CPU.FPSCR.FEX, CPU.FPSCR.FX); } }; diff --git a/rpcs3/Emu/Cell/PPUOpcodes.h b/rpcs3/Emu/Cell/PPUOpcodes.h index 1bd9bc5434..4a817eecc6 100644 --- a/rpcs3/Emu/Cell/PPUOpcodes.h +++ b/rpcs3/Emu/Cell/PPUOpcodes.h @@ -8,253 +8,434 @@ #define ADD_NULL_OPCODE(name) virtual void(##name##)()=0 #define END_OPCODES_GROUP(x) /*x*/ -enum PPU_MainOpcodes +namespace PPU_opcodes { - TDI = 0x02, //Trap Doubleword Immediate - TWI = 0x03, //Trap Word Immediate - G_04 = 0x04, - MULLI = 0x07, //Multiply Low Immediate - SUBFIC = 0x08, //Subtract from Immediate Carrying - //DOZI = 0x09, - CMPLI = 0x0a, //Compare Logical Immediate - CMPI = 0x0b, //Compare Immediate - ADDIC = 0x0c, //Add Immediate Carrying - ADDIC_ = 0x0d, //Add Immediate Carrying and Record - ADDI = 0x0e, //Add Immediate - ADDIS = 0x0f, //Add Immediate Shifted - BC = 0x10, //Branch Conditional - SC = 0x11, //System Call - B = 0x12, //Branch - G_13 = 0x13, - RLWIMI = 0x14, //Rotate Left Word Immediate then Mask Insert - RLWINM = 0x15, //Rotate Left Word Immediate then AND with Mask - RLWNM = 0x17, //Rotate Left Word then AND with Mask - ORI = 0x18, //OR Immediate - ORIS = 0x19, //OR Immediate Shifted - XORI = 0x1a, //XOR Immediate - XORIS = 0x1b, //XOR Immediate Shifted - ANDI_ = 0x1c, //AND Immediate - ANDIS_ = 0x1d, //AND Immediate Shifted - G_1e = 0x1e, - G_1f = 0x1f, - LWZ = 0x20, //Load Word and Zero Indexed - LWZU = 0x21, //Load Word and Zero with Update Indexed - LBZ = 0x22, //Load Byte and Zero - LBZU = 0x23, //Load Byte and Zero with Update - STW = 0x24, //Store Word - STWU = 0x25, //Store Word with Update - STB = 0x26, //Store Byte - STBU = 0x27, //Store Byte with Update - LHZ = 0x28, //Load Halfword and Zero - LHZU = 0x29, //Load Halfword and Zero with Update - LHA = 0x2a, //Load Halfword Algebraic with Update - LHAU = 0x2b, //Load Halfword Algebraic - STH = 0x2c, //Store Halfword - STHU = 0x2d, //Store Halfword with Update - LMW = 0x2e, //Load Multiple Word - STMW = 0x2f, //Store Multiple Word - LFS = 0x30, //Load Floating-Point Single - LFSU = 0x31, //Load Floating-Point Single with Update - LFD = 0x32, //Load Floating-Point Double - LFDU = 0x33, //Load Floating-Point Double with Update - STFS = 0x34, //Store Floating-Point Single - STFSU = 0x35, //Store Floating-Point Single with Update - STFD = 0x36, //Store Floating-Point Double - STFDU = 0x37, //Store Floating-Point Double with Update - LFQ = 0x38, // - LFQU = 0x39, // - G_3a = 0x3a, - G_3b = 0x3b, - G_3e = 0x3e, - G_3f = 0x3f, -}; + enum PPU_MainOpcodes + { + TDI = 0x02, //Trap Doubleword Immediate + TWI = 0x03, //Trap Word Immediate + G_04 = 0x04, + MULLI = 0x07, //Multiply Low Immediate + SUBFIC = 0x08, //Subtract from Immediate Carrying + //DOZI = 0x09, + CMPLI = 0x0a, //Compare Logical Immediate + CMPI = 0x0b, //Compare Immediate + ADDIC = 0x0c, //Add Immediate Carrying + ADDIC_ = 0x0d, //Add Immediate Carrying and Record + ADDI = 0x0e, //Add Immediate + ADDIS = 0x0f, //Add Immediate Shifted + BC = 0x10, //Branch Conditional + SC = 0x11, //System Call + B = 0x12, //Branch + G_13 = 0x13, + RLWIMI = 0x14, //Rotate Left Word Immediate then Mask Insert + RLWINM = 0x15, //Rotate Left Word Immediate then AND with Mask + RLWNM = 0x17, //Rotate Left Word then AND with Mask + ORI = 0x18, //OR Immediate + ORIS = 0x19, //OR Immediate Shifted + XORI = 0x1a, //XOR Immediate + XORIS = 0x1b, //XOR Immediate Shifted + ANDI_ = 0x1c, //AND Immediate + ANDIS_ = 0x1d, //AND Immediate Shifted + G_1e = 0x1e, + G_1f = 0x1f, + LWZ = 0x20, //Load Word and Zero Indexed + LWZU = 0x21, //Load Word and Zero with Update Indexed + LBZ = 0x22, //Load Byte and Zero + LBZU = 0x23, //Load Byte and Zero with Update + STW = 0x24, //Store Word + STWU = 0x25, //Store Word with Update + STB = 0x26, //Store Byte + STBU = 0x27, //Store Byte with Update + LHZ = 0x28, //Load Halfword and Zero + LHZU = 0x29, //Load Halfword and Zero with Update + LHA = 0x2a, //Load Halfword Algebraic with Update + LHAU = 0x2b, //Load Halfword Algebraic + STH = 0x2c, //Store Halfword + STHU = 0x2d, //Store Halfword with Update + LMW = 0x2e, //Load Multiple Word + STMW = 0x2f, //Store Multiple Word + LFS = 0x30, //Load Floating-Point Single + LFSU = 0x31, //Load Floating-Point Single with Update + LFD = 0x32, //Load Floating-Point Double + LFDU = 0x33, //Load Floating-Point Double with Update + STFS = 0x34, //Store Floating-Point Single + STFSU = 0x35, //Store Floating-Point Single with Update + STFD = 0x36, //Store Floating-Point Double + STFDU = 0x37, //Store Floating-Point Double with Update + LFQ = 0x38, // + LFQU = 0x39, // + G_3a = 0x3a, + G_3b = 0x3b, + G_3e = 0x3e, + G_3f = 0x3f, + }; -enum G_04Opcodes -{ - VXOR = 0x262, -}; + enum G_04Opcodes + { + VADDUBM = 0x0, + VMAXUB = 0x2, + VRLB = 0x4, + VCMPEQUB = 0x6, + VMULOUB = 0x8, + VADDFP = 0xa, + VMRGHB = 0xc, + VPKUHUM = 0xe, + VADDUHM = 0x40, + VMAXUH = 0x42, + VRLH = 0x44, + VCMPEQUH = 0x46, + VMULOUH = 0x48, + VSUBFP = 0x4a, + VMRGHH = 0x4c, + VPKUWUM = 0x4e, + VADDUWM = 0x80, + VMAXUW = 0x82, + VRLW = 0x84, + VCMPEQUW = 0x86, + VMRGHW = 0x8c, + VPKUHUS = 0x8e, + VCMPEQFP = 0xc6, + VPKUWUS = 0xce, + VMAXSB = 0x102, + VSLB = 0x104, + VMULOSB = 0x108, + VREFP = 0x10a, + VMRGLB = 0x10c, + VPKSHUS = 0x10e, + VMAXSH = 0x142, + VSLH = 0x144, + VMULOSH = 0x148, + VRSQRTEFP = 0x14a, + VMRGLH = 0x14c, + VPKSWUS = 0x14e, + VADDCUW = 0x180, + VMAXSW = 0x182, + VSLW = 0x184, + VEXPTEFP = 0x18a, + VMRGLW = 0x18c, + VPKSHSS = 0x18e, + VSL = 0x1c4, + VCMPGEFP = 0x1c6, + VLOGEFP = 0x1ca, + VPKSWSS = 0x1ce, + VADDUBS = 0x200, + VMINUB = 0x202, + VSRB = 0x204, + VCMPGTUB = 0x206, + VMULEUB = 0x208, + VRFIN = 0x20a, + VSPLTB = 0x20c, + VUPKHSB = 0x20e, + VADDUHS = 0x240, + VMINUH = 0x242, + VSRH = 0x244, + VCMPGTUH = 0x246, + VMULEUH = 0x248, + VRFIZ = 0x24a, + VSPLTH = 0x24c, + VUPKHSH = 0x24e, + VADDUWS = 0x280, + VMINUW = 0x282, + VSRW = 0x284, + VCMPGTUW = 0x286, + VRFIP = 0x28a, + VSPLTW = 0x28c, + VUPKLSB = 0x28e, + VSR = 0x2c4, + VCMPGTFP = 0x2c6, + VRFIM = 0x2ca, + VUPKLSH = 0x2ce, + VADDSBS = 0x300, + VMINSB = 0x302, + VSRAB = 0x304, + VCMPGTSB = 0x306, + VMULESB = 0x308, + VCFUX = 0x30a, + VSPLTISB = 0x30c, + VPKPX = 0x30e, + VADDSHS = 0x340, + VMINSH = 0x342, + VSRAH = 0x344, + VCMPGTSH = 0x346, + VMULESH = 0x348, + VCFSX = 0x34a, + VSPLTISH = 0x34c, + VUPKHPX = 0x34e, + VADDSWS = 0x380, + VMINSW = 0x382, + VSRAW = 0x384, + VCMPGTSW = 0x386, + VCTUXS = 0x38a, + VSPLTISW = 0x38c, + VCMPBFP = 0x3c6, + VCTSXS = 0x3ca, + VUPKLPX = 0x3ce, + VSUBUBM = 0x400, + VAVGUB = 0x402, + VAND = 0x404, + VCMPEQUB_ = 0x406, + VMAXFP = 0x40a, + VSLO = 0x40c, + VSUBUHM = 0x440, + VAVGUH = 0x442, + VANDC = 0x444, + VCMPEQUH_ = 0x446, + VMINFP = 0x44a, + VSRO = 0x44c, + VSUBUWM = 0x480, + VAVGUW = 0x482, + VOR = 0x484, + VCMPEQUW_ = 0x486, + VXOR = 0x4c4, + VCMPEQFP_ = 0x4c6, + VAVGSB = 0x502, + VNOR = 0x504, + VAVGSH = 0x542, + VSUBCUW = 0x580, + VAVGSW = 0x582, + VCMPGEFP_ = 0x5c6, + VSUBUBS = 0x600, + MFVSCR = 0x604, + VCMPGTUB_ = 0x606, + VSUM4UBS = 0x608, + VSUBUHS = 0x640, + MTVSCR = 0x644, + VCMPGTUH_ = 0x646, + VSUM4SHS = 0x648, + VSUBUWS = 0x680, + VCMPGTUW_ = 0x686, + VSUM2SWS = 0x688, + VCMPGTFP_ = 0x6c6, + VSUBSBS = 0x700, + VCMPGTSB_ = 0x706, + VSUM4SBS = 0x708, + VSUBSHS = 0x740, + VCMPGTSH_ = 0x746, + VSUBSWS = 0x780, + VCMPGTSW_ = 0x786, + VSUMSWS = 0x788, + VCMPBFP_ = 0x7c6, + }; -enum G_13Opcodes //Field 21 - 30 -{ - MCRF = 0x000, - BCLR = 0x010, - CRNOR = 0x021, - CRANDC = 0x081, - ISYNC = 0x096, - CRXOR = 0x0c1, - CRNAND = 0x0e1, - CRAND = 0x101, - CREQV = 0x121, - CRORC = 0x1a1, - CROR = 0x1c1, - BCCTR = 0x210, -}; + enum G_04_VA_Opcodes + { + VMHADDSHS = 0x20, + VMHRADDSHS = 0x21, + VMLADDUHM = 0x22, + VMSUMUBM = 0x24, + VMSUMMBM = 0x25, + VMSUMUHM = 0x26, + VMSUMUHS = 0x27, + VMSUMSHM = 0x28, + VMSUMSHS = 0x29, + VSEL = 0x2a, + VPERM = 0x2b, + VSLDOI = 0x2c, + VMADDFP = 0x2e, + VNMSUBFP = 0x2f, + }; -enum G_1eOpcodes //Field 27 - 29 -{ - RLDICL = 0x0, - RLDICR = 0x1, - RLDIC = 0x2, - RLDIMI = 0x3, -}; + enum G_13Opcodes //Field 21 - 30 + { + MCRF = 0x000, + BCLR = 0x010, + CRNOR = 0x021, + CRANDC = 0x081, + ISYNC = 0x096, + CRXOR = 0x0c1, + CRNAND = 0x0e1, + CRAND = 0x101, + CREQV = 0x121, + CRORC = 0x1a1, + CROR = 0x1c1, + BCCTR = 0x210, + }; -enum G_1fOpcodes //Field 21 - 30 -{ - CMP = 0x000, - TW = 0x004, - LVEBX = 0x007, //Load Vector Element Byte Indexed - SUBFC = 0x008, //Subtract from Carrying - MULHDU = 0x009, - ADDC = 0x00a, - MULHWU = 0x00b, - MFOCRF = 0x013, - LWARX = 0x014, - LDX = 0x015, - LWZX = 0x017, - SLW = 0x018, - CNTLZW = 0x01a, - SLD = 0x01b, - AND = 0x01c, - CMPL = 0x020, - LVEHX = 0x027, //Load Vector Element Halfword Indexed - SUBF = 0x028, - LDUX = 0x035, //Load Doubleword with Update Indexed - DCBST = 0x036, - CNTLZD = 0x03a, - ANDC = 0x03c, - LVEWX = 0x047, //Load Vector Element Word Indexed - MULHD = 0x049, - MULHW = 0x04b, - LDARX = 0x054, - DCBF = 0x056, - LBZX = 0x057, - LVX = 0x067, - NEG = 0x068, - LBZUX = 0x077, - NOR = 0x07c, - SUBFE = 0x088, //Subtract from Extended - ADDE = 0x08a, - MTOCRF = 0x090, - STDX = 0x095, - STWCX_ = 0x096, - STWX = 0x097, - STDUX = 0x0b5, - ADDZE = 0x0ca, - STDCX_ = 0x0d6, - STBX = 0x0d7, - STVX = 0x0e7, - MULLD = 0x0e9, - ADDME = 0x0ea, - MULLW = 0x0eb, - DCBTST = 0x0f6, - DOZ = 0x108, - ADD = 0x10a, - DCBT = 0x116, - LHZX = 0x117, - EQV = 0x11c, - ECIWX = 0x136, - LHZUX = 0x137, - XOR = 0x13c, - MFSPR = 0x153, - LHAX = 0x157, - ABS = 0x168, - MFTB = 0x173, - LHAUX = 0x177, - STHX = 0x197, //Store Halfword Indexed - ORC = 0x19c, //OR with Complement - ECOWX = 0x1b6, - OR = 0x1bc, - DIVDU = 0x1c9, - DIVWU = 0x1cb, - MTSPR = 0x1d3, - DCBI = 0x1d6, - DIVD = 0x1e9, - DIVW = 0x1eb, - LWBRX = 0x216, - LFSX = 0x217, - SRW = 0x218, - SRD = 0x21b, - LFSUX = 0x237, - SYNC = 0x256, - LFDX = 0x257, - LFDUX = 0x277, - STFSX = 0x297, - LHBRX = 0x316, - SRAW = 0x318, - SRAD = 0x31A, - SRAWI = 0x338, - SRADI1 = 0x33a, //sh_5 == 0 - SRADI2 = 0x33b, //sh_5 != 0 - EIEIO = 0x356, - EXTSH = 0x39a, - EXTSB = 0x3ba, - STFIWX = 0x3d7, - EXTSW = 0x3da, - ICBI = 0x3d6, - DCBZ = 0x3f6, -}; + enum G_1eOpcodes //Field 27 - 29 + { + RLDICL = 0x0, + RLDICR = 0x1, + RLDIC = 0x2, + RLDIMI = 0x3, + }; -enum G_3aOpcodes //Field 30 - 31 -{ - LD = 0x0, - LDU = 0x1, -}; + enum G_1fOpcodes //Field 21 - 30 + { + CMP = 0x000, + TW = 0x004, + LVSL = 0x006, //Load Vector for Shift Left + LVEBX = 0x007, //Load Vector Element Byte Indexed + SUBFC = 0x008, //Subtract from Carrying + MULHDU = 0x009, + ADDC = 0x00a, + MULHWU = 0x00b, + MFOCRF = 0x013, + LWARX = 0x014, + LDX = 0x015, + LWZX = 0x017, + SLW = 0x018, + CNTLZW = 0x01a, + SLD = 0x01b, + AND = 0x01c, + CMPL = 0x020, + LVSR = 0x026, //Load Vector for Shift Right + LVEHX = 0x027, //Load Vector Element Halfword Indexed + SUBF = 0x028, + LDUX = 0x035, //Load Doubleword with Update Indexed + DCBST = 0x036, + CNTLZD = 0x03a, + ANDC = 0x03c, + LVEWX = 0x047, //Load Vector Element Word Indexed + MULHD = 0x049, + MULHW = 0x04b, + LDARX = 0x054, + DCBF = 0x056, + LBZX = 0x057, + LVX = 0x067, //Load Vector Indexed + NEG = 0x068, + LBZUX = 0x077, + NOR = 0x07c, + STVEBX = 0x087, //Store Vector Element Byte Indexed + SUBFE = 0x088, //Subtract from Extended + ADDE = 0x08a, + MTOCRF = 0x090, + STDX = 0x095, + STWCX_ = 0x096, + STWX = 0x097, + STVEHX = 0x0a7, //Store Vector Element Halfword Indexed + STDUX = 0x0b5, + STVEWX = 0x0c7, //Store Vector Element Word Indexed + ADDZE = 0x0ca, + STDCX_ = 0x0d6, + STBX = 0x0d7, + STVX = 0x0e7, + MULLD = 0x0e9, + ADDME = 0x0ea, + MULLW = 0x0eb, + DCBTST = 0x0f6, + DOZ = 0x108, + ADD = 0x10a, + DCBT = 0x116, + LHZX = 0x117, + EQV = 0x11c, + ECIWX = 0x136, + LHZUX = 0x137, + XOR = 0x13c, + MFSPR = 0x153, + DST = 0x156, //Data Stream Touch + LHAX = 0x157, + LVXL = 0x167, //Load Vector Indexed Last + ABS = 0x168, + MFTB = 0x173, + DSTST = 0x176, //Data Stream Touch for Store + LHAUX = 0x177, + STHX = 0x197, //Store Halfword Indexed + ORC = 0x19c, //OR with Complement + ECOWX = 0x1b6, + OR = 0x1bc, + DIVDU = 0x1c9, + DIVWU = 0x1cb, + MTSPR = 0x1d3, + DCBI = 0x1d6, + NAND = 0x1dc, + STVXL = 0x1e7, //Store Vector Indexed Last + DIVD = 0x1e9, + DIVW = 0x1eb, + LVLX = 0x207, //Load Vector Left Indexed + LWBRX = 0x216, + LFSX = 0x217, + SRW = 0x218, + SRD = 0x21b, + LVRX = 0x227, //Load Vector Right Indexed + LFSUX = 0x237, + SYNC = 0x256, + LFDX = 0x257, + LFDUX = 0x277, + STVLX = 0x287, //Store Vector Left Indexed + STFSX = 0x297, + STVRX = 0x2a7, //Store Vector Right Indexed + STFDX = 0x2d7, //Store Floating-Point Double Indexed + LVLXL = 0x307, //Load Vector Left Indexed Last + LHBRX = 0x316, + SRAW = 0x318, + SRAD = 0x31a, + LVRXL = 0x327, //Load Vector Right Indexed Last + DSS = 0x336, //Data Stream Stop + SRAWI = 0x338, + SRADI1 = 0x33a, //sh_5 == 0 + SRADI2 = 0x33b, //sh_5 != 0 + EIEIO = 0x356, + STVLXL = 0x387, //Store Vector Left Indexed Last + EXTSH = 0x39a, + STVRXL = 0x3a7, //Store Vector Right Indexed Last + EXTSB = 0x3ba, + STFIWX = 0x3d7, + EXTSW = 0x3da, + ICBI = 0x3d6, + DCBZ = 0x3f6, + }; -enum G_3bOpcodes //Field 26 - 30 -{ - FDIVS = 0x12, - FSUBS = 0x14, - FADDS = 0x15, - FSQRTS = 0x16, - FRES = 0x18, - FMULS = 0x19, - FMSUBS = 0x1c, - FMADDS = 0x1d, - FNMSUBS = 0x1e, - FNMADDS = 0x1f, -}; + enum G_3aOpcodes //Field 30 - 31 + { + LD = 0x0, + LDU = 0x1, + }; -enum G_3eOpcodes //Field 30 - 31 -{ - STD = 0x0, - STDU = 0x1, -}; + enum G_3bOpcodes //Field 26 - 30 + { + FDIVS = 0x12, + FSUBS = 0x14, + FADDS = 0x15, + FSQRTS = 0x16, + FRES = 0x18, + FMULS = 0x19, + FMSUBS = 0x1c, + FMADDS = 0x1d, + FNMSUBS = 0x1e, + FNMADDS = 0x1f, + }; -enum G_3fOpcodes //Field 21 - 30 -{ - MTFSB1 = 0x026, - MCRFS = 0x040, - MTFSB0 = 0x046, - MTFSFI = 0x086, - MFFS = 0x247, - MTFSF = 0x2c7, + enum G_3eOpcodes //Field 30 - 31 + { + STD = 0x0, + STDU = 0x1, + }; - FCMPU = 0x000, - FRSP = 0x00c, - FCTIW = 0x00e, - FCTIWZ = 0x00f, - FDIV = 0x012, - FSUB = 0x014, - FADD = 0x015, - FSQRT = 0x016, - FSEL = 0x017, - FMUL = 0x019, - FRSQRTE = 0x01a, - FMSUB = 0x01c, - FMADD = 0x01d, - FNMSUB = 0x01e, - FNMADD = 0x01f, - FCMPO = 0x020, - FNEG = 0x028, - FMR = 0x048, - FNABS = 0x088, - FABS = 0x108, - FCTID = 0x32e, - FCTIDZ = 0x32f, - FCFID = 0x34e, -}; + enum G_3fOpcodes //Field 21 - 30 + { + MTFSB1 = 0x026, + MCRFS = 0x040, + MTFSB0 = 0x046, + MTFSFI = 0x086, + MFFS = 0x247, + MTFSF = 0x2c7, -//118 + FCMPU = 0x000, + FRSP = 0x00c, + FCTIW = 0x00e, + FCTIWZ = 0x00f, + FDIV = 0x012, + FSUB = 0x014, + FADD = 0x015, + FSQRT = 0x016, + FSEL = 0x017, + FMUL = 0x019, + FRSQRTE = 0x01a, + FMSUB = 0x01c, + FMADD = 0x01d, + FNMSUB = 0x01e, + FNMADD = 0x01f, + FCMPO = 0x020, + FNEG = 0x028, + FMR = 0x048, + FNABS = 0x088, + FABS = 0x108, + FCTID = 0x32e, + FCTIDZ = 0x32f, + FCFID = 0x34e, + }; +} class PPU_Opcodes { @@ -273,7 +454,163 @@ public: ADD_OPCODE(TWI,(OP_uIMM to, OP_REG ra, OP_sIMM simm16)); START_OPCODES_GROUP(G_04) - ADD_OPCODE(VXOR,(OP_REG vrd, OP_REG vra, OP_REG vrb)); + ADD_OPCODE(MFVSCR,(OP_REG vd)); + ADD_OPCODE(MTVSCR,(OP_REG vb)); + ADD_OPCODE(VADDCUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDSBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDSHS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDSWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUBM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUHM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUHS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUWM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VADDUWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAND,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VANDC,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGSB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGSH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGSW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VAVGUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCFSX,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VCFUX,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VCMPBFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPBFP_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQFP_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUB_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUH_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPEQUW_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGEFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGEFP_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTFP_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSB_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSH_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTSW_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUB_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUH_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCMPGTUW_,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VCTSXS,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VCTUXS,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VEXPTEFP,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VLOGEFP,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VMADDFP,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMAXFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXSB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXSH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXSW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMAXUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMHADDSHS,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMHRADDSHS,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMINFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINSB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINSH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINSW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMINUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMLADDUHM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMRGHB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMRGHH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMRGHW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMRGLB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMRGLH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMRGLW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMSUMMBM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMSUMSHM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMSUMSHS,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMSUMUBM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMSUMUHM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMSUMUHS,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VMULESB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULESH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULEUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULEUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULOSB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULOSH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULOUB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VMULOUH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VNMSUBFP,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VNOR,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VOR,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPERM,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VPKPX,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKSHSS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKSHUS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKSWSS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKSWUS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKUHUM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKUHUS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKUWUM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VPKUWUS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VREFP,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VRFIM,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VRFIN,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VRFIP,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VRFIZ,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VRLB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VRLH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VRLW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VRSQRTEFP,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VSEL,(OP_REG vd, OP_REG va, OP_REG vb, OP_REG vc)); + ADD_OPCODE(VSL,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSLB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSLDOI,(OP_REG vd, OP_REG va, OP_REG vb, OP_uIMM sh)); + ADD_OPCODE(VSLH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSLO,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSLW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSPLTB,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VSPLTH,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VSPLTISB,(OP_REG vd, OP_sIMM simm5)); + ADD_OPCODE(VSPLTISH,(OP_REG vd, OP_sIMM simm5)); + ADD_OPCODE(VSPLTISW,(OP_REG vd, OP_sIMM simm5)); + ADD_OPCODE(VSPLTW,(OP_REG vd, OP_uIMM uimm5, OP_REG vb)); + ADD_OPCODE(VSR,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRAB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRAH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRAW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRB,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRH,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRO,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSRW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBCUW,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBFP,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBSBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBSHS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBSWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUBM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUHM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUHS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUWM,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUBUWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUMSWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUM2SWS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUM4SBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUM4SHS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VSUM4UBS,(OP_REG vd, OP_REG va, OP_REG vb)); + ADD_OPCODE(VUPKHPX,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VUPKHSB,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VUPKHSH,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VUPKLPX,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VUPKLSB,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VUPKLSH,(OP_REG vd, OP_REG vb)); + ADD_OPCODE(VXOR,(OP_REG vd, OP_REG va, OP_REG vb)); END_OPCODES_GROUP(G_04); ADD_OPCODE(MULLI,(OP_REG rd, OP_REG ra, OP_sIMM simm16)); @@ -323,12 +660,13 @@ public: START_OPCODES_GROUP(G_1f) /*0x000*/ADD_OPCODE(CMP,(OP_REG crfd, OP_REG l, OP_REG ra, OP_REG rb)); /*0x004*/ADD_OPCODE(TW,(OP_uIMM to, OP_REG ra, OP_REG rb)); + /*0x006*/ADD_OPCODE(LVSL,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x007*/ADD_OPCODE(LVEBX,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x008*/ADD_OPCODE(SUBFC,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x009*/ADD_OPCODE(MULHDU,(OP_REG rd, OP_REG ra, OP_REG rb, bool rc)); /*0x00a*/ADD_OPCODE(ADDC,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x00b*/ADD_OPCODE(MULHWU,(OP_REG rd, OP_REG ra, OP_REG rb, bool rc)); - /*0x013*/ADD_OPCODE(MFOCRF,(OP_REG a, OP_REG fxm, OP_REG rd)); + /*0x013*/ADD_OPCODE(MFOCRF,(OP_uIMM a, OP_REG rd, OP_uIMM crm)); /*0x014*/ADD_OPCODE(LWARX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x015*/ADD_OPCODE(LDX,(OP_REG ra, OP_REG rs, OP_REG rb)); /*0x017*/ADD_OPCODE(LWZX,(OP_REG rd, OP_REG ra, OP_REG rb)); @@ -337,6 +675,7 @@ public: /*0x01b*/ADD_OPCODE(SLD,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); /*0x01c*/ADD_OPCODE(AND,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); /*0x020*/ADD_OPCODE(CMPL,(OP_REG bf, OP_REG l, OP_REG ra, OP_REG rb)); + /*0x026*/ADD_OPCODE(LVSR,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x027*/ADD_OPCODE(LVEHX,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x028*/ADD_OPCODE(SUBF,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x035*/ADD_OPCODE(LDUX,(OP_REG rd, OP_REG ra, OP_REG rb)); @@ -349,21 +688,24 @@ public: /*0x054*/ADD_OPCODE(LDARX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x056*/ADD_OPCODE(DCBF,(OP_REG ra, OP_REG rb)); /*0x057*/ADD_OPCODE(LBZX,(OP_REG rd, OP_REG ra, OP_REG rb)); - /*0x067*/ADD_OPCODE(LVX,(OP_REG vrd, OP_REG ra, OP_REG rb)); + /*0x067*/ADD_OPCODE(LVX,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x068*/ADD_OPCODE(NEG,(OP_REG rd, OP_REG ra, OP_REG oe, bool rc)); /*0x077*/ADD_OPCODE(LBZUX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x07c*/ADD_OPCODE(NOR,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); + /*0x087*/ADD_OPCODE(STVEBX,(OP_REG vs, OP_REG ra, OP_REG rb)); /*0x088*/ADD_OPCODE(SUBFE,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x08a*/ADD_OPCODE(ADDE,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); - /*0x090*/ADD_OPCODE(MTOCRF,(OP_REG fxm, OP_REG rs)); + /*0x090*/ADD_OPCODE(MTOCRF,(OP_REG crm, OP_REG rs)); /*0x095*/ADD_OPCODE(STDX,(OP_REG rs, OP_REG ra, OP_REG rb)); /*0x096*/ADD_OPCODE(STWCX_,(OP_REG rs, OP_REG ra, OP_REG rb)); /*0x097*/ADD_OPCODE(STWX,(OP_REG rs, OP_REG ra, OP_REG rb)); + /*0x0a7*/ADD_OPCODE(STVEHX,(OP_REG vs, OP_REG ra, OP_REG rb)); /*0x0b5*/ADD_OPCODE(STDUX,(OP_REG rs, OP_REG ra, OP_REG rb)); + /*0x0c7*/ADD_OPCODE(STVEWX,(OP_REG vs, OP_REG ra, OP_REG rb)); /*0x0ca*/ADD_OPCODE(ADDZE,(OP_REG rd, OP_REG ra, OP_REG oe, bool rc)); /*0x0d6*/ADD_OPCODE(STDCX_,(OP_REG rs, OP_REG ra, OP_REG rb)); /*0x0d7*/ADD_OPCODE(STBX,(OP_REG rs, OP_REG ra, OP_REG rb)); - /*0x0e7*/ADD_OPCODE(STVX,(OP_REG vrd, OP_REG ra, OP_REG rb)); + /*0x0e7*/ADD_OPCODE(STVX,(OP_REG vs, OP_REG ra, OP_REG rb)); /*0x0e9*/ADD_OPCODE(MULLD,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x0ea*/ADD_OPCODE(ADDME,(OP_REG rd, OP_REG ra, OP_REG oe, bool rc)); /*0x0eb*/ADD_OPCODE(MULLW,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); @@ -376,9 +718,12 @@ public: /*0x137*/ADD_OPCODE(LHZUX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x13c*/ADD_OPCODE(XOR,(OP_REG rs, OP_REG ra, OP_REG rb, bool rc)); /*0x153*/ADD_OPCODE(MFSPR,(OP_REG rd, OP_REG spr)); + /*0x156*/ADD_OPCODE(DST,(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t)); /*0x157*/ADD_OPCODE(LHAX,(OP_REG rd, OP_REG ra, OP_REG rb)); + /*0x167*/ADD_OPCODE(LVXL,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x168*/ADD_OPCODE(ABS,(OP_REG rd, OP_REG ra, OP_REG oe, bool rc)); /*0x173*/ADD_OPCODE(MFTB,(OP_REG rd, OP_REG spr)); + /*0x176*/ADD_OPCODE(DSTST,(OP_REG ra, OP_REG rb, OP_uIMM strm, OP_uIMM t)); /*0x177*/ADD_OPCODE(LHAUX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x197*/ADD_OPCODE(STHX,(OP_REG rs, OP_REG ra, OP_REG rb)); /*0x19c*/ADD_OPCODE(ORC,(OP_REG rs, OP_REG ra, OP_REG rb, bool rc)); @@ -388,25 +733,37 @@ public: /*0x1cb*/ADD_OPCODE(DIVWU,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x1d3*/ADD_OPCODE(MTSPR,(OP_REG spr, OP_REG rs)); /*0x1d6*///DCBI + /*0x1dc*/ADD_OPCODE(NAND,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); + /*0x1e7*/ADD_OPCODE(STVXL,(OP_REG vs, OP_REG ra, OP_REG rb)); /*0x1e9*/ADD_OPCODE(DIVD,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); /*0x1eb*/ADD_OPCODE(DIVW,(OP_REG rd, OP_REG ra, OP_REG rb, OP_REG oe, bool rc)); + /*0x207*/ADD_OPCODE(LVLX,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x216*/ADD_OPCODE(LWBRX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x217*/ADD_OPCODE(LFSX,(OP_REG frd, OP_REG ra, OP_REG rb)); /*0x218*/ADD_OPCODE(SRW,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); /*0x21b*/ADD_OPCODE(SRD,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); + /*0x227*/ADD_OPCODE(LVRX,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x237*/ADD_OPCODE(LFSUX,(OP_REG frd, OP_REG ra, OP_REG rb)); /*0x256*/ADD_OPCODE(SYNC,(OP_REG l)); /*0x257*/ADD_OPCODE(LFDX,(OP_REG frd, OP_REG ra, OP_REG rb)); /*0x277*/ADD_OPCODE(LFDUX,(OP_REG frd, OP_REG ra, OP_REG rb)); - /*0x297*/ADD_OPCODE(STFSX,(OP_REG rs, OP_REG ra, OP_REG rb)); + /*0x287*/ADD_OPCODE(STVLX,(OP_REG vs, OP_REG ra, OP_REG rb)); + /*0x297*/ADD_OPCODE(STFSX,(OP_REG frs, OP_REG ra, OP_REG rb)); + /*0x2a7*/ADD_OPCODE(STVRX,(OP_REG vs, OP_REG ra, OP_REG rb)); + /*0x2d7*/ADD_OPCODE(STFDX,(OP_REG frs, OP_REG ra, OP_REG rb)); + /*0x307*/ADD_OPCODE(LVLXL,(OP_REG vd, OP_REG ra, OP_REG rb)); /*0x316*/ADD_OPCODE(LHBRX,(OP_REG rd, OP_REG ra, OP_REG rb)); /*0x318*/ADD_OPCODE(SRAW,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); - /*0x31A*/ADD_OPCODE(SRAD,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); + /*0x31a*/ADD_OPCODE(SRAD,(OP_REG ra, OP_REG rs, OP_REG rb, bool rc)); + /*0x327*/ADD_OPCODE(LVRXL,(OP_REG vd, OP_REG ra, OP_REG rb)); + /*0x336*/ADD_OPCODE(DSS,(OP_uIMM strm, OP_uIMM a)); /*0x338*/ADD_OPCODE(SRAWI,(OP_REG ra, OP_REG rs, OP_REG sh, bool rc)); /*0x33a*/ADD_OPCODE(SRADI1,(OP_REG ra, OP_REG rs, OP_REG sh, bool rc)); /*0x33b*/ADD_OPCODE(SRADI2,(OP_REG ra, OP_REG rs, OP_REG sh, bool rc)); /*0x356*/ADD_OPCODE(EIEIO,()); + /*0x387*/ADD_OPCODE(STVLXL,(OP_REG sd, OP_REG ra, OP_REG rb)); /*0x39a*/ADD_OPCODE(EXTSH,(OP_REG ra, OP_REG rs, bool rc)); + /*0x3a7*/ADD_OPCODE(STVRXL,(OP_REG sd, OP_REG ra, OP_REG rb)); /*0x3ba*/ADD_OPCODE(EXTSB,(OP_REG ra, OP_REG rs, bool rc)); /*0x3d7*/ADD_OPCODE(STFIWX,(OP_REG frs, OP_REG ra, OP_REG rb)); /*0x3da*/ADD_OPCODE(EXTSW,(OP_REG ra, OP_REG rs, bool rc)); @@ -493,7 +850,7 @@ public: ADD_OPCODE(FCFID,(OP_REG frd, OP_REG frb, bool rc)); END_OPCODES_GROUP(G_3f); - ADD_OPCODE(UNK,(const s32 code, const s32 opcode, const s32 gcode)); + ADD_OPCODE(UNK,(const u32 code, const u32 opcode, const u32 gcode)); }; #undef START_OPCODES_GROUP diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 945caabc34..0b8eb74234 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -4,11 +4,20 @@ #include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPUDisAsm.h" -#include "Emu/SysCalls/SysCalls.h" - extern gcmInfo gcm_info; -PPUThread::PPUThread() : PPCThread(PPC_THREAD_PPU) +PPUThread& GetCurrentPPUThread() +{ + PPCThread* thread = GetCurrentPPCThread(); + + if(!thread || thread->IsSPU()) throw wxString("GetCurrentPPUThread: bad thread"); + + return *(PPUThread*)thread; +} + +PPUThread::PPUThread() + : PPCThread(PPC_THREAD_PPU) + , SysCalls(*this) { Reset(); } @@ -26,13 +35,14 @@ void PPUThread::DoReset() memset(GPR, 0, sizeof(GPR)); memset(SPRG, 0, sizeof(SPRG)); - CR.CR = 0; - LR = 0; - CTR = 0; - USPRG = 0; - TB = 0; - XER.XER = 0; + CR.CR = 0; + LR = 0; + CTR = 0; + USPRG0 = 0; + TB = 0; + XER.XER = 0; FPSCR.FPSCR = 0; + VSCR.VSCR = 0; cycle = 0; @@ -40,50 +50,6 @@ void PPUThread::DoReset() reserve_addr = 0; } -void PPUThread::SetBranch(const u64 pc) -{ - u64 fid, waddr; - if(Memory.MemFlags.IsFlag(pc, waddr, fid)) - { - GPR[3] = SysCallsManager.DoFunc(fid, *this); - - if((s64)GPR[3] < 0 && fid != 0x72a577ce && fid != 0x8461e528) ConLog.Write("Func[0x%llx] done with code [0x%llx]! #pc: 0x%llx", fid, GPR[3], PC); -#ifdef HLE_CALL_LOG - else ConLog.Warning("Func[0xll%x] done with code [0x%llx]! #pc: 0x%llx", fid, GPR[3], PC); -#endif - //ConLog.Warning("Func waddr: 0x%llx", waddr); - const u64 addr = Emu.GetTLSAddr(); - Memory.Write32(waddr, addr); - Memory.Write32(addr, PC + 4); - if(fid == 0x744680a2) Memory.Write32(addr+4, GPR[3]); - //Memory.Write32(addr+4, Emu.GetTLSMemsz()); - } - else if(pc == Emu.GetRSXCallback()) - { - //ConLog.Warning("gcm: callback(context=0x%llx, count=0x%llx) #pc: 0x%llx", GPR[3], GPR[4], PC); - - CellGcmContextData& ctx = *(CellGcmContextData*)Memory.GetMemFromAddr(GPR[3]); - CellGcmControl& ctrl = *(CellGcmControl*)Memory.GetMemFromAddr(gcm_info.control_addr); - - while(ctrl.put != ctrl.get) Sleep(1); - - const u32 reserve = GPR[4]; - - ctx.current = re(re(ctx.begin) + reserve); - - Emu.GetGSManager().GetRender().Pause(); - ctrl.put = ctrl.get = re(reserve); - Emu.GetGSManager().GetRender().Resume(); - - GPR[3] = 0; - - PPCThread::SetBranch(PC + 4); - return; - } - - PPCThread::SetBranch(pc); -} - void PPUThread::AddArgv(const wxString& arg) { stack_point -= arg.Len() + 1; @@ -97,6 +63,7 @@ void PPUThread::InitRegs() const u32 entry = Memory.Read32(PC); const u32 rtoc = Memory.Read32(PC + 4); + ConLog.Write("entry = 0x%x", entry); ConLog.Write("rtoc = 0x%x", rtoc); SetPc(entry); @@ -123,6 +90,7 @@ void PPUThread::InitRegs() return; } + /* const s32 tls_size = Emu.GetTLSFilesz() * thread_num; if(tls_size >= Emu.GetTLSMemsz()) @@ -131,6 +99,7 @@ void PPUThread::InitRegs() Emu.Pause(); return; } + */ stack_point = Memory.AlignAddr(stack_point, 0x200) - 0x200; @@ -154,13 +123,14 @@ void PPUThread::InitRegs() //GPR[10] = 0x131700; GPR[11] = 0x80; GPR[12] = Emu.GetMallocPageSize(); - GPR[13] = 0x10007060; + GPR[13] = Memory.MainMem.Alloc(0x10000) + 0x7060; GPR[28] = GPR[4]; GPR[29] = GPR[3]; GPR[31] = GPR[5]; CTR = PC; CR.CR = 0x22000082; + VSCR.NJ = 1; } u64 PPUThread::GetFreeStackSize() const @@ -193,8 +163,11 @@ void PPUThread::DoPause() void PPUThread::DoStop() { - delete m_dec; - m_dec = 0; + if(m_dec) + { + delete m_dec; + m_dec = nullptr; + } } bool dump_enable = false; @@ -220,36 +193,31 @@ void PPUThread::DoCode(const s32 code) m_dec->Decode(code); } -bool FPRdouble::IsINF(double d) +bool FPRdouble::IsINF(PPCdouble d) { return wxFinite(d) ? 1 : 0; } -bool FPRdouble::IsNaN(double d) +bool FPRdouble::IsNaN(PPCdouble d) { return wxIsNaN(d) ? 1 : 0; } -bool FPRdouble::IsQNaN(double d) +bool FPRdouble::IsQNaN(PPCdouble d) { - return - ((*(u64*)&d & DOUBLE_EXP) == DOUBLE_EXP) && - ((*(u64*)&d & 0x0007fffffffffffULL) == DOUBLE_ZERO) && - ((*(u64*)&d & 0x000800000000000ULL) == 0x000800000000000ULL); + return d.GetType() == FPR_QNAN; } -bool FPRdouble::IsSNaN(double d) +bool FPRdouble::IsSNaN(PPCdouble d) { - return - ((*(u64*)&d & DOUBLE_EXP) == DOUBLE_EXP) && - ((*(u64*)&d & DOUBLE_FRAC) != DOUBLE_ZERO) && - ((*(u64*)&d & 0x0008000000000000ULL) == DOUBLE_ZERO); + return d.GetType() == FPR_SNAN; } -int FPRdouble::Cmp(double a, double b) +int FPRdouble::Cmp(PPCdouble a, PPCdouble b) { if(a < b) return CR_LT; if(a > b) return CR_GT; if(a == b) return CR_EQ; + return CR_SO; } \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 4e0d443a71..7e1c150632 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -1,5 +1,7 @@ #pragma once #include "Emu/Cell/PPCThread.h" +#include "Emu/SysCalls/SysCalls.h" +#include "rpcs3.h" enum { @@ -215,14 +217,14 @@ union CRhdr struct { - u8 cr0 : 4; - u8 cr1 : 4; - u8 cr2 : 4; - u8 cr3 : 4; - u8 cr4 : 4; - u8 cr5 : 4; - u8 cr6 : 4; u8 cr7 : 4; + u8 cr6 : 4; + u8 cr5 : 4; + u8 cr4 : 4; + u8 cr3 : 4; + u8 cr2 : 4; + u8 cr1 : 4; + u8 cr0 : 4; }; }; @@ -239,6 +241,49 @@ union XERhdr }; }; +union VSCRhdr +{ + u32 VSCR; + + struct + { + /* + Saturation. A sticky status bit indicating that some field in a saturating instruction saturated since the last + time SAT was cleared. In other words when SAT = ‘1’ it remains set to ‘1’ until it is cleared to ‘0’ by an + mtvscr instruction. + 1 The vector saturate instruction implicitly sets when saturation has occurred on the results one of + the vector instructions having saturate in its name: + Move To VSCR (mtvscr) + Vector Add Integer with Saturation (vaddubs, vadduhs, vadduws, vaddsbs, vaddshs, + vaddsws) + Vector Subtract Integer with Saturation (vsububs, vsubuhs, vsubuws, vsubsbs, vsubshs, + vsubsws) + Vector Multiply-Add Integer with Saturation (vmhaddshs, vmhraddshs) + Vector Multiply-Sum with Saturation (vmsumuhs, vmsumshs, vsumsws) + Vector Sum-Across with Saturation (vsumsws, vsum2sws, vsum4sbs, vsum4shs, + vsum4ubs) + Vector Pack with Saturation (vpkuhus, vpkuwus, vpkshus, vpkswus, vpkshss, vpkswss) + Vector Convert to Fixed-Point with Saturation (vctuxs, vctsxs) + 0 Indicates no saturation occurred; mtvscr can explicitly clear this bit. + */ + u32 SAT : 1; + u32 X : 15; + + /* + Non-Java. A mode control bit that determines whether vector floating-point operations will be performed + in a Java-IEEE-C9X–compliant mode or a possibly faster non-Java/non-IEEE mode. + 0 The Java-IEEE-C9X–compliant mode is selected. Denormalized values are handled as specified + by Java, IEEE, and C9X standard. + 1 The non-Java/non-IEEE–compliant mode is selected. If an element in a source vector register + contains a denormalized value, the value ‘0’ is used instead. If an instruction causes an underflow + exception, the corresponding element in the target VR is cleared to ‘0’. In both cases, the ‘0’ + has the same sign as the denormalized or underflowing value. + */ + u32 NJ : 1; + u32 Y : 15; + }; +}; + enum FPRType { FPR_NORM, @@ -280,35 +325,53 @@ struct PPCdouble }; FPRType type; + + operator double&() { return _double; } + operator const double&() const { return _double; } - u32 GetType() + PPCdouble& operator = (const PPCdouble& r) { - if(exp > 0 && exp < 0x7ff) return sign ? FPR_NN : FPR_PN; - - if(frac) - { - if(exp) return FPR_QNAN; - - return sign ? FPR_INF : FPR_PINF; - } - - return sign ? FPR_NZ : FPR_PZ; + _u64 = r._u64; + type = UpdateType(); + return *this; } - u32 To32() + FPRType UpdateType() const { - if (exp > 896 || (!frac && !exp)) + const int fpc = _fpclass(_double); + + switch(fpc) { - return ((_u64 >> 32) & 0xc0000000) | ((_u64 >> 29) & 0x3fffffff); + case _FPCLASS_SNAN: return FPR_SNAN; + case _FPCLASS_QNAN: return FPR_QNAN; + case _FPCLASS_NINF: return FPR_NINF; + case _FPCLASS_NN: return FPR_NN; + case _FPCLASS_ND: return FPR_ND; + case _FPCLASS_NZ: return FPR_NZ; + case _FPCLASS_PZ: return FPR_PZ; + case _FPCLASS_PD: return FPR_PD; + case _FPCLASS_PN: return FPR_PN; + case _FPCLASS_PINF: return FPR_PINF; } - if (exp >= 874) - { - return ((0x80000000 | (frac >> 21)) >> (905 - exp)) | (_u64 >> 32) & 0x80000000; - } + throw wxString::Format("PPCdouble::UpdateType() -> unknown fpclass (0x%04x).", fpc); + } - //? - return ((_u64 >> 32) & 0xc0000000) | ((_u64 >> 29) & 0x3fffffff); + FPRType GetType() const + { + return type; + } + + u32 To32() const + { + float res = _double; + + return (u32&)res; + } + + u64 To64() const + { + return (u64&)_double; } u32 GetZerosCount() @@ -369,370 +432,76 @@ struct PPCdouble struct FPRdouble { - static PPCdouble ConvertToIntegerMode(const PPCdouble& d, FPSCRhdr& fpscr, bool is_64, u32 round_mode) - { - PPCdouble ret; - - if(d.exp == 2047) - { - if (d.frac == 0) - { - ret.type = FPR_INF; - - fpscr.FI = 0; - fpscr.FR = 0; - fpscr.VXCVI = 1; - - if(fpscr.VE == 0) - { - if(is_64) - { - return d.sign ? 0x8000000000000000 : 0x7FFFFFFFFFFFFFFF; - } - else - { - return d.sign ? 0x80000000 : 0x7FFFFFFF; - } - - fpscr.FPRF = 0; - } - } - else if(d.nan == 0) - { - ret.type = FPR_SNAN; - - fpscr.FI = 0; - fpscr.FR = 0; - fpscr.VXCVI = 1; - fpscr.VXSNAN = 1; - - if(fpscr.VE == 0) - { - return is_64 ? 0x8000000000000000 : 0x80000000; - fpscr.FPRF = 0; - } - } - else - { - ret.type = FPR_QNAN; - - fpscr.FI = 0; - fpscr.FR = 0; - fpscr.VXCVI = 1; - - if(fpscr.VE == 0) - { - return is_64 ? 0x8000000000000000 : 0x80000000; - fpscr.FPRF = 0; - } - } - } - else if(d.exp > 1054) - { - fpscr.FI = 0; - fpscr.FR = 0; - fpscr.VXCVI = 1; - - if(fpscr.VE == 0) - { - if(is_64) - { - return d.sign ? 0x8000000000000000 : 0x7FFFFFFFFFFFFFFF; - } - else - { - return d.sign ? 0x80000000 : 0x7FFFFFFF; - } - - fpscr.FPRF = 0; - } - } - - ret.sign = d.sign; - - if(d.exp > 0) - { - ret.exp = d.exp - 1023; - ret.frac = 1 | d.frac; - } - else if(d.exp == 0) - { - ret.exp = -1022; - ret.frac = d.frac; - } - /* - if(d.exp == 0) - { - if (d.frac == 0) - { - d.type = FPR_ZERO; - } - else - { - const u32 z = d.GetZerosCount() - 8; - d.frac <<= z + 3; - d.exp -= 1023 - 1 + z; - d.type = FPR_NORM; - } - } - else - { - d.exp -= 1023; - d.type = FPR_NORM; - d.nan = 1; - d.frac <<= 3; - } - */ - - return ret; - } - - static u32 ConvertToFloatMode(PPCdouble& d, u32 RN) - { - /* - u32 fpscr = 0; - switch (d.type) - { - case FPR_NORM: - d.exp += 1023; - if (d.exp > 0) - { - fpscr |= Round(d, RN); - if(d.nan) - { - d.exp++; - d.frac >>= 4; - } - else - { - d.frac >>= 3; - } - - if(d.exp >= 2047) - { - d.exp = 2047; - d.frac = 0; - fpscr |= FPSCR_OX; - } - } - else - { - d.exp = -(s64)d.exp + 1; - - if(d.exp <= 56) - { - d.frac >>= d.exp; - fpscr |= Round(d, RN); - d.frac <<= 1; - if(d.nan) - { - d.exp = 1; - d.frac = 0; - } - else - { - d.exp = 0; - d.frac >>= 4; - fpscr |= FPSCR_UX; - } - } - else - { - d.exp = 0; - d.frac = 0; - fpscr |= FPSCR_UX; - } - } - break; - - case FPR_ZERO: - d.exp = 0; - d.frac = 0; - break; - - case FPR_NAN: - d.exp = 2047; - d.frac = 1; - break; - - case FPR_INF: - d.exp = 2047; - d.frac = 0; - break; - } - - return fpscr; - */ - return 0; - } - - static u32 Round(PPCdouble& d, u32 RN) - { - switch(RN) - { - case FPSCR_RN_NEAR: - if(d.frac & 0x7) - { - if((d.frac & 0x7) != 4 || d.frac & 0x8) - { - d.frac += 4; - } - - return FPSCR_XX; - } - return 0; - - case FPSCR_RN_ZERO: - if(d.frac & 0x7) return FPSCR_XX; - return 0; - - case FPSCR_RN_PINF: - if(!d.sign && (d.frac & 0x7)) - { - d.frac += 8; - return FPSCR_XX; - } - return 0; - - case FPSCR_RN_MINF: - if(d.sign && (d.frac & 0x7)) - { - d.frac += 8; - return FPSCR_XX; - } - return 0; - } - - return 0; - } - static const u64 double_sign = 0x8000000000000000ULL; static const u64 double_frac = 0x000FFFFFFFFFFFFFULL; - - static bool IsINF(double d); - static bool IsNaN(double d); - static bool IsQNaN(double d); - static bool IsSNaN(double d); - static int Cmp(double a, double b); + static bool IsINF(PPCdouble d); + static bool IsNaN(PPCdouble d); + static bool IsQNaN(PPCdouble d); + static bool IsSNaN(PPCdouble d); + + static int Cmp(PPCdouble a, PPCdouble b); }; union VPR_reg { //__m128i _m128i; u128 _u128; - s128 _i128; + s128 _s128; u64 _u64[2]; - s64 _i64[2]; + s64 _s64[2]; u32 _u32[4]; - s32 _i32[4]; + s32 _s32[4]; u16 _u16[8]; - s16 _i16[8]; + s16 _s16[8]; u8 _u8[16]; - s8 _i8[16]; - - //struct { float x, y, z, w; }; + s8 _s8[16]; + float _f[4]; + double _d[2]; VPR_reg() { Clear(); } - VPR_reg(const __m128i val){_u128._u64[0] = val.m128i_u64[0]; _u128._u64[1] = val.m128i_u64[1];} - VPR_reg(const u128 val) { _u128 = val; } - VPR_reg(const u64 val) { Clear(); _u64[0] = val; } - VPR_reg(const u32 val) { Clear(); _u32[0] = val; } - VPR_reg(const u16 val) { Clear(); _u16[0] = val; } - VPR_reg(const u8 val) { Clear(); _u8[0] = val; } - VPR_reg(const s128 val) { _i128 = val; } - VPR_reg(const s64 val) { Clear(); _i64[0] = val; } - VPR_reg(const s32 val) { Clear(); _i32[0] = val; } - VPR_reg(const s16 val) { Clear(); _i16[0] = val; } - VPR_reg(const s8 val) { Clear(); _i8[0] = val; } - - operator u128() const { return _u128; } - operator s128() const { return _i128; } - operator u64() const { return _u64[0]; } - operator s64() const { return _i64[0]; } - operator u32() const { return _u32[0]; } - operator s32() const { return _i32[0]; } - operator u16() const { return _u16[0]; } - operator s16() const { return _i16[0]; } - operator u8() const { return _u8[0]; } - operator s8() const { return _i8[0]; } - operator __m128i() { __m128i ret; ret.m128i_u64[0]=_u128._u64[0]; ret.m128i_u64[1]=_u128._u64[1]; return ret; } - operator bool() const { return _u64[0] != 0 || _u64[1] != 0; } - - wxString ToString() const + wxString ToString(bool hex=false) const { - return wxString::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); + if(hex) return wxString::Format("%08x%08x%08x%08x", _u32[3], _u32[2], _u32[1], _u32[0]); + + return wxString::Format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]); } - VPR_reg operator ^ (VPR_reg right) { return _mm_xor_si128(*this, right); } - VPR_reg operator | (VPR_reg right) { return _mm_or_si128 (*this, right); } - VPR_reg operator & (VPR_reg right) { return _mm_and_si128(*this, right); } + u8 GetBit(u8 bit) + { + if(bit < 64) return (_u64[0] >> bit) & 0x1; - VPR_reg operator ^ (__m128i right) { return _mm_xor_si128(*this, right); } - VPR_reg operator | (__m128i right) { return _mm_or_si128 (*this, right); } - VPR_reg operator & (__m128i right) { return _mm_and_si128(*this, right); } + return (_u64[1] >> (bit - 64)) & 0x1; + } - bool operator == (const VPR_reg& right){ return _u64[0] == right._u64[0] && _u64[1] == right._u64[1]; } + void SetBit(u8 bit, u8 value) + { + if(bit < 64) + { + _u64[0] &= ~(1 << bit); + _u64[0] |= (value & 0x1) << bit; - bool operator == (const u128 right) { return _u64[0] == right._u64[0] && _u64[1] == right._u64[1]; } - bool operator == (const s128 right) { return _i64[0] == right._i64[0] && _i64[1] == right._i64[1]; } - bool operator == (const u64 right) { return _u64[0] == (u64)right && _u64[1] == 0; } - bool operator == (const s64 right) { return _i64[0] == (s64)right && _i64[1] == 0; } - bool operator == (const u32 right) { return _u64[0] == (u64)right && _u64[1] == 0; } - bool operator == (const s32 right) { return _i64[0] == (s64)right && _i64[1] == 0; } - bool operator == (const u16 right) { return _u64[0] == (u64)right && _u64[1] == 0; } - bool operator == (const s16 right) { return _i64[0] == (s64)right && _i64[1] == 0; } - bool operator == (const u8 right) { return _u64[0] == (u64)right && _u64[1] == 0; } - bool operator == (const s8 right) { return _i64[0] == (s64)right && _i64[1] == 0; } + return; + } - bool operator != (const VPR_reg& right){ return !(*this == right); } - bool operator != (const u128 right) { return !(*this == right); } - bool operator != (const u64 right) { return !(*this == right); } - bool operator != (const u32 right) { return !(*this == right); } - bool operator != (const u16 right) { return !(*this == right); } - bool operator != (const u8 right) { return !(*this == right); } - bool operator != (const s128 right) { return !(*this == right); } - bool operator != (const s64 right) { return !(*this == right); } - bool operator != (const s32 right) { return !(*this == right); } - bool operator != (const s16 right) { return !(*this == right); } - bool operator != (const s8 right) { return !(*this == right); } + bit -= 64; - s64& d(const u32 c) { return _i64[1 - c]; } - u64& ud(const u32 c) { return _u64[1 - c]; } - - s32& w(const u32 c) { return _i32[3 - c]; } - u32& uw(const u32 c) { return _u32[3 - c]; } - - s16& h(const u32 c) { return _i16[7 - c]; } - u16& uh(const u32 c) { return _u16[7 - c]; } - - s8& b(const u32 c) { return _i8[15 - c]; } - u8& ub(const u32 c) { return _u8[15 - c]; } + _u64[1] &= ~(1 << bit); + _u64[1] |= (value & 0x1) << bit; + } void Clear() { memset(this, 0, sizeof(*this)); } }; -/* -struct VPR_table -{ - VPR_reg t[32]; - - operator VPR_reg*() { return t; } - - VPR_reg& operator [] (int index) - { - return t[index]; - } -} -*/ - static const s32 MAX_INT_VALUE = 0x7fffffff; -class PPUThread : public PPCThread +class PPUThread + : public PPCThread + , public SysCalls { public: - double FPR[32]; //Floating Point Register + PPCdouble FPR[32]; //Floating Point Register FPSCRhdr FPSCR; //Floating Point Status and Control Register u64 GPR[32]; //General-Purpose Register VPR_reg VPR[32]; @@ -786,12 +555,16 @@ public: MSRhdr MSR; //Machine State Register PVRhdr PVR; //Processor Version Register + VSCRhdr VSCR; // Vector Status and Control Register + u64 LR; //SPR 0x008 : Link Register u64 CTR; //SPR 0x009 : Count Register - s32 USPRG; //SPR 0x100 : User-SPR General-Purpose Registers - - s32 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers + union + { + u64 USPRG0; //SPR 0x100 : User-SPR General-Purpose Register 0 + u64 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers + }; //TBR : Time-Base Registers union @@ -818,14 +591,14 @@ public: { switch(n) { - case 7: return CR.cr0; - case 6: return CR.cr1; - case 5: return CR.cr2; - case 4: return CR.cr3; - case 3: return CR.cr4; - case 2: return CR.cr5; - case 1: return CR.cr6; - case 0: return CR.cr7; + case 0: return CR.cr0; + case 1: return CR.cr1; + case 2: return CR.cr2; + case 3: return CR.cr3; + case 4: return CR.cr4; + case 5: return CR.cr5; + case 6: return CR.cr6; + case 7: return CR.cr7; } return 0; @@ -835,14 +608,14 @@ public: { switch(n) { - case 7: CR.cr0 = value; break; - case 6: CR.cr1 = value; break; - case 5: CR.cr2 = value; break; - case 4: CR.cr3 = value; break; - case 3: CR.cr4 = value; break; - case 2: CR.cr5 = value; break; - case 1: CR.cr6 = value; break; - case 0: CR.cr7 = value; break; + case 0: CR.cr0 = value; break; + case 1: CR.cr1 = value; break; + case 2: CR.cr2 = value; break; + case 3: CR.cr3 = value; break; + case 4: CR.cr4 = value; break; + case 5: CR.cr5 = value; break; + case 6: CR.cr6 = value; break; + case 7: CR.cr7 = value; break; } } @@ -850,14 +623,14 @@ public: { switch(n) { - case 7: value ? CR.cr0 |= bit : CR.cr0 &= ~bit; break; - case 6: value ? CR.cr1 |= bit : CR.cr1 &= ~bit; break; - case 5: value ? CR.cr2 |= bit : CR.cr2 &= ~bit; break; - case 4: value ? CR.cr3 |= bit : CR.cr3 &= ~bit; break; - case 3: value ? CR.cr4 |= bit : CR.cr4 &= ~bit; break; - case 2: value ? CR.cr5 |= bit : CR.cr5 &= ~bit; break; - case 1: value ? CR.cr6 |= bit : CR.cr6 &= ~bit; break; - case 0: value ? CR.cr7 |= bit : CR.cr7 &= ~bit; break; + case 0: value ? CR.cr0 |= bit : CR.cr0 &= ~bit; break; + case 1: value ? CR.cr1 |= bit : CR.cr1 &= ~bit; break; + case 2: value ? CR.cr2 |= bit : CR.cr2 &= ~bit; break; + case 3: value ? CR.cr3 |= bit : CR.cr3 &= ~bit; break; + case 4: value ? CR.cr4 |= bit : CR.cr4 &= ~bit; break; + case 5: value ? CR.cr5 |= bit : CR.cr5 &= ~bit; break; + case 6: value ? CR.cr6 |= bit : CR.cr6 &= ~bit; break; + case 7: value ? CR.cr7 |= bit : CR.cr7 &= ~bit; break; } } @@ -916,17 +689,31 @@ public: virtual wxString RegsToString() { wxString ret = PPCThread::RegsToString(); + for(uint i=0; i<32; ++i) ret += wxString::Format("GPR[%d] = 0x%llx\n", i, GPR[i]); for(uint i=0; i<32; ++i) ret += wxString::Format("FPR[%d] = %.6G\n", i, FPR[i]); + for(uint i=0; i<32; ++i) ret += wxString::Format("VPR[%d] = 0x%s [%s]\n", i, VPR[i].ToString(true), VPR[i].ToString()); ret += wxString::Format("CR = 0x%08x\n", CR); ret += wxString::Format("LR = 0x%llx\n", LR); ret += wxString::Format("CTR = 0x%llx\n", CTR); - ret += wxString::Format("XER = 0x%llx\n", XER); - ret += wxString::Format("FPSCR = 0x%x\n", FPSCR); + ret += wxString::Format("XER = 0x%llx [CA=%lld | OV=%lld | SO=%lld]\n", XER, XER.CA, XER.OV, XER.SO); + ret += wxString::Format("FPSCR = 0x%x " + "[RN=%d | NI=%d | XE=%d | ZE=%d | UE=%d | OE=%d | VE=%d | " + "VXCVI=%d | VXSQRT=%d | VXSOFT=%d | FPRF=%d | " + "FI=%d | FR=%d | VXVC=%d | VXIMZ=%d | " + "VXZDZ=%d | VXIDI=%d | VXISI=%d | VXSNAN=%d | " + "XX=%d | ZX=%d | UX=%d | OX=%d | VX=%d | FEX=%d | FX=%d]\n", + FPSCR, + FPSCR.RN, + FPSCR.NI, FPSCR.XE, FPSCR.ZE, FPSCR.UE, FPSCR.OE, FPSCR.VE, + FPSCR.VXCVI, FPSCR.VXSQRT, FPSCR.VXSOFT, FPSCR.FPRF, + FPSCR.FI, FPSCR.FR, FPSCR.VXVC, FPSCR.VXIMZ, + FPSCR.VXZDZ, FPSCR.VXIDI, FPSCR.VXISI, FPSCR.VXSNAN, + FPSCR.XX, FPSCR.ZX, FPSCR.UX, FPSCR.OX, FPSCR.VX, FPSCR.FEX, FPSCR.FX); + return ret; } - void SetBranch(const u64 pc); virtual void AddArgv(const wxString& arg); public: @@ -940,6 +727,8 @@ protected: virtual void DoResume(); virtual void DoStop(); -private: +public: virtual void DoCode(const s32 code); -}; \ No newline at end of file +}; + +PPUThread& GetCurrentPPUThread(); \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPUDecoder.h b/rpcs3/Emu/Cell/SPUDecoder.h index 1724924992..5f315a8d2a 100644 --- a/rpcs3/Emu/Cell/SPUDecoder.h +++ b/rpcs3/Emu/Cell/SPUDecoder.h @@ -31,18 +31,20 @@ class SPU_Decoder : public Decoder OP_REG RA() const { return GetField(18, 24); } OP_REG RB() const { return GetField(11, 17); } - OP_sIMM i7() const { return GetField(11, 17); } - OP_sIMM i10() const { return GetField(8, 17); } - OP_sIMM i16() const { return GetField(9, 24); } - OP_sIMM i18() const { return GetField(7, 24); } + OP_uIMM i7() const { return GetField(11, 17); } + OP_uIMM i8() const { return GetField(10, 17); } + OP_uIMM i10() const { return GetField(8, 17); } + OP_uIMM i16() const { return GetField(9, 24); } + OP_uIMM i18() const { return GetField(7, 24); } - OP_sIMM ROH() const { return GetField(16, 17); } - OP_sIMM ROL() const { return GetField(25, 31); } - OP_sIMM RO() const { return ROL()/* | (ROH() << 8)*/; } + OP_uIMM ROH() const { return GetField(16, 17); } + OP_uIMM ROL() const { return GetField(25, 31); } + OP_uIMM RO() const { return ROL() | (ROH() << 8); } OP_uIMM RR() const { return GetField(0, 10); } OP_uIMM RRR() const { return GetField(0, 3); } OP_uIMM RI7() const { return GetField(0, 10); } + OP_uIMM RI8() const { return GetField(0, 9); } OP_uIMM RI10() const { return GetField(0, 7); } OP_uIMM RI16() const { return GetField(0, 8); } OP_uIMM RI18() const { return GetField(0, 6); } @@ -93,59 +95,219 @@ public: virtual void Decode(const u32 code) { + using namespace SPU_opcodes; + m_code = code; switch(RR()) //& RI7 //0 - 10 { ADD_OPCODE(STOP,(GetField(18, 31))); ADD_OPCODE(LNOP,()); + ADD_OPCODE(SYNC,(GetField(11))); + ADD_OPCODE(DSYNC,()); + ADD_OPCODE(MFSPR,(RT(), RA())); ADD_OPCODE(RDCH,(RT(), RA())); ADD_OPCODE(RCHCNT,(RT(), RA())); ADD_OPCODE(SF,(RT(), RA(), RB())); + ADD_OPCODE(OR,(RT(), RA(), RB())); + ADD_OPCODE(BG,(RT(), RA(), RB())); + ADD_OPCODE(SFH,(RT(), RA(), RB())); + ADD_OPCODE(NOR,(RT(), RA(), RB())); + ADD_OPCODE(ABSDB,(RT(), RA(), RB())); + ADD_OPCODE(ROT,(RT(), RA(), RB())); + ADD_OPCODE(ROTM,(RT(), RA(), RB())); + ADD_OPCODE(ROTMA,(RT(), RA(), RB())); + ADD_OPCODE(SHL,(RT(), RA(), RB())); + ADD_OPCODE(ROTH,(RT(), RA(), RB())); + ADD_OPCODE(ROTHM,(RT(), RA(), RB())); + ADD_OPCODE(ROTMAH,(RT(), RA(), RB())); + ADD_OPCODE(SHLH,(RT(), RA(), RB())); + ADD_OPCODE(ROTI,(RT(), RA(), RB())); + ADD_OPCODE(ROTMI,(RT(), RA(), RB())); + ADD_OPCODE(ROTMAI,(RT(), RA(), RB())); ADD_OPCODE(SHLI,(RT(), RA(), i7())); + ADD_OPCODE(ROTHI,(RT(), RA(), i7())); + ADD_OPCODE(ROTHMI,(RT(), RA(), i7())); + ADD_OPCODE(ROTMAHI,(RT(), RA(), i7())); + ADD_OPCODE(SHLHI,(RT(), RA(), i7())); ADD_OPCODE(A,(RT(), RA(), RB())); - ADD_OPCODE(SPU_AND,(RT(), RA(), RB())); - ADD_OPCODE(LQX,(RT(), RA(), RB())); + ADD_OPCODE(AND,(RT(), RA(), RB())); + ADD_OPCODE(CG,(RT(), RA(), RB())); + ADD_OPCODE(AH,(RT(), RA(), RB())); + ADD_OPCODE(NAND,(RT(), RA(), RB())); + ADD_OPCODE(AVGB,(RT(), RA(), RB())); + ADD_OPCODE(MTSPR,(RT(), RA())); ADD_OPCODE(WRCH,(RA(), RT())); + ADD_OPCODE(BIZ,(RT(), RA())); + ADD_OPCODE(BINZ,(RT(), RA())); + ADD_OPCODE(BIHZ,(RT(), RA())); + ADD_OPCODE(BIHNZ,(RT(), RA())); + ADD_OPCODE(STOPD,(RT(), RA(), RB())); ADD_OPCODE(STQX,(RT(), RA(), RB())); ADD_OPCODE(BI,(RA())); ADD_OPCODE(BISL,(RT(), RA())); + ADD_OPCODE(IRET,(RA())); + ADD_OPCODE(BISLED,(RT(), RA())); ADD_OPCODE(HBR,(GetField(11), RO(), RA())); + ADD_OPCODE(GB,(RT(), RA())); + ADD_OPCODE(GBH,(RT(), RA())); + ADD_OPCODE(GBB,(RT(), RA())); + ADD_OPCODE(FSM,(RT(), RA())); + ADD_OPCODE(FSMH,(RT(), RA())); + ADD_OPCODE(FSMB,(RT(), RA())); + ADD_OPCODE(FREST,(RT(), RA())); + ADD_OPCODE(FRSQEST,(RT(), RA())); + ADD_OPCODE(LQX,(RT(), RA(), RB())); + ADD_OPCODE(ROTQBYBI,(RT(), RA(), RB())); + ADD_OPCODE(ROTQMBYBI,(RT(), RA(), RB())); + ADD_OPCODE(SHLQBYBI,(RT(), RA(), RB())); + ADD_OPCODE(CBX,(RT(), RA(), RB())); + ADD_OPCODE(CHX,(RT(), RA(), RB())); ADD_OPCODE(CWX,(RT(), RA(), RB())); + ADD_OPCODE(CDX,(RT(), RA(), RB())); + ADD_OPCODE(ROTQBI,(RT(), RA(), RB())); + ADD_OPCODE(ROTQMBI,(RT(), RA(), RB())); + ADD_OPCODE(SHLQBI,(RT(), RA(), RB())); ADD_OPCODE(ROTQBY,(RT(), RA(), RB())); + ADD_OPCODE(ROTQMBY,(RT(), RA(), RB())); + ADD_OPCODE(SHLQBY,(RT(), RA(), RB())); + ADD_OPCODE(ORX,(RT(), RA())); + ADD_OPCODE(CBD,(RT(), RA(), exts7(i7()))); + ADD_OPCODE(CHD,(RT(), RA(), exts7(i7()))); + ADD_OPCODE(CWD,(RT(), RA(), exts7(i7()))); + ADD_OPCODE(CDD,(RT(), RA(), exts7(i7()))); + ADD_OPCODE(ROTQBII,(RT(), RA(), i7())); + ADD_OPCODE(ROTQMBII,(RT(), RA(), i7())); + ADD_OPCODE(SHLQBII,(RT(), RA(), i7())); ADD_OPCODE(ROTQBYI,(RT(), RA(), i7())); + ADD_OPCODE(ROTQMBYI,(RT(), RA(), i7())); ADD_OPCODE(SHLQBYI,(RT(), RA(), i7())); - ADD_OPCODE(SPU_NOP,(RT())); + ADD_OPCODE(NOP,(RT())); + ADD_OPCODE(CGT,(RT(), RA(), RB())); + ADD_OPCODE(XOR,(RT(), RA(), RB())); + ADD_OPCODE(CGTH,(RT(), RA(), RB())); + ADD_OPCODE(EQV,(RT(), RA(), RB())); + ADD_OPCODE(CGTB,(RT(), RA(), RB())); + ADD_OPCODE(SUMB,(RT(), RA(), RB())); + ADD_OPCODE(HGT,(RT(), RA(), RB())); + ADD_OPCODE(CLZ,(RT(), RA())); + ADD_OPCODE(XSWD,(RT(), RA())); + ADD_OPCODE(XSHW,(RT(), RA())); + ADD_OPCODE(CNTB,(RT(), RA())); + ADD_OPCODE(XSBH,(RT(), RA())); ADD_OPCODE(CLGT,(RT(), RA(), RB())); + ADD_OPCODE(ANDC,(RT(), RA(), RB())); + ADD_OPCODE(FCGT,(RT(), RA(), RB())); + ADD_OPCODE(DFCGT,(RT(), RA(), RB())); + ADD_OPCODE(FA,(RT(), RA(), RB())); + ADD_OPCODE(FS,(RT(), RA(), RB())); + ADD_OPCODE(FM,(RT(), RA(), RB())); + ADD_OPCODE(CLGTH,(RT(), RA(), RB())); + ADD_OPCODE(ORC,(RT(), RA(), RB())); + ADD_OPCODE(FCMGT,(RT(), RA(), RB())); + ADD_OPCODE(DFCMGT,(RT(), RA(), RB())); + ADD_OPCODE(DFA,(RT(), RA(), RB())); + ADD_OPCODE(DFS,(RT(), RA(), RB())); + ADD_OPCODE(DFM,(RT(), RA(), RB())); + ADD_OPCODE(CLGTB,(RT(), RA(), RB())); + ADD_OPCODE(HLGT,(RT(), RA(), RB())); + ADD_OPCODE(DFMA,(RT(), RA(), RB())); + ADD_OPCODE(DFMS,(RT(), RA(), RB())); + ADD_OPCODE(DFNMS,(RT(), RA(), RB())); + ADD_OPCODE(DFNMA,(RT(), RA(), RB())); + ADD_OPCODE(CEQ,(RT(), RA(), RB())); + ADD_OPCODE(MPYHHU,(RT(), RA(), RB())); + ADD_OPCODE(ADDX,(RT(), RA(), RB())); + ADD_OPCODE(SFX,(RT(), RA(), RB())); + ADD_OPCODE(CGX,(RT(), RA(), RB())); + ADD_OPCODE(BGX,(RT(), RA(), RB())); + ADD_OPCODE(MPYHHA,(RT(), RA(), RB())); + ADD_OPCODE(MPYHHAU,(RT(), RA(), RB())); + ADD_OPCODE(FSCRRD,(RT())); + ADD_OPCODE(FESD,(RT(), RA())); + ADD_OPCODE(FRDS,(RT(), RA())); + ADD_OPCODE(FSCRWR,(RT(), RA())); + ADD_OPCODE(DFTSV,(RT(), RA(), i7())); + ADD_OPCODE(FCEQ,(RT(), RA(), RB())); + ADD_OPCODE(DFCEQ,(RT(), RA(), RB())); + ADD_OPCODE(MPY,(RT(), RA(), RB())); + ADD_OPCODE(MPYH,(RT(), RA(), RB())); + ADD_OPCODE(MPYHH,(RT(), RA(), RB())); + ADD_OPCODE(MPYS,(RT(), RA(), RB())); + ADD_OPCODE(CEQH,(RT(), RA(), RB())); + ADD_OPCODE(FCMEQ,(RT(), RA(), RB())); + ADD_OPCODE(DFCMEQ,(RT(), RA(), RB())); + ADD_OPCODE(MPYU,(RT(), RA(), RB())); + ADD_OPCODE(CEQB,(RT(), RA(), RB())); + ADD_OPCODE(FI,(RT(), RA(), RB())); + ADD_OPCODE(HEQ,(RT(), RA(), RB())); + } + + switch(RI8()) //0 - 9 + { + ADD_OPCODE(CFLTS,(RT(), RA(), i8())); + ADD_OPCODE(CFLTU,(RT(), RA(), i8())); + ADD_OPCODE(CSFLT,(RT(), RA(), i8())); + ADD_OPCODE(CUFLT,(RT(), RA(), i8())); } switch(RI16()) //0 - 8 { ADD_OPCODE(BRZ,(RT(), exts16(i16()))); + ADD_OPCODE(STQA,(RT(), exts16(i16()))); + ADD_OPCODE(BRNZ,(RT(), exts16(i16()))); ADD_OPCODE(BRHZ,(RT(), exts16(i16()))); ADD_OPCODE(BRHNZ,(RT(), exts16(i16()))); ADD_OPCODE(STQR,(RT(), i16())); + ADD_OPCODE(BRA,(exts16(i16()))); + ADD_OPCODE(LQA,(RT(), exts16(i16()))); + ADD_OPCODE(BRASL,(RT(), exts16(i16()))); ADD_OPCODE(BR,(exts16(i16()))); ADD_OPCODE(FSMBI,(RT(), i16())); ADD_OPCODE(BRSL,(RT(), exts16(i16()))); - ADD_OPCODE(IL,(RT(), exts16(i16()))); ADD_OPCODE(LQR,(RT(), exts16(i16()))); + ADD_OPCODE(IL,(RT(), exts16(i16()))); + ADD_OPCODE(ILHU,(RT(), i16())); + ADD_OPCODE(ILH,(RT(), i16())); + ADD_OPCODE(IOHL,(RT(), i16())); } switch(RI10()) //0 - 7 { - ADD_OPCODE(SPU_ORI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ORI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ORHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ORBI,(RT(), RA(), i10())); + ADD_OPCODE(SFI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(SFHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ANDI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ANDHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(ANDBI,(RT(), RA(), i10())); ADD_OPCODE(AI,(RT(), RA(), exts10(i10()))); ADD_OPCODE(AHI,(RT(), RA(), exts10(i10()))); ADD_OPCODE(STQD,(RT(), exts10(i10()) << 4, RA())); ADD_OPCODE(LQD,(RT(), exts10(i10()) << 4, RA())); - ADD_OPCODE(CLGTI,(RT(), RA(), i10())); - ADD_OPCODE(CLGTHI,(RT(), RA(), i10())); - ADD_OPCODE(CEQI,(RT(), RA(), i10())); + ADD_OPCODE(XORI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(XORHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(XORBI,(RT(), RA(), i10())); + ADD_OPCODE(CGTI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CGTHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CGTBI,(RT(), RA(), i10())); + ADD_OPCODE(HGTI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CLGTI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CLGTHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CLGTBI,(RT(), RA(), i10())); + ADD_OPCODE(HLGTI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(MPYI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(MPYUI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CEQI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CEQHI,(RT(), RA(), exts10(i10()))); + ADD_OPCODE(CEQBI,(RT(), RA(), i10())); + ADD_OPCODE(HEQI,(RT(), RA(), exts10(i10()))); } switch(RI18()) //0 - 6 { + ADD_OPCODE(HBRA,(RO(), i16() << 2)); ADD_OPCODE(HBRR,(RO(), exts16(i16()))); ADD_OPCODE(ILA,(RT(), i18())); } @@ -154,6 +316,10 @@ public: { ADD_OPCODE(SELB,(RC(), RA(), RB(), RT())); ADD_OPCODE(SHUFB,(RC(), RA(), RB(), RT())); + ADD_OPCODE(MPYA,(RC(), RA(), RB(), RT())); + ADD_OPCODE(FNMS,(RC(), RA(), RB(), RT())); + ADD_OPCODE(FMA,(RC(), RA(), RB(), RT())); + ADD_OPCODE(FMS,(RC(), RA(), RB(), RT())); } m_op.UNK(m_code, 0, 0); diff --git a/rpcs3/Emu/Cell/SPUDisAsm.h b/rpcs3/Emu/Cell/SPUDisAsm.h index bdec9631a6..4937f4adf5 100644 --- a/rpcs3/Emu/Cell/SPUDisAsm.h +++ b/rpcs3/Emu/Cell/SPUDisAsm.h @@ -58,6 +58,18 @@ private: { Write("lnop"); } + virtual void SYNC(OP_uIMM Cbit) + { + Write(wxString::Format("sync %d", Cbit)); + } + virtual void DSYNC() + { + Write("dsync"); + } + virtual void MFSPR(OP_REG rt, OP_REG sa) + { + Write(wxString::Format("mfspr %s,%s", spu_reg_name[rt], spu_reg_name[sa])); // Are SPR mapped on the GPR or are there 128 additional registers ? + } virtual void RDCH(OP_REG rt, OP_REG ra) { Write(wxString::Format("rdch %s,%s", spu_reg_name[rt], spu_ch_name[ra])); @@ -70,26 +82,142 @@ private: { Write(wxString::Format("sf %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); } + virtual void OR(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("or %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void BG(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("bg %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SFH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("sfh %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void NOR(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("nor %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ABSDB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("absdb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rot %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTM(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotm %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotma %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SHL(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("shl %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("roth %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTHM(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rothm %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTMAH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotmah %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SHLH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("shlh %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("roti %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTMI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotmi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTMAI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotmai %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } virtual void SHLI(OP_REG rt, OP_REG ra, OP_sIMM i7) { Write(wxString::Format("shli %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); } + virtual void ROTHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rothi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTHMI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rothmi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTMAHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotmahi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void SHLHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("shlhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } virtual void A(OP_REG rt, OP_REG ra, OP_REG rb) { Write(wxString::Format("a %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); } - virtual void SPU_AND(OP_REG rt, OP_REG ra, OP_REG rb) + virtual void AND(OP_REG rt, OP_REG ra, OP_REG rb) { Write(wxString::Format("and %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); } - virtual void LQX(OP_REG rt, OP_REG ra, OP_REG rb) + virtual void CG(OP_REG rt, OP_REG ra, OP_REG rb) { - Write(wxString::Format("lqx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + Write(wxString::Format("cg %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void AH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("ah %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void NAND(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("nand %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void AVGB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("avgb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MTSPR(OP_REG rt, OP_REG sa) + { + Write(wxString::Format("mtspr %s,%s", spu_reg_name[rt], spu_reg_name[sa])); } virtual void WRCH(OP_REG ra, OP_REG rt) { Write(wxString::Format("wrch %s,%s", spu_ch_name[ra], spu_reg_name[rt])); } + virtual void BIZ(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("biz %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void BINZ(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("binz %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void BIHZ(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("bihz %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void BIHNZ(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("bihnz %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void STOPD(OP_REG rc, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("bihnz %s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb])); + } virtual void STQX(OP_REG rt, OP_REG ra, OP_REG rb) { Write(wxString::Format("stqx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); @@ -102,40 +230,418 @@ private: { Write(wxString::Format("bisl %s,%s", spu_reg_name[rt], spu_reg_name[ra])); } + virtual void IRET(OP_REG ra) + { + Write(wxString::Format("iret %s", spu_reg_name[ra])); + } + virtual void BISLED(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("bisled %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } virtual void HBR(OP_REG p, OP_REG ro, OP_REG ra) { Write(wxString::Format("hbr 0x%x,%s", DisAsmBranchTarget(ro), spu_reg_name[ra])); } + virtual void GB(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("gb %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void GBH(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("gbh %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void GBB(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("gbb %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FSM(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("fsm %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FSMH(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("fsmh %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FSMB(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("fsmb %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FREST(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("frest %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FRSQEST(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("frsqest %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void LQX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("lqx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTQBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotqbybi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTQMBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotqmbybi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SHLQBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("shlqbybi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CBX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cbx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CHX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("chx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } virtual void CWX(OP_REG rt, OP_REG ra, OP_REG rb) { Write(wxString::Format("cwx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); } + virtual void CDX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cdx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTQBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotqbi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTQMBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotqmbi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SHLQBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("shlqbi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } virtual void ROTQBY(OP_REG rt, OP_REG ra, OP_REG rb) { - Write(wxString::Format("rotqby %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], rb)); + Write(wxString::Format("rotqby %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ROTQMBY(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("rotqmby %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SHLQBY(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("shlqby %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ORX(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("orx %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void CBD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("cbd %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void CHD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("chd %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void CWD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("cwd %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void CDD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("cdd %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTQBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotqbii %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void ROTQMBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotqmbii %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void SHLQBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("shlqbii %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); } virtual void ROTQBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) { Write(wxString::Format("rotqbyi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); } + virtual void ROTQMBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("rotqmbyi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } virtual void SHLQBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) { Write(wxString::Format("shlqbyi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); } - virtual void SPU_NOP(OP_REG rt) + virtual void NOP(OP_REG rt) { Write(wxString::Format("nop %s", spu_reg_name[rt])); } + virtual void CGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void XOR(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("xor %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CGTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cgth %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void EQV(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("eqv %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CGTB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cgtb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SUMB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("sumb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void HGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("hgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CLZ(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("clz %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void XSWD(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("xswd %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void XSHW(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("xshw %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void CNTB(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("cntb %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void XSBH(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("xsbh %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } virtual void CLGT(OP_REG rt, OP_REG ra, OP_REG rb) { Write(wxString::Format("clgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); } + virtual void ANDC(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("andc %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FCGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fcgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFCGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfcgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fa %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FS(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fs %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FM(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fm %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CLGTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("clgth %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ORC(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("orc %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FCMGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fcmgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFCMGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfcmgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfa %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFS(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfs %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFM(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfm %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CLGTB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("clgtb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void HLGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("hlgt %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfma %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFMS(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfms %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFNMS(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfnms %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFNMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfnma %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("ceq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYHHU(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyhhu %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void ADDX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("addx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void SFX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("sfx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CGX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("cgx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void BGX(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("bgx %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYHHA(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyhha %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYHHAU(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyhhau %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FSCRRD(OP_REG rt) + { + Write(wxString::Format("fscrrd %s", spu_reg_name[rt])); + } + virtual void FESD(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("fesd %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FRDS(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("frds %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void FSCRWR(OP_REG rt, OP_REG ra) + { + Write(wxString::Format("fscrwr %s,%s", spu_reg_name[rt], spu_reg_name[ra])); + } + virtual void DFTSV(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + Write(wxString::Format("dftsv %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i7)); + } + virtual void FCEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fceq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFCEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfceq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPY(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpy %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyh %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYHH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyhh %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYS(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpys %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CEQH(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("ceqh %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FCMEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fcmeq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void DFCMEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("dfcmeq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void MPYU(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("mpyu %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void CEQB(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("ceqb %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void FI(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("fi %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + virtual void HEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + Write(wxString::Format("heq %s,%s,%s", spu_reg_name[rt], spu_reg_name[ra], spu_reg_name[rb])); + } + + //0 - 9 + virtual void CFLTS(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + Write(wxString::Format("cflts %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i8)); + } + virtual void CFLTU(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + Write(wxString::Format("cfltu %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i8)); + } + virtual void CSFLT(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + Write(wxString::Format("csflt %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i8)); + } + virtual void CUFLT(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + Write(wxString::Format("cuflt %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i8)); + } //0 - 8 virtual void BRZ(OP_REG rt, OP_sIMM i16) { Write(wxString::Format("brz %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); } + virtual void STQA(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("stqa %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); + } + virtual void BRNZ(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("brnz %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); + } virtual void BRHZ(OP_REG rt, OP_sIMM i16) { Write(wxString::Format("brhz %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); @@ -148,6 +654,18 @@ private: { Write(wxString::Format("stqr %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); } + virtual void BRA(OP_sIMM i16) + { + Write(wxString::Format("bra 0x%x", DisAsmBranchTarget(i16))); + } + virtual void LQA(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("lqa %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); + } + virtual void BRASL(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("brasl %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); + } virtual void BR(OP_sIMM i16) { Write(wxString::Format("br 0x%x", DisAsmBranchTarget(i16))); @@ -160,20 +678,61 @@ private: { Write(wxString::Format("brsl %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); } - virtual void IL(OP_REG rt, OP_sIMM i16) - { - Write(wxString::Format("il %s,%d", spu_reg_name[rt], i16)); - } virtual void LQR(OP_REG rt, OP_sIMM i16) { Write(wxString::Format("lqr %s,0x%x", spu_reg_name[rt], DisAsmBranchTarget(i16))); } + virtual void IL(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("il %s,%d", spu_reg_name[rt], i16)); + } + virtual void ILHU(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("ilhu %s,%d", spu_reg_name[rt], i16)); + } + virtual void ILH(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("ilh %s,%d", spu_reg_name[rt], i16)); + } + virtual void IOHL(OP_REG rt, OP_sIMM i16) + { + Write(wxString::Format("iolh %s,%d", spu_reg_name[rt], i16)); + } + //0 - 7 - virtual void SPU_ORI(OP_REG rt, OP_REG ra, OP_sIMM i10) + virtual void ORI(OP_REG rt, OP_REG ra, OP_sIMM i10) { Write(wxString::Format("ori %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); } + virtual void ORHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("orhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void ORBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("orbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void SFI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("sfi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void SFHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("sfhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void ANDI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("andi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void ANDHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("andhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void ANDBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("andbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } virtual void AI(OP_REG rt, OP_REG ra, OP_sIMM i10) { Write(wxString::Format("ai %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); @@ -190,6 +749,34 @@ private: { Write(wxString::Format("lqd %s,%d(%s)", spu_reg_name[rt], i10, spu_reg_name[ra])); } + virtual void XORI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("xori %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void XORHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("xorhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void XORBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("xorbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void CGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("cgti %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void CGTHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("cgthi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void CGTBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("cgtbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void HGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("hgti %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } virtual void CLGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) { Write(wxString::Format("clgti %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); @@ -198,12 +785,44 @@ private: { Write(wxString::Format("clgthi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); } + virtual void CLGTBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("clgtbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void HLGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("hlgti %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void MPYI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("mpyi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void MPYUI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("mpyui %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } virtual void CEQI(OP_REG rt, OP_REG ra, OP_sIMM i10) { Write(wxString::Format("ceqi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); } + virtual void CEQHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("ceqhi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void CEQBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("ceqbi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } + virtual void HEQI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + Write(wxString::Format("heqi %s,%s,%d", spu_reg_name[rt], spu_reg_name[ra], i10)); + } //0 - 6 + virtual void HBRA(OP_sIMM ro, OP_sIMM i16) + { + Write(wxString::Format("hbra 0x%x,0x%x", DisAsmBranchTarget(ro), DisAsmBranchTarget(i16))); + } virtual void HBRR(OP_sIMM ro, OP_sIMM i16) { Write(wxString::Format("hbrr 0x%x,0x%x", DisAsmBranchTarget(ro), DisAsmBranchTarget(i16))); @@ -222,6 +841,22 @@ private: { Write(wxString::Format("shufb %s,%s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb], spu_reg_name[rt])); } + virtual void MPYA(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + Write(wxString::Format("mpya %s,%s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb], spu_reg_name[rt])); + } + virtual void FNMS(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + Write(wxString::Format("fnms %s,%s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb], spu_reg_name[rt])); + } + virtual void FMA(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + Write(wxString::Format("fma %s,%s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb], spu_reg_name[rt])); + } + virtual void FMS(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + Write(wxString::Format("fms %s,%s,%s,%s", spu_reg_name[rc], spu_reg_name[ra], spu_reg_name[rb], spu_reg_name[rt])); + } virtual void UNK(const s32 code, const s32 opcode, const s32 gcode) { diff --git a/rpcs3/Emu/Cell/SPUInterpreter.h b/rpcs3/Emu/Cell/SPUInterpreter.h index 8061849ff9..9098e80106 100644 --- a/rpcs3/Emu/Cell/SPUInterpreter.h +++ b/rpcs3/Emu/Cell/SPUInterpreter.h @@ -33,6 +33,18 @@ private: virtual void LNOP() { } + virtual void SYNC(OP_uIMM Cbit) + { + // TODO + } + virtual void DSYNC() + { + // TODO + } + virtual void MFSPR(OP_REG rt, OP_REG sa) + { + // TODO + } virtual void RDCH(OP_REG rt, OP_REG ra) { CPU.ReadChannel(CPU.GPR[rt], ra); @@ -49,6 +61,109 @@ private: CPU.GPR[rt]._u32[2] = CPU.GPR[rb]._u32[2] + ~CPU.GPR[ra]._u32[2] + 1; CPU.GPR[rt]._u32[3] = CPU.GPR[rb]._u32[3] + ~CPU.GPR[ra]._u32[3] + 1; } + virtual void OR(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] | CPU.GPR[rb]._u32[0]; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._u32[1] | CPU.GPR[rb]._u32[1]; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._u32[2] | CPU.GPR[rb]._u32[2]; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] | CPU.GPR[rb]._u32[3]; + } + virtual void BG(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] > CPU.GPR[rb]._u32[0] ? 0 : 1; + CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._u32[1] > CPU.GPR[rb]._u32[1] ? 0 : 1; + CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._u32[2] > CPU.GPR[rb]._u32[2] ? 0 : 1; + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] > CPU.GPR[rb]._u32[3] ? 0 : 1; + } + virtual void SFH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[rb]._u16[h] - CPU.GPR[ra]._u16[h]; + } + virtual void NOR(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = ~(CPU.GPR[ra]._u32[0] | CPU.GPR[rb]._u32[0]); + CPU.GPR[rt]._u32[1] = ~(CPU.GPR[ra]._u32[1] | CPU.GPR[rb]._u32[1]); + CPU.GPR[rt]._u32[2] = ~(CPU.GPR[ra]._u32[2] | CPU.GPR[rb]._u32[2]); + CPU.GPR[rt]._u32[3] = ~(CPU.GPR[ra]._u32[3] | CPU.GPR[rb]._u32[3]); + } + virtual void ABSDB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[rb]._u8[b] > CPU.GPR[ra]._u8[b] ? CPU.GPR[rb]._u8[b] - CPU.GPR[ra]._u8[b] : CPU.GPR[ra]._u8[b] - CPU.GPR[rb]._u8[b]; + } + virtual void ROT(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << (CPU.GPR[rb]._u32[0] & 0x1f)) | (CPU.GPR[ra]._u32[0] >> (32 - (CPU.GPR[rb]._u32[0] & 0x1f))); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << (CPU.GPR[rb]._u32[1] & 0x1f)) | (CPU.GPR[ra]._u32[1] >> (32 - (CPU.GPR[rb]._u32[1] & 0x1f))); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << (CPU.GPR[rb]._u32[2] & 0x1f)) | (CPU.GPR[ra]._u32[2] >> (32 - (CPU.GPR[rb]._u32[2] & 0x1f))); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << (CPU.GPR[rb]._u32[3] & 0x1f)) | (CPU.GPR[ra]._u32[3] >> (32 - (CPU.GPR[rb]._u32[3] & 0x1f))); + } + virtual void ROTM(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = ((0 - CPU.GPR[rb]._u32[0]) % 64) < 32 ? CPU.GPR[ra]._u32[0] >> ((0 - CPU.GPR[rb]._u32[0]) % 64) : 0; + CPU.GPR[rt]._u32[1] = ((0 - CPU.GPR[rb]._u32[1]) % 64) < 32 ? CPU.GPR[ra]._u32[1] >> ((0 - CPU.GPR[rb]._u32[1]) % 64) : 0; + CPU.GPR[rt]._u32[2] = ((0 - CPU.GPR[rb]._u32[2]) % 64) < 32 ? CPU.GPR[ra]._u32[2] >> ((0 - CPU.GPR[rb]._u32[2]) % 64) : 0; + CPU.GPR[rt]._u32[3] = ((0 - CPU.GPR[rb]._u32[3]) % 64) < 32 ? CPU.GPR[ra]._u32[3] >> ((0 - CPU.GPR[rb]._u32[3]) % 64) : 0; + } + virtual void ROTMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._i32[0] = ((0 - CPU.GPR[rb]._i32[0]) % 64) < 32 ? CPU.GPR[ra]._i32[0] >> ((0 - CPU.GPR[rb]._i32[0]) % 64) : CPU.GPR[ra]._i32[0] >> 31; + CPU.GPR[rt]._i32[1] = ((0 - CPU.GPR[rb]._i32[1]) % 64) < 32 ? CPU.GPR[ra]._i32[1] >> ((0 - CPU.GPR[rb]._i32[1]) % 64) : CPU.GPR[ra]._i32[1] >> 31; + CPU.GPR[rt]._i32[2] = ((0 - CPU.GPR[rb]._i32[2]) % 64) < 32 ? CPU.GPR[ra]._i32[2] >> ((0 - CPU.GPR[rb]._i32[2]) % 64) : CPU.GPR[ra]._i32[2] >> 31; + CPU.GPR[rt]._i32[3] = ((0 - CPU.GPR[rb]._i32[3]) % 64) < 32 ? CPU.GPR[ra]._i32[3] >> ((0 - CPU.GPR[rb]._i32[3]) % 64) : CPU.GPR[ra]._i32[3] >> 31; + } + virtual void SHL(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = (CPU.GPR[rb]._u32[0] & 0x3f) > 31 ? 0 : CPU.GPR[ra]._u32[0] << (CPU.GPR[rb]._u32[0] & 0x3f); + CPU.GPR[rt]._u32[1] = (CPU.GPR[rb]._u32[1] & 0x3f) > 31 ? 0 : CPU.GPR[ra]._u32[1] << (CPU.GPR[rb]._u32[1] & 0x3f); + CPU.GPR[rt]._u32[2] = (CPU.GPR[rb]._u32[2] & 0x3f) > 31 ? 0 : CPU.GPR[ra]._u32[2] << (CPU.GPR[rb]._u32[2] & 0x3f); + CPU.GPR[rt]._u32[3] = (CPU.GPR[rb]._u32[3] & 0x3f) > 31 ? 0 : CPU.GPR[ra]._u32[3] << (CPU.GPR[rb]._u32[3] & 0x3f); + } + virtual void ROTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u16[h] << (CPU.GPR[rb]._u16[h] & 0xf)) | (CPU.GPR[ra]._u16[h] >> (16 - (CPU.GPR[rb]._u32[h] & 0xf))); + } + virtual void ROTHM(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = ((0 - CPU.GPR[rb]._u16[h]) % 32) < 16 ? CPU.GPR[ra]._u16[h] >> ((0 - CPU.GPR[rb]._u16[h]) % 32) : 0; + } + virtual void ROTMAH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._i16[h] = ((0 - CPU.GPR[rb]._i16[h]) % 32) < 16 ? CPU.GPR[ra]._i16[h] >> ((0 - CPU.GPR[rb]._i16[h]) % 32) : CPU.GPR[ra]._i16[h] >> 15; + } + virtual void SHLH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = (CPU.GPR[rb]._u16[h] & 0x1f) > 15 ? 0 : CPU.GPR[ra]._u16[h] << (CPU.GPR[rb]._u16[h] & 0x3f); + } + virtual void ROTI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = i7 & 0x1f; + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nRot) | (CPU.GPR[ra]._u32[0] >> (32 - nRot)); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nRot) | (CPU.GPR[ra]._u32[1] >> (32 - nRot)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nRot) | (CPU.GPR[ra]._u32[2] >> (32 - nRot)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << nRot) | (CPU.GPR[ra]._u32[3] >> (32 - nRot)); + } + virtual void ROTMI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = (0 - i7) % 64; + CPU.GPR[rt]._u32[0] = nRot < 32 ? CPU.GPR[ra]._u32[0] >> nRot : 0; + CPU.GPR[rt]._u32[1] = nRot < 32 ? CPU.GPR[ra]._u32[1] >> nRot : 0; + CPU.GPR[rt]._u32[2] = nRot < 32 ? CPU.GPR[ra]._u32[2] >> nRot : 0; + CPU.GPR[rt]._u32[3] = nRot < 32 ? CPU.GPR[ra]._u32[3] >> nRot : 0; + } + virtual void ROTMAI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = (0 - i7) % 64; + CPU.GPR[rt]._i32[0] = nRot < 32 ? CPU.GPR[ra]._i32[0] >> nRot : CPU.GPR[ra]._i32[0] >> 31; + CPU.GPR[rt]._i32[1] = nRot < 32 ? CPU.GPR[ra]._i32[1] >> nRot : CPU.GPR[ra]._i32[1] >> 31; + CPU.GPR[rt]._i32[2] = nRot < 32 ? CPU.GPR[ra]._i32[2] >> nRot : CPU.GPR[ra]._i32[2] >> 31; + CPU.GPR[rt]._i32[3] = nRot < 32 ? CPU.GPR[ra]._i32[3] >> nRot : CPU.GPR[ra]._i32[3] >> 31; + } virtual void SHLI(OP_REG rt, OP_REG ra, OP_sIMM i7) { const u32 s = i7 & 0x3f; @@ -66,6 +181,34 @@ private: CPU.GPR[rt]._u32[j] = r; } } + virtual void ROTHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = i7 & 0xf; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u16[h] << nRot) | (CPU.GPR[ra]._u16[h] >> (16 - nRot)); + } + virtual void ROTHMI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = (0 - i7) % 32; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = nRot < 16 ? CPU.GPR[ra]._u16[h] >> nRot : 0; + } + virtual void ROTMAHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = (0 - i7) % 32; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._i16[h] = nRot < 16 ? CPU.GPR[ra]._i16[h] >> nRot : CPU.GPR[ra]._i16[h] >> 15; + } + virtual void SHLHI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nRot = i7 & 0x1f; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[0] = nRot > 15 ? 0 : CPU.GPR[ra]._u16[0] << nRot; + } virtual void A(OP_REG rt, OP_REG ra, OP_REG rb) { CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]; @@ -73,22 +216,69 @@ private: CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._u32[2] + CPU.GPR[rb]._u32[2]; CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]; } - virtual void SPU_AND(OP_REG rt, OP_REG ra, OP_REG rb) + virtual void AND(OP_REG rt, OP_REG ra, OP_REG rb) { CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] & CPU.GPR[rb]._u32[0]; CPU.GPR[rt]._u32[1] = CPU.GPR[ra]._u32[1] & CPU.GPR[rb]._u32[1]; CPU.GPR[rt]._u32[2] = CPU.GPR[ra]._u32[2] & CPU.GPR[rb]._u32[2]; CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] & CPU.GPR[rb]._u32[3]; } - virtual void LQX(OP_REG rt, OP_REG ra, OP_REG rb) + virtual void CG(OP_REG rt, OP_REG ra, OP_REG rb) { - CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]; - CPU.GPR[rt]._u128 = CPU.ReadLSA128(); + CPU.GPR[rt]._u32[0] = ((CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]) < CPU.GPR[ra]._u32[0]) ? 1 : 0; + CPU.GPR[rt]._u32[1] = ((CPU.GPR[ra]._u32[1] + CPU.GPR[rb]._u32[1]) < CPU.GPR[ra]._u32[1]) ? 1 : 0; + CPU.GPR[rt]._u32[2] = ((CPU.GPR[ra]._u32[2] + CPU.GPR[rb]._u32[2]) < CPU.GPR[ra]._u32[2]) ? 1 : 0; + CPU.GPR[rt]._u32[3] = ((CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) < CPU.GPR[ra]._u32[3]) ? 1 : 0; + } + virtual void AH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] + CPU.GPR[rb]._u16[h]; + } + virtual void NAND(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.GPR[rt]._u32[0] = ~(CPU.GPR[ra]._u32[0] & CPU.GPR[rb]._u32[0]); + CPU.GPR[rt]._u32[1] = ~(CPU.GPR[ra]._u32[1] & CPU.GPR[rb]._u32[1]); + CPU.GPR[rt]._u32[2] = ~(CPU.GPR[ra]._u32[2] & CPU.GPR[rb]._u32[2]); + CPU.GPR[rt]._u32[3] = ~(CPU.GPR[ra]._u32[3] & CPU.GPR[rb]._u32[3]); + } + virtual void AVGB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = (CPU.GPR[ra]._u8[b] + CPU.GPR[rb]._u8[b] + 1) >> 1; + } + virtual void MTSPR(OP_REG rt, OP_REG sa) + { + // TODO } virtual void WRCH(OP_REG ra, OP_REG rt) { CPU.WriteChannel(ra, CPU.GPR[rt]); } + virtual void BIZ(OP_REG rt, OP_REG ra) + { + if(CPU.GPR[rt]._u32[0] == 0) + CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); + } + virtual void BINZ(OP_REG rt, OP_REG ra) + { + if(CPU.GPR[rt]._u32[0] != 0) + CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); + } + virtual void BIHZ(OP_REG rt, OP_REG ra) + { + if(CPU.GPR[rt]._u16[0] == 0) + CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); + } + virtual void BIHNZ(OP_REG rt, OP_REG ra) + { + if(CPU.GPR[rt]._u16[0] != 0) + CPU.SetBranch(CPU.GPR[ra]._u32[0] & 0xfffffffc); + } + virtual void STOPD(OP_REG rc, OP_REG ra, OP_REG rb) + { + Emu.Pause(); + } virtual void STQX(OP_REG rt, OP_REG ra, OP_REG rb) { CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]; @@ -104,16 +294,154 @@ private: CPU.GPR[rt].Reset(); CPU.GPR[rt]._u32[0] = CPU.PC + 4; } + virtual void IRET(OP_REG ra) + { + // TODO + // SetBranch(SRR0); + } + virtual void BISLED(OP_REG rt, OP_REG ra) + { + // TODO + } virtual void HBR(OP_REG p, OP_REG ro, OP_REG ra) { CPU.SetBranch(CPU.GPR[ra]._u32[0]); } + virtual void GB(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt].Reset(); + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] & 1) | + ((CPU.GPR[ra]._u32[1] & 1) << 1) | + ((CPU.GPR[ra]._u32[2] & 1) << 2) | + ((CPU.GPR[ra]._u32[3] & 1) << 3); + } + virtual void GBH(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt].Reset(); + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u32[0] |= (CPU.GPR[ra]._u16[h] & 1) << h; + } + virtual void GBB(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt].Reset(); + + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u32[0] |= (CPU.GPR[ra]._u8[b] & 1) << b; + } + virtual void FSM(OP_REG rt, OP_REG ra) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[0] & (8 >> w)) ? ~0 : 0; + } + virtual void FSMH(OP_REG rt, OP_REG ra) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = (CPU.GPR[ra]._u32[0] & (128 >> h)) ? ~0 : 0; + } + virtual void FSMB(OP_REG rt, OP_REG ra) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = (CPU.GPR[ra]._u32[0] & (32768 >> b)) ? ~0 : 0; + } + virtual void FREST(OP_REG rt, OP_REG ra) + { + // TODO + } + virtual void FRSQEST(OP_REG rt, OP_REG ra) + { + // TODO + } + virtual void LQX(OP_REG rt, OP_REG ra, OP_REG rb) + { + CPU.LSA = CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]; + CPU.GPR[rt]._u128 = CPU.ReadLSA128(); + } + virtual void ROTQBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = (CPU.GPR[rb]._u32[0] >> 3) & 0xf; + + for (int b = 0; b < 8; b++) + CPU.GPR[rt]._u8[b] = nShift == 0 ? CPU.GPR[ra]._u8[b] : (CPU.GPR[ra]._u8[b] << nShift) | (CPU.GPR[ra]._u8[b] >> (16 - nShift)); + } + virtual void ROTQMBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = ((0 - CPU.GPR[rb]._u32[0]) >> 3) & 0x1f; + + for (int b = 0; b < 16; b++) + { + if (b >= nShift) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; + else + CPU.GPR[rt]._u8[b] = 0; + } + } + virtual void SHLQBYBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = (CPU.GPR[rb]._u32[0] >> 3) & 0x1f; + + for (int b = 0; b < 16; b++) + { + if ((b + nShift) < 16) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + nShift]; + else + CPU.GPR[rt]._u8[b] = 0; + } + } + virtual void CBX(OP_REG rt, OP_REG ra, OP_REG rb) + { + int n = (CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0xf; + + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = b == n ? 3 : b | 0x10; + } + virtual void CHX(OP_REG rt, OP_REG ra, OP_REG rb) + { + int n = ((CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0xf) >> 1; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = h == n ? 0x0203 : (h * 2 * 0x0101 + 0x1011); + } virtual void CWX(OP_REG rt, OP_REG ra, OP_REG rb) { const u32 t = ((CPU.GPR[ra]._u32[0] + CPU.GPR[rb]._u32[0]) & 0xc) / 4; - for(u32 i=0; i<16; ++i) CPU.GPR[rt]._i8[i] = 0x1f - i; + for(u32 i=0; i<16; ++i) CPU.GPR[rt]._i8[i] = 0x10 + i; CPU.GPR[rt]._u32[t] = 0x10203; } + virtual void CDX(OP_REG rt, OP_REG ra, OP_REG rb) + { + int n = ((CPU.GPR[rb]._u32[0] + CPU.GPR[ra]._u32[0]) & 0x8) >> 2; + + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = (w == n) ? 0x00010203 : (w == (n + 1)) ? 0x04050607 : (0x01010101 * (w * 4) + 0x10111213); + } + virtual void ROTQBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + int nShift = CPU.GPR[rb]._u32[0] & 0x7; + + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << nShift) | (CPU.GPR[ra]._u32[0] >> (32 - nShift)); + } + virtual void ROTQMBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + int nShift = (0 - CPU.GPR[rb]._u32[0]) % 8; + + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] >> nShift; + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> nShift) | (CPU.GPR[ra]._u32[0] << (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> nShift) | (CPU.GPR[ra]._u32[1] << (32 - nShift)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> nShift) | (CPU.GPR[ra]._u32[2] << (32 - nShift)); + } + virtual void SHLQBI(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = CPU.GPR[rb]._u32[0] & 0x7; + + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] << nShift; + } virtual void ROTQBY(OP_REG rt, OP_REG ra, OP_REG rb) { const s32 s = CPU.GPR[rb]._u8[0] & 0xf; @@ -130,6 +458,94 @@ private: } } } + virtual void ROTQMBY(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = (0 - CPU.GPR[rb]._u32[0]) % 32; + + for (int b = 0; b < 16; b++) + if (b >= nShift) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; + else + CPU.GPR[rt]._u8[b] = 0; + } + virtual void SHLQBY(OP_REG rt, OP_REG ra, OP_REG rb) + { + const int nShift = CPU.GPR[rb]._u32[0] & 0x1f; + + for (int b = 0; b < 16; b++) + if (b + nShift < 16) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + nShift]; + else + CPU.GPR[rt]._u8[b] = 0; + } + virtual void ORX(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt].Reset(); + + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] | CPU.GPR[ra]._u32[1] | CPU.GPR[ra]._u32[2] | CPU.GPR[ra]._u32[3]; + } + virtual void CBD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int n = (CPU.GPR[ra]._u32[0] + i7) & 0xf; + + for (int b = 0; b < 16; b++) + if (b == n) + CPU.GPR[rt]._u8[b] = 0x3; + else + CPU.GPR[rt]._u8[b] = b | 0x10; + } + virtual void CHD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + int n = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 1; + + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = h == n ? 0x0203 : (h * 2 * 0x0101 + 0x1011); + } + virtual void CWD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int t = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 2; + + for (int i=0; i<16; ++i) + CPU.GPR[rt]._u8[i] = 0x10 + i; + + CPU.GPR[rt]._u32[t] = 0x10203; + } + virtual void CDD(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int t = ((CPU.GPR[ra]._u32[0] + i7) & 0xf) >> 3; + + for (int i=0; i<16; ++i) + CPU.GPR[rt]._u8[i] = 0x10 + i; + + CPU.GPR[rt]._u64[t] = (u64)0x0001020304050607; + } + virtual void ROTQBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + int nShift = i7 & 0x7; + + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] << nShift) | (CPU.GPR[ra]._u32[0] >> (32 - nShift)); + } + virtual void ROTQMBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + int nShift = (0 - i7) % 8; + + CPU.GPR[rt]._u32[0] = CPU.GPR[ra]._u32[0] >> nShift; + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] >> nShift) | (CPU.GPR[ra]._u32[0] << (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] >> nShift) | (CPU.GPR[ra]._u32[1] << (32 - nShift)); + CPU.GPR[rt]._u32[3] = (CPU.GPR[ra]._u32[3] >> nShift) | (CPU.GPR[ra]._u32[2] << (32 - nShift)); + } + virtual void SHLQBII(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nShift = i7 & 0x7; + + CPU.GPR[rt]._u32[0] = (CPU.GPR[ra]._u32[0] << nShift) | (CPU.GPR[ra]._u32[1] >> (32 - nShift)); + CPU.GPR[rt]._u32[1] = (CPU.GPR[ra]._u32[1] << nShift) | (CPU.GPR[ra]._u32[2] >> (32 - nShift)); + CPU.GPR[rt]._u32[2] = (CPU.GPR[ra]._u32[2] << nShift) | (CPU.GPR[ra]._u32[3] >> (32 - nShift)); + CPU.GPR[rt]._u32[3] = CPU.GPR[ra]._u32[3] << nShift; + } virtual void ROTQBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) { const u16 s = i7 & 0xf; @@ -146,6 +562,16 @@ private: } } } + virtual void ROTQMBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + const int nShift = (0 - i7) % 32; + + for (int b = 0; b < 16; b++) + if (b >= nShift) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b - nShift]; + else + CPU.GPR[rt]._u8[b] = 0; + } virtual void SHLQBYI(OP_REG rt, OP_REG ra, OP_sIMM i7) { const u16 s = i7 & 0x1f; @@ -157,9 +583,82 @@ private: CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b + s]; } } - virtual void SPU_NOP(OP_REG rt) + virtual void NOP(OP_REG rt) { } + virtual void CGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] > CPU.GPR[rb]._i32[w] ? 0xffffffff : 0; + } + virtual void XOR(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] ^ CPU.GPR[rb]._u32[w]; + } + virtual void CGTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] > CPU.GPR[rb]._i16[h] ? 0xffff : 0; + } + virtual void EQV(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[w] & CPU.GPR[rb]._u32[w]) | ~(CPU.GPR[ra]._u32[w] | CPU.GPR[rb]._u32[w]); + } + virtual void CGTB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._i8[b] > CPU.GPR[rb]._i8[b] ? 0xff : 0; + } + virtual void SUMB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + { + CPU.GPR[rt]._u16[w*2] = CPU.GPR[ra]._u8[w*4] + CPU.GPR[ra]._u8[w*4 + 1] + CPU.GPR[ra]._u8[w*4 + 2] + CPU.GPR[ra]._u8[w*4 + 3]; + CPU.GPR[rt]._u16[w*2 + 1] = CPU.GPR[rb]._u8[w*4] + CPU.GPR[rb]._u8[w*4 + 1] + CPU.GPR[rb]._u8[w*4 + 2] + CPU.GPR[rb]._u8[w*4 + 3]; + } + } + virtual void HGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void CLZ(OP_REG rt, OP_REG ra) + { + for (int w = 0; w < 4; w++) + { + int nPos; + + for (nPos = 0; nPos < 32; nPos++) + if (CPU.GPR[ra]._u32[w] & (1 << (31 - nPos))) + break; + + CPU.GPR[rt]._u32[w] = nPos; + } + } + virtual void XSWD(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt]._i64[0] = (s64)CPU.GPR[ra]._i32[1]; + CPU.GPR[rt]._i64[1] = (s64)CPU.GPR[ra]._i32[3]; + } + virtual void XSHW(OP_REG rt, OP_REG ra) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = (s32)CPU.GPR[ra]._i16[w*2 + 1]; + } + virtual void CNTB(OP_REG rt, OP_REG ra) + { + CPU.GPR[rt].Reset(); + + for (int b = 0; b < 16; b++) + for (int i = 0; i < 8; i++) + CPU.GPR[rt]._u8[b] += (CPU.GPR[ra]._u8[b] & (1 << i)) ? 1 : 0; + } + virtual void XSBH(OP_REG rt, OP_REG ra) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._i16[h] = (s16)CPU.GPR[ra]._i8[h*2 + 1]; + } virtual void CLGT(OP_REG rt, OP_REG ra, OP_REG rb) { for(u32 i = 0; i < 4; ++i) @@ -167,12 +666,248 @@ private: CPU.GPR[rt]._u32[i] = (CPU.GPR[ra]._u32[i] > CPU.GPR[rb]._u32[i]) ? 0xffffffff : 0x00000000; } } + virtual void ANDC(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] & (~CPU.GPR[rb]._u32[w]); + } + virtual void FCGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFCGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void FA(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void FS(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void FM(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void CLGTH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] > CPU.GPR[rb]._u16[h] ? 0xffff : 0; + } + virtual void ORC(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] | (~CPU.GPR[rb]._u32[w]); + } + virtual void FCMGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFCMGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFA(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFS(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFM(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void CLGTB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] > CPU.GPR[rb]._u8[b] ? 0xff : 0; + } + virtual void HLGT(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFMS(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFNMS(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFNMA(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void CEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] == CPU.GPR[rb]._i32[w] ? 0xffffffff : 0; + } + virtual void MPYHHU(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; + } + virtual void ADDX(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] + CPU.GPR[rb]._u32[w] + (CPU.GPR[rt]._u32[w] & 1); + } + virtual void SFX(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[rb]._u32[w] - CPU.GPR[ra]._u32[w] - (1 - (CPU.GPR[rt]._u32[w] & 1)); + } + virtual void CGX(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = (CPU.GPR[ra]._u32[w] + CPU.GPR[rb]._u32[w] + (CPU.GPR[rt]._u32[w] & 1)) < CPU.GPR[ra]._u32[w] ? 1 : 0; + } + virtual void BGX(OP_REG rt, OP_REG ra, OP_REG rb) + { + s64 nResult; + + for (int w = 0; w < 4; w++) + { + nResult = (u64)CPU.GPR[rb]._u32[w] - (u64)CPU.GPR[ra]._u32[w] - (1 - (CPU.GPR[rt]._u32[w] & 1)); + CPU.GPR[rt]._u32[w] = nResult < 0 ? 0 : 1; + } + } + virtual void MPYHHA(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] += CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; + } + virtual void MPYHHAU(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] += CPU.GPR[ra]._u16[w*2] * CPU.GPR[rb]._u16[w*2]; + } + virtual void FSCRRD(OP_REG rt) + { + // TODO + } + virtual void FESD(OP_REG rt, OP_REG ra) + { + // TODO + } + virtual void FRDS(OP_REG rt, OP_REG ra) + { + // TODO + } + virtual void FSCRWR(OP_REG rt, OP_REG ra) + { + // TODO + } + virtual void DFTSV(OP_REG rt, OP_REG ra, OP_sIMM i7) + { + // TODO + } + virtual void FCEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFCEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void MPY(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1]; + } + virtual void MPYH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = ((CPU.GPR[ra]._i32[w] >> 16) * (CPU.GPR[rb]._i32[w] & 0xffff)) << 16; + } + virtual void MPYHH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2] * CPU.GPR[rb]._i16[w*2]; + } + virtual void MPYS(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = (CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1]) >> 16; + } + virtual void CEQH(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] == CPU.GPR[rb]._u16[h] ? 0xffff : 0; + } + virtual void FCMEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void DFCMEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void MPYU(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u16[w*2 + 1] * CPU.GPR[rb]._u16[w*2 + 1]; + } + virtual void CEQB(OP_REG rt, OP_REG ra, OP_REG rb) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] == CPU.GPR[rb]._u8[b] ? 0xff : 0; + } + virtual void FI(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + virtual void HEQ(OP_REG rt, OP_REG ra, OP_REG rb) + { + // TODO + } + + + + //0 - 9 + virtual void CFLTS(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + // TODO + } + virtual void CFLTU(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + // TODO + } + virtual void CSFLT(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + // TODO + } + virtual void CUFLT(OP_REG rt, OP_REG ra, OP_sIMM i8) + { + // TODO + } + + //0 - 8 virtual void BRZ(OP_REG rt, OP_sIMM i16) { if(!CPU.GPR[rt]._u32[0]) CPU.SetBranch(branchTarget(CPU.PC, i16)); } + virtual void STQA(OP_REG rt, OP_sIMM i16) + { + CPU.LSA = i16 << 2; + CPU.WriteLSA128(CPU.GPR[rt]._u128); + } + virtual void BRNZ(OP_REG rt, OP_sIMM i16) + { + if(CPU.GPR[rt]._u32[0] != 0) + CPU.SetBranch(branchTarget(CPU.PC, i16)); + } virtual void BRHZ(OP_REG rt, OP_sIMM i16) { if(!CPU.GPR[rt]._u16[0]) CPU.SetBranch(branchTarget(CPU.PC, i16)); @@ -186,6 +921,27 @@ private: CPU.LSA = branchTarget(CPU.PC, i16); CPU.WriteLSA128(CPU.GPR[rt]._u128); } + virtual void BRA(OP_sIMM i16) + { + CPU.SetBranch(i16 << 2); + } + virtual void LQA(OP_REG rt, OP_sIMM i16) + { + CPU.LSA = i16 << 2; + if(!Memory.IsGoodAddr(CPU.LSA)) + { + ConLog.Warning("LQA: Bad addr: 0x%x", CPU.LSA); + return; + } + + CPU.GPR[rt]._u128 = CPU.ReadLSA128(); + } + virtual void BRASL(OP_REG rt, OP_sIMM i16) + { + CPU.GPR[rt].Reset(); + CPU.GPR[rt]._u32[0] = CPU.PC + 4; + CPU.SetBranch(i16 << 2); + } virtual void BR(OP_sIMM i16) { CPU.SetBranch(branchTarget(CPU.PC, i16)); @@ -212,13 +968,6 @@ private: CPU.GPR[rt]._u32[0] = CPU.PC + 4; CPU.SetBranch(branchTarget(CPU.PC, i16)); } - virtual void IL(OP_REG rt, OP_sIMM i16) - { - CPU.GPR[rt]._u32[0] = i16; - CPU.GPR[rt]._u32[1] = i16; - CPU.GPR[rt]._u32[2] = i16; - CPU.GPR[rt]._u32[3] = i16; - } virtual void LQR(OP_REG rt, OP_sIMM i16) { CPU.LSA = branchTarget(CPU.PC, i16); @@ -230,15 +979,73 @@ private: CPU.GPR[rt]._u128 = CPU.ReadLSA128(); } + virtual void IL(OP_REG rt, OP_sIMM i16) + { + CPU.GPR[rt]._u32[0] = i16; + CPU.GPR[rt]._u32[1] = i16; + CPU.GPR[rt]._u32[2] = i16; + CPU.GPR[rt]._u32[3] = i16; + } + virtual void ILHU(OP_REG rt, OP_sIMM i16) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u16[w*2] = i16; + } + virtual void ILH(OP_REG rt, OP_sIMM i16) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = i16; + } + virtual void IOHL(OP_REG rt, OP_sIMM i16) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] |= i16; + } + //0 - 7 - virtual void SPU_ORI(OP_REG rt, OP_REG ra, OP_sIMM i10) + virtual void ORI(OP_REG rt, OP_REG ra, OP_sIMM i10) { for(u32 i = 0; i < 4; ++i) { CPU.GPR[rt]._u32[i] = CPU.GPR[ra]._u32[i] | i10; } } + virtual void ORHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] | i10; + } + virtual void ORBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] | (i10 & 0xff); + } + virtual void SFI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = i10 - CPU.GPR[ra]._i32[w]; + } + virtual void SFHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._i16[h] = i10 - CPU.GPR[ra]._i16[h]; + } + virtual void ANDI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] & i10; + } + virtual void ANDHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] & i10; + } + virtual void ANDBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] & (i10 & 0xff); + } virtual void AI(OP_REG rt, OP_REG ra, OP_sIMM i10) { for(u32 i = 0; i < 4; ++i) @@ -263,6 +1070,40 @@ private: CPU.LSA = branchTarget(0, i10 + CPU.GPR[ra]._u32[0]); CPU.GPR[rt]._u128 = CPU.ReadLSA128(); } + virtual void XORI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._u32[w] ^ i10; + } + virtual void XORHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._u16[h] ^ i10; + } + virtual void XORBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] ^ (i10 & 0xff); + } + virtual void CGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[ra]._i32[w] > i10 ? 0xffffffff : 0; + } + virtual void CGTHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] > i10 ? 0xffff : 0; + } + virtual void CGTBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._i8[b] > (s8)(i10 & 0xff) ? 0xff : 0; + } + virtual void HGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + // TODO + } virtual void CLGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) { for(u32 i = 0; i < 4; ++i) @@ -277,6 +1118,25 @@ private: CPU.GPR[rt]._u16[i] = (CPU.GPR[rt]._u16[i] > (u16)i10) ? 0xffff : 0x0000; } } + virtual void CLGTBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] > (u8)(i10 & 0xff) ? 0xff : 0; + } + virtual void HLGTI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + // TODO + } + virtual void MPYI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = CPU.GPR[rt]._i16[w*2 + 1] * i10; + } + virtual void MPYUI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._u32[w] = CPU.GPR[rt]._u16[w*2 + 1] * (u16)(i10 & 0xffff); + } virtual void CEQI(OP_REG rt, OP_REG ra, OP_sIMM i10) { for(u32 i = 0; i < 4; ++i) @@ -284,8 +1144,27 @@ private: CPU.GPR[rt]._u32[i] = (CPU.GPR[rt]._u32[i] == (u32)i10) ? 0xffffffff : 0x00000000; } } + virtual void CEQHI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int h = 0; h < 8; h++) + CPU.GPR[rt]._u16[h] = CPU.GPR[ra]._i16[h] == (s16)i10 ? 0xffff : 0; + } + virtual void CEQBI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + for (int b = 0; b < 16; b++) + CPU.GPR[rt]._u8[b] = CPU.GPR[ra]._u8[b] == (u8)(i10 & 0xff) ? 0xff : 0; + } + virtual void HEQI(OP_REG rt, OP_REG ra, OP_sIMM i10) + { + // TODO + } + //0 - 6 + virtual void HBRA(OP_sIMM ro, OP_sIMM i16) + { + // TODO + } virtual void HBRR(OP_sIMM ro, OP_sIMM i16) { //CHECK ME @@ -320,6 +1199,23 @@ private: { ConLog.Warning("SHUFB"); } + virtual void MPYA(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + for (int w = 0; w < 4; w++) + CPU.GPR[rt]._i32[w] = CPU.GPR[ra]._i16[w*2 + 1] * CPU.GPR[rb]._i16[w*2 + 1] + CPU.GPR[rc]._i32[w]; + } + virtual void FNMS(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + // TODO + } + virtual void FMA(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + // TODO + } + virtual void FMS(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt) + { + // TODO + } virtual void UNK(const s32 code, const s32 opcode, const s32 gcode) { diff --git a/rpcs3/Emu/Cell/SPUOpcodes.h b/rpcs3/Emu/Cell/SPUOpcodes.h index c46098b965..4855c53f36 100644 --- a/rpcs3/Emu/Cell/SPUOpcodes.h +++ b/rpcs3/Emu/Cell/SPUOpcodes.h @@ -8,65 +8,230 @@ #define ADD_NULL_OPCODE(name) virtual void(##name##)()=0 #define END_OPCODES_GROUP(x) /*x*/ -enum SPU_0_10_Opcodes +namespace SPU_opcodes { - STOP = 0x0, - LNOP = 0x1, - RDCH = 0xd, - RCHCNT = 0xf, - SF = 0x40, - SHLI = 0x7b, - A = 0xc0, - SPU_AND = 0xc1, - LQX = 0x1c4, - WRCH = 0x10d, - STQX = 0x144, - BI = 0x1a8, - BISL = 0x1a9, - HBR = 0x1ac, - CWX = 0x1d6, - ROTQBY = 0x1dc, - ROTQBYI = 0x1fc, - SHLQBYI = 0x1ff, - SPU_NOP = 0x201, - CLGT = 0x2c0, -}; + enum SPU_0_10_Opcodes + { + STOP = 0x0, + LNOP = 0x1, + SYNC = 0x2, + DSYNC = 0x3, + MFSPR = 0xc, + RDCH = 0xd, + RCHCNT = 0xf, + SF = 0x40, + OR = 0x41, + BG = 0x42, + SFH = 0x48, + NOR = 0x49, + ABSDB = 0x53, + ROT = 0x58, + ROTM = 0x59, + ROTMA = 0x5a, + SHL = 0x5b, + ROTH = 0x5c, + ROTHM = 0x5d, + ROTMAH = 0x5e, + SHLH = 0x5f, + ROTI = 0x78, + ROTMI = 0x79, + ROTMAI = 0x7a, + SHLI = 0x7b, + ROTHI = 0x7c, + ROTHMI = 0x7d, + ROTMAHI = 0x7e, + SHLHI = 0x7f, + A = 0xc0, + AND = 0xc1, + CG = 0xc2, + AH = 0xc8, + NAND = 0xc9, + AVGB = 0xd3, + MTSPR = 0x10c, + WRCH = 0x10d, + BIZ = 0x128, + BINZ = 0x129, + BIHZ = 0x12a, + BIHNZ = 0x12b, + STOPD = 0x140, + STQX = 0x144, + BI = 0x1a8, + BISL = 0x1a9, + IRET = 0x1aa, + BISLED = 0x1ab, + HBR = 0x1ac, + GB = 0x1b0, + GBH = 0x1b1, + GBB = 0x1b2, + FSM = 0x1b4, + FSMH = 0x1b5, + FSMB = 0x1b6, + FREST = 0x1b8, + FRSQEST = 0x1b9, + LQX = 0x1c4, + ROTQBYBI = 0x1cc, + ROTQMBYBI = 0x1cd, + SHLQBYBI = 0x1cf, + CBX = 0x1d4, + CHX = 0x1d5, + CWX = 0x1d6, + CDX = 0x1d7, + ROTQBI = 0x1d8, + ROTQMBI = 0x1d9, + SHLQBI = 0x1db, + ROTQBY = 0x1dc, + ROTQMBY = 0x1dd, + SHLQBY = 0x1df, + ORX = 0x1f0, + CBD = 0x1f4, + CHD = 0x1f5, + CWD = 0x1f6, + CDD = 0x1f7, + ROTQBII = 0x1f8, + ROTQMBII = 0x1f9, + SHLQBII = 0x1fb, + ROTQBYI = 0x1fc, + ROTQMBYI = 0x1fd, + SHLQBYI = 0x1ff, + NOP = 0x201, + CGT = 0x240, + XOR = 0x241, + CGTH = 0x248, + EQV = 0x249, + CGTB = 0x250, + SUMB = 0x253, + HGT = 0x258, + CLZ = 0x2a5, + XSWD = 0x2a6, + XSHW = 0x2ae, + CNTB = 0x2b4, + XSBH = 0x2b6, + CLGT = 0x2c0, + ANDC = 0x2c1, + FCGT = 0x2c2, + DFCGT = 0x2c3, + FA = 0x2c4, + FS = 0x2c5, + FM = 0x2c6, + CLGTH = 0x2c8, + ORC = 0x2c9, + FCMGT = 0x2ca, + DFCMGT = 0x2cb, + DFA = 0x2cc, + DFS = 0x2cd, + DFM = 0x2ce, + CLGTB = 0x2d0, + HLGT = 0x2d8, + DFMA = 0x35c, + DFMS = 0x35d, + DFNMS = 0x35e, + DFNMA = 0x35f, + CEQ = 0x3c0, + MPYHHU = 0x3ce, + ADDX = 0x340, + SFX = 0x341, + CGX = 0x342, + BGX = 0x343, + MPYHHA = 0x346, + MPYHHAU = 0x34e, + FSCRRD = 0x398, + FESD = 0x3b8, + FRDS = 0x3b9, + FSCRWR = 0x3ba, + DFTSV = 0x3bf, + FCEQ = 0x3c2, + DFCEQ = 0x3c3, + MPY = 0x3c4, + MPYH = 0x3c5, + MPYHH = 0x3c6, + MPYS = 0x3c7, + CEQH = 0x3c8, + FCMEQ = 0x3ca, + DFCMEQ = 0x3cb, + MPYU = 0x3cc, + CEQB = 0x3d0, + FI = 0x3d4, + HEQ = 0x3d8, + }; -enum SPU_0_8_Opcodes -{ - BRZ = 0x40, - BRHZ = 0x44, - BRHNZ = 0x46, - STQR = 0x47, - BR = 0x64, - FSMBI = 0x65, - BRSL = 0x66, - LQR = 0x67, - IL = 0x81, -}; + enum SPU_0_9_Opcodes + { + CFLTS = 0x1d8, + CFLTU = 0x1d9, + CSFLT = 0x1da, + CUFLT = 0x1db, + }; -enum SPU_0_7_Opcodes -{ - SPU_ORI = 0x4, - AI = 0x1c, - AHI = 0x1d, - STQD = 0x24, - LQD = 0x34, - CLGTI = 0x5c, - CLGTHI = 0x5d, - CEQI = 0x7c, -}; + enum SPU_0_8_Opcodes + { + BRZ = 0x40, + STQA = 0x41, + BRNZ = 0x42, + BRHZ = 0x44, + BRHNZ = 0x46, + STQR = 0x47, + BRA = 0x60, + LQA = 0x61, + BRASL = 0x62, + BR = 0x64, + FSMBI = 0x65, + BRSL = 0x66, + LQR = 0x67, + IL = 0x81, + ILHU = 0x82, + ILH = 0x83, + IOHL = 0xc1, + }; -enum SPU_0_6_Opcodes -{ - HBRR = 0x9, - ILA = 0x21, -}; + enum SPU_0_7_Opcodes + { + ORI = 0x4, + ORHI = 0x5, + ORBI = 0x6, + SFI = 0xc, + SFHI = 0xd, + ANDI = 0x14, + ANDHI = 0x15, + ANDBI = 0x16, + AI = 0x1c, + AHI = 0x1d, + STQD = 0x24, + LQD = 0x34, + XORI = 0x44, + XORHI = 0x45, + XORBI = 0x46, + CGTI = 0x4c, + CGTHI = 0x4d, + CGTBI = 0x4e, + HGTI = 0x4f, + CLGTI = 0x5c, + CLGTHI = 0x5d, + CLGTBI = 0x5e, + HLGTI = 0x5f, + MPYI = 0x74, + MPYUI = 0x75, + CEQI = 0x7c, + CEQHI = 0x7d, + CEQBI = 0x7e, + HEQI = 0x7f, + }; -enum SPU_0_3_Opcodes -{ - SELB = 0x8, - SHUFB = 0xb, + enum SPU_0_6_Opcodes + { + HBRA = 0x8, + HBRR = 0x9, + ILA = 0x21, + }; + + enum SPU_0_3_Opcodes + { + SELB = 0x8, + SHUFB = 0xb, + MPYA = 0xc, + FNMS = 0xd, + FMA = 0xe, + FMS = 0xf, + }; }; class SPU_Opcodes @@ -79,79 +244,216 @@ public: virtual void Exit()=0; -/* -- 1: Unk/0xb0c2c58c -> 11c: b0 c2 c5 8c shufb $6,$11,$11,$12 -- 2: Unk/0x5800c505 -> 124: 58 00 c5 05 clgt $5,$10,$3 -- 3: Unk/0x5c000184 -> 128: 5c 00 01 84 clgti $4,$3,0 -- 4: Unk/0x18210282 -> 12c: 18 21 02 82 and $2,$5,$4 -- 5: Unk/0x00000000 -> 154: 00 00 00 00 stop -- 6: Unk/0x00200000 -> 1b4: 00 20 00 00 lnop -- 7: Unk/0x0f608487 -> 1c0: 0f 60 84 87 shli $7,$9,2 -- 8: Unk/0x18140384 -> 1c8: 18 14 03 84 a $4,$7,$80 -- 9: Unk/0x38940386 -> 1cc: 38 94 03 86 lqx $6,$7,$80 -- 10: Unk/0x3b810305 -> 1d0: 3b 81 03 05 rotqby $5,$6,$4 -- 11: Unk/0x35200280 -> 1d4: 35 20 02 80 bisl $0,$5 -- 12: Unk/0x237ff982 -> 1e4: 23 7f f9 82 brhnz $2,0x1b0 -- 13: Unk/0x35800014 -> 204: 35 80 00 14 hbr 0x254,$0 -- 14: Unk/0x5d13c482 -> 224: 5d 13 c4 82 clgthi $2,$9,79 -- 15: Unk/0x3ac1828d -> 240: 3a c1 82 8d cwx $13,$5,$6 -- 16: Unk/0x2881828b -> 24c: 28 81 82 8b stqx $11,$5,$6 -- 17: Unk/0x21a00b82 -> 25c: 21 a0 0b 82 wrch $ch23,$2 -- 18: Unk/0x01e00c05 -> 260: 01 e0 0c 05 rchcnt $5,$ch24 -- 19: Unk/0x7c004284 -> 264: 7c 00 42 84 ceqi $4,$5,1 -- 20: Unk/0x207ffe84 -> 26c: 20 7f fe 84 brz $4,0x260 -- 21: Unk/0x01a00c03 -> 27c: 01 a0 0c 03 rdch $3,$ch24 -*/ //0 - 10 ADD_OPCODE(STOP,(OP_uIMM code)); ADD_OPCODE(LNOP,()); + ADD_OPCODE(SYNC, (OP_uIMM Cbit)); + ADD_OPCODE(DSYNC, ()); + ADD_OPCODE(MFSPR,(OP_REG rt, OP_REG sa)); ADD_OPCODE(RDCH,(OP_REG rt, OP_REG ra)); ADD_OPCODE(RCHCNT,(OP_REG rt, OP_REG ra)); ADD_OPCODE(SF,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(OR,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(BG,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SFH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(NOR,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ABSDB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTM,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTMA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SHL,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTHM,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTMAH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SHLH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTMI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTMAI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); ADD_OPCODE(SHLI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTHI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTHMI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTMAHI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(SHLHI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); ADD_OPCODE(A,(OP_REG rt, OP_REG ra, OP_REG rb)); - ADD_OPCODE(SPU_AND,(OP_REG rt, OP_REG ra, OP_REG rb)); - ADD_OPCODE(LQX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(AND,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CG,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(AH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(NAND,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(AVGB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MTSPR,(OP_REG rt, OP_REG sa)); ADD_OPCODE(WRCH,(OP_REG ra, OP_REG rt)); + ADD_OPCODE(BIZ,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(BINZ,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(BIHZ,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(BIHNZ,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(STOPD,(OP_REG rc, OP_REG ra, OP_REG rb)); ADD_OPCODE(STQX,(OP_REG rt, OP_REG ra, OP_REG rb)); ADD_OPCODE(BI,(OP_REG ra)); ADD_OPCODE(BISL,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(IRET,(OP_REG ra)); + ADD_OPCODE(BISLED,(OP_REG rt, OP_REG ra)); ADD_OPCODE(HBR,(OP_REG p, OP_REG ro, OP_REG ra)); + ADD_OPCODE(GB,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(GBH,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(GBB,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FSM,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FSMH,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FSMB,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FREST,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FRSQEST,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(LQX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTQBYBI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTQMBYBI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SHLQBYBI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CBX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CHX,(OP_REG rt, OP_REG ra, OP_REG rb)); ADD_OPCODE(CWX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CDX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTQBI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTQMBI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SHLQBI,(OP_REG rt, OP_REG ra, OP_REG rb)); ADD_OPCODE(ROTQBY,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ROTQMBY,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SHLQBY,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ORX,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(CBD,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(CHD,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(CWD,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(CDD,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTQBII,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTQMBII,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(SHLQBII,(OP_REG rt, OP_REG ra, OP_sIMM i7)); ADD_OPCODE(ROTQBYI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(ROTQMBYI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); ADD_OPCODE(SHLQBYI,(OP_REG rt, OP_REG ra, OP_sIMM i7)); - ADD_OPCODE(SPU_NOP,(OP_REG rt)); + ADD_OPCODE(NOP,(OP_REG rt)); + ADD_OPCODE(CGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(XOR,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CGTH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(EQV,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CGTB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SUMB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(HGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CLZ,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(XSWD,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(XSHW,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(CNTB,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(XSBH,(OP_REG rt, OP_REG ra)); ADD_OPCODE(CLGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ANDC,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FCGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFCGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FS,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FM,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CLGTH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ORC,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FCMGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFCMGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFS,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFM,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CLGTB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(HLGT,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFMA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFMS,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFNMS,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFNMA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYHHU,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(ADDX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(SFX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CGX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(BGX,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYHHA,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYHHAU,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FSCRRD,(OP_REG rt)); + ADD_OPCODE(FESD,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FRDS,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(FSCRWR,(OP_REG rt, OP_REG ra)); + ADD_OPCODE(DFTSV,(OP_REG rt, OP_REG ra, OP_sIMM i7)); + ADD_OPCODE(FCEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFCEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPY,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYHH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYS,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CEQH,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FCMEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(DFCMEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(MPYU,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(CEQB,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(FI,(OP_REG rt, OP_REG ra, OP_REG rb)); + ADD_OPCODE(HEQ,(OP_REG rt, OP_REG ra, OP_REG rb)); + + //0 - 9 + ADD_OPCODE(CFLTS,(OP_REG rt, OP_REG ra, OP_sIMM i8)); + ADD_OPCODE(CFLTU,(OP_REG rt, OP_REG ra, OP_sIMM i8)); + ADD_OPCODE(CSFLT,(OP_REG rt, OP_REG ra, OP_sIMM i8)); + ADD_OPCODE(CUFLT,(OP_REG rt, OP_REG ra, OP_sIMM i8)); //0 - 8 ADD_OPCODE(BRZ,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(STQA,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(BRNZ,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(BRHZ,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(BRHNZ,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(STQR,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(BRA,(OP_sIMM i16)); + ADD_OPCODE(LQA,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(BRASL,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(BR,(OP_sIMM i16)); ADD_OPCODE(FSMBI,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(BRSL,(OP_REG rt, OP_sIMM i16)); - ADD_OPCODE(IL,(OP_REG rt, OP_sIMM i16)); ADD_OPCODE(LQR,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(IL,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(ILHU,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(ILH,(OP_REG rt, OP_sIMM i16)); + ADD_OPCODE(IOHL,(OP_REG rt, OP_sIMM i16)); //0 - 7 - ADD_OPCODE(SPU_ORI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ORI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ORHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ORBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(SFI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(SFHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ANDI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ANDHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(ANDBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(AI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(AHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(STQD,(OP_REG rt, OP_sIMM i10, OP_REG ra)); ADD_OPCODE(LQD,(OP_REG rt, OP_sIMM i10, OP_REG ra)); + ADD_OPCODE(XORI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(XORHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(XORBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CGTI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CGTHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CGTBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(HGTI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(CLGTI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(CLGTHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CLGTBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(HLGTI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(MPYI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(MPYUI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); ADD_OPCODE(CEQI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CEQHI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(CEQBI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); + ADD_OPCODE(HEQI,(OP_REG rt, OP_REG ra, OP_sIMM i10)); //0 - 6 + ADD_OPCODE(HBRA,(OP_sIMM ro, OP_sIMM i16)); ADD_OPCODE(HBRR,(OP_sIMM ro, OP_sIMM i16)); ADD_OPCODE(ILA,(OP_REG rt, OP_sIMM i18)); //0 - 3 ADD_OPCODE(SELB,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); ADD_OPCODE(SHUFB,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); + ADD_OPCODE(MPYA,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); + ADD_OPCODE(FNMS,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); + ADD_OPCODE(FMA,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); + ADD_OPCODE(FMS,(OP_REG rc, OP_REG ra, OP_REG rb, OP_REG rt)); ADD_OPCODE(UNK,(const s32 code, const s32 opcode, const s32 gcode)); }; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 9af4f4c653..fcac328f20 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4,6 +4,15 @@ #include "Emu/Cell/SPUInterpreter.h" #include "Emu/Cell/SPUDisAsm.h" +SPUThread& GetCurrentSPUThread() +{ + PPCThread* thread = GetCurrentPPCThread(); + + if(!thread || !thread->IsSPU()) throw wxString("GetCurrentSPUThread: bad thread"); + + return *(SPUThread*)thread; +} + SPUThread::SPUThread() : PPCThread(PPC_THREAD_SPU) { Reset(); diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 0ff9b7cd38..54e46e85f6 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -248,4 +248,6 @@ protected: private: virtual void DoCode(const s32 code); -}; \ No newline at end of file +}; + +SPUThread& GetCurrentSPUThread(); \ No newline at end of file diff --git a/rpcs3/Emu/DbgConsole.cpp b/rpcs3/Emu/DbgConsole.cpp index 9a7a54d1ba..263368600b 100644 --- a/rpcs3/Emu/DbgConsole.cpp +++ b/rpcs3/Emu/DbgConsole.cpp @@ -6,7 +6,7 @@ BEGIN_EVENT_TABLE(DbgConsole, FrameBase) END_EVENT_TABLE() DbgConsole::DbgConsole() - : FrameBase(NULL, wxID_ANY, "DbgConsole", wxEmptyString, wxDefaultSize, wxDefaultPosition) + : FrameBase(NULL, wxID_ANY, "DbgConsole", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxDEFAULT_FRAME_STYLE, true) , ThreadBase(false, "DbgConsole thread") { m_console = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, @@ -20,7 +20,7 @@ DbgConsole::DbgConsole() DbgConsole::~DbgConsole() { - Stop(); + ThreadBase::Stop(); m_dbg_buffer.Flush(); } @@ -39,7 +39,7 @@ void DbgConsole::Clear() void DbgConsole::Task() { - while(m_dbg_buffer.HasNewPacket()) + while(m_dbg_buffer.HasNewPacket() && !TestDestroy()) { DbgPacket packet = m_dbg_buffer.Pop(); m_console->SetDefaultStyle(packet.m_ch == 1 ? *m_color_red : *m_color_white); @@ -52,5 +52,7 @@ void DbgConsole::Task() void DbgConsole::OnQuit(wxCloseEvent& event) { + ThreadBase::Stop(); Hide(); + //event.Skip(); } \ No newline at end of file diff --git a/rpcs3/Emu/DbgConsole.h b/rpcs3/Emu/DbgConsole.h index 0f98807521..548fcb4458 100644 --- a/rpcs3/Emu/DbgConsole.h +++ b/rpcs3/Emu/DbgConsole.h @@ -27,7 +27,7 @@ struct _DbgBuffer : public MTPacketBuffer { } - void Push(const DbgPacket& data) + void _push(const DbgPacket& data) { const u32 stext = data.m_text.Len(); @@ -47,7 +47,7 @@ struct _DbgBuffer : public MTPacketBuffer CheckBusy(); } - DbgPacket Pop() + DbgPacket _pop() { DbgPacket ret; diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp new file mode 100644 index 0000000000..3aa909ffd6 --- /dev/null +++ b/rpcs3/Emu/FS/VFS.cpp @@ -0,0 +1,91 @@ +#include "stdafx.h" +#include "VFS.h" + +int sort_devices(const void* _a, const void* _b) +{ + const vfsDevice& a = **(const vfsDevice**)_a; + const vfsDevice& b = **(const vfsDevice**)_b; + + if(a.GetPs3Path().Len() > b.GetPs3Path().Len()) return 1; + if(a.GetPs3Path().Len() < b.GetPs3Path().Len()) return -1; + + return 0; +} + +void VFS::Mount(const wxString& ps3_path, const wxString& local_path, vfsDevice* device) +{ + UnMount(ps3_path); + + device->SetPath(ps3_path, local_path); + m_devices.Add(device); + + if(m_devices.GetCount() > 1) + { + std::qsort(m_devices.GetPtr(), m_devices.GetCount(), sizeof(vfsDevice*), sort_devices); + } +} + +void VFS::UnMount(const wxString& ps3_path) +{ + for(u32 i=0; iGetNew(); + stream->Open(path, mode); + } + + return stream; +} + +void VFS::Create(const wxString& ps3_path) +{ + wxString path; + + if(vfsDevice* dev = GetDevice(ps3_path, path)) + { + dev->Create(path); + } +} + +void VFS::Close(vfsStream*& device) +{ + delete device; + device = nullptr; +} + +vfsDevice* VFS::GetDevice(const wxString& ps3_path, wxString& path) +{ + u32 max_eq; + s32 max_i=-1; + + for(u32 i=0; i max_eq) + { + max_eq = eq; + max_i = i; + } + } + + if(max_i < 0) return nullptr; + + path = vfsDevice::GetWinPath(m_devices[max_i].GetLocalPath(), ps3_path(max_eq, ps3_path.Len() - max_eq)); + return &m_devices[max_i]; +} diff --git a/rpcs3/Emu/FS/VFS.h b/rpcs3/Emu/FS/VFS.h new file mode 100644 index 0000000000..75e0f2dc49 --- /dev/null +++ b/rpcs3/Emu/FS/VFS.h @@ -0,0 +1,15 @@ +#pragma once +#include "vfsDevice.h" + +struct VFS +{ + ArrayF m_devices; + + void Mount(const wxString& ps3_path, const wxString& local_path, vfsDevice* device); + void UnMount(const wxString& ps3_path); + + vfsStream* Open(const wxString& ps3_path, vfsOpenMode mode); + void Create(const wxString& ps3_path); + void Close(vfsStream*& device); + vfsDevice* GetDevice(const wxString& ps3_path, wxString& path); +}; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsDevice.cpp b/rpcs3/Emu/FS/vfsDevice.cpp new file mode 100644 index 0000000000..1560fa647b --- /dev/null +++ b/rpcs3/Emu/FS/vfsDevice.cpp @@ -0,0 +1,201 @@ +#include "stdafx.h" +#include "vfsDevice.h" + +vfsDevice::vfsDevice(const wxString& ps3_path, const wxString& local_path) + : m_ps3_path(ps3_path) + , m_local_path(GetWinPath(local_path)) +{ +} + +wxString vfsDevice::GetLocalPath() const +{ + return m_local_path; +} + +wxString vfsDevice::GetPs3Path() const +{ + return m_ps3_path; +} + +void vfsDevice::SetPath(const wxString& ps3_path, const wxString& local_path) +{ + m_ps3_path = ps3_path; + m_local_path = local_path; +} + +u32 vfsDevice::CmpPs3Path(const wxString& ps3_path) +{ + const u32 lim = min(m_ps3_path.Len(), ps3_path.Len()); + u32 ret = 0; + + for(u32 i=0; i= 0; --i) + { + if(path[i] == '\\' || path[i] == '/' || i == 0) + { + if(dir++ == end_dir_count) + { + to = i; + break; + } + } + } + + return path(from, to - from); +} + +wxString vfsDevice::GetRoot(const wxString& path) +{ + if(path.IsEmpty()) return wxEmptyString; + + u32 first_dir = path.Len() - 1; + + for(int i = path.Len() - 1, dir = 0, li = path.Len() - 1; i >= 0 && dir < 2; --i) + { + if(path[i] == '\\' || path[i] == '/' || i == 0) + { + switch(dir++) + { + case 0: + first_dir = i; + break; + + case 1: + if(!path(i + 1, li - i).Cmp("USRDIR")) return path(0, i + 1); + continue; + } + + li = i - 1; + } + } + + return path(0, first_dir + 1); +} + +wxString vfsDevice::GetRootPs3(const wxString& path) +{ + if(path.IsEmpty()) return wxEmptyString; + + static const wxString& home = "/dev_hdd0/game/"; + u32 last_dir = 0; + u32 first_dir = path.Len() - 1; + + for(int i = path.Len() - 1, dir = 0; i >= 0; --i) + { + if(path[i] == '\\' || path[i] == '/' || i == 0) + { + switch(dir++) + { + case 1: + if(!!path(i + 1, last_dir - i - 1).Cmp("USRDIR")) return wxEmptyString; + break; + + case 2: + return GetPs3Path(home + path(i + 1, last_dir - i - 1)); + } + + last_dir = i; + } + } + + return GetPs3Path(home + path(0, last_dir - 1)); +} + +wxString vfsDevice::GetWinPath(const wxString& p, bool is_dir) +{ + if(p.IsEmpty()) return wxEmptyString; + + wxString ret; + bool is_ls = false; + + for(u32 i=0; i GetEntryes()=0; + virtual void Close()=0; + + virtual bool Create(const wxString& path)=0; + virtual bool Exists(const wxString& path)=0; + virtual bool Rename(const wxString& from, const wxString& to)=0; + virtual bool Remove(const wxString& path)=0; +}; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsFileBase.cpp b/rpcs3/Emu/FS/vfsFileBase.cpp new file mode 100644 index 0000000000..5606491d37 --- /dev/null +++ b/rpcs3/Emu/FS/vfsFileBase.cpp @@ -0,0 +1,43 @@ +#include "stdafx.h" +#include "vfsFileBase.h" + +vfsFileBase::vfsFileBase() : vfsDevice() +{ +} + +vfsFileBase::~vfsFileBase() +{ + Close(); +} + +bool Access(const wxString& path, vfsOpenMode mode) +{ + return false; +} + +bool vfsFileBase::Open(const wxString& path, vfsOpenMode mode) +{ + m_path = path; + m_mode = mode; + + vfsStream::Reset(); + + return true; +} + +bool vfsFileBase::Close() +{ + m_path = wxEmptyString; + + return vfsStream::Close(); +} + +wxString vfsFileBase::GetPath() const +{ + return m_path; +} + +vfsOpenMode vfsFileBase::GetOpenMode() const +{ + return m_mode; +} \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsFileBase.h b/rpcs3/Emu/FS/vfsFileBase.h new file mode 100644 index 0000000000..0b33913dc2 --- /dev/null +++ b/rpcs3/Emu/FS/vfsFileBase.h @@ -0,0 +1,24 @@ +#pragma once +#include "vfsDevice.h" + +struct vfsFileBase : public vfsDevice +{ +protected: + wxString m_path; + vfsOpenMode m_mode; + +public: + vfsFileBase(); + virtual ~vfsFileBase(); + + virtual bool Open(const wxString& path, vfsOpenMode mode); + virtual bool Close(); + /* + virtual bool Create(const wxString& path)=0; + virtual bool Exists(const wxString& path)=0; + virtual bool Rename(const wxString& from, const wxString& to)=0; + virtual bool Remove(const wxString& path)=0; + */ + wxString GetPath() const; + vfsOpenMode GetOpenMode() const; +}; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsLocalFile.cpp b/rpcs3/Emu/FS/vfsLocalFile.cpp new file mode 100644 index 0000000000..244cb68e8a --- /dev/null +++ b/rpcs3/Emu/FS/vfsLocalFile.cpp @@ -0,0 +1,95 @@ +#include "stdafx.h" +#include "vfsLocalFile.h" + +static const wxFile::OpenMode vfs2wx_mode(vfsOpenMode mode) +{ + switch(mode) + { + case vfsRead: return wxFile::read; + case vfsWrite: return wxFile::write; + case vfsReadWrite: return wxFile::read_write; + case vfsWriteExcl: return wxFile::write_excl; + case vfsWriteAppend: return wxFile::write_append; + } + + return wxFile::read; +} + +static const wxSeekMode vfs2wx_seek(vfsSeekMode mode) +{ + switch(mode) + { + case vfsSeekSet: return wxFromStart; + case vfsSeekCur: return wxFromCurrent; + case vfsSeekEnd: return wxFromEnd; + } + + return wxFromStart; +} + +vfsLocalFile::vfsLocalFile() : vfsFileBase() +{ +} + +vfsLocalFile::vfsLocalFile(const wxString path, vfsOpenMode mode) : vfsFileBase() +{ + Open(path, mode); +} + +vfsDevice* vfsLocalFile::GetNew() +{ + return new vfsLocalFile(); +} + +bool vfsLocalFile::Open(const wxString& path, vfsOpenMode mode) +{ + Close(); + + if(mode == vfsRead && !m_file.Access(vfsDevice::GetWinPath(GetLocalPath(), path), vfs2wx_mode(mode))) return false; + + return m_file.Open(vfsDevice::GetWinPath(GetLocalPath(), path), vfs2wx_mode(mode)) && + vfsFileBase::Open(vfsDevice::GetPs3Path(GetPs3Path(), path), mode); +} + +bool vfsLocalFile::Create(const wxString& path) +{ + if(wxFileExists(path)) return false; + + wxFile f; + return f.Create(path); +} + +bool vfsLocalFile::Close() +{ + return m_file.Close() && vfsFileBase::Close(); +} + +u64 vfsLocalFile::GetSize() +{ + return m_file.Length(); +} + +u32 vfsLocalFile::Write(const void* src, u32 size) +{ + return m_file.Write(src, size); +} + +u32 vfsLocalFile::Read(void* dst, u32 size) +{ + return m_file.Read(dst, size); +} + +u64 vfsLocalFile::Seek(s64 offset, vfsSeekMode mode) +{ + return m_file.Seek(offset, vfs2wx_seek(mode)); +} + +u64 vfsLocalFile::Tell() const +{ + return m_file.Tell(); +} + +bool vfsLocalFile::IsOpened() const +{ + return m_file.IsOpened() && vfsFileBase::IsOpened(); +} \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsLocalFile.h b/rpcs3/Emu/FS/vfsLocalFile.h new file mode 100644 index 0000000000..d205675936 --- /dev/null +++ b/rpcs3/Emu/FS/vfsLocalFile.h @@ -0,0 +1,27 @@ +#pragma once +#include "vfsFileBase.h" + +class vfsLocalFile : public vfsFileBase +{ +private: + wxFile m_file; + +public: + vfsLocalFile(); + vfsLocalFile(const wxString path, vfsOpenMode mode = vfsRead); + vfsDevice* GetNew(); + + virtual bool Open(const wxString& path, vfsOpenMode mode = vfsRead); + virtual bool Create(const wxString& path); + virtual bool Close(); + + virtual u64 GetSize(); + + virtual u32 Write(const void* src, u32 size); + virtual u32 Read(void* dst, u32 size); + + virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet); + virtual u64 Tell() const; + + virtual bool IsOpened() const; +}; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsStream.cpp b/rpcs3/Emu/FS/vfsStream.cpp new file mode 100644 index 0000000000..abecaf1849 --- /dev/null +++ b/rpcs3/Emu/FS/vfsStream.cpp @@ -0,0 +1,74 @@ +#include "stdafx.h" +#include "vfsStream.h" + +vfsStream::vfsStream() +{ +} + +vfsStream::~vfsStream() +{ + Close(); +} + +void vfsStream::Reset() +{ + m_pos = 0; +} + +bool vfsStream::Close() +{ + Reset(); + + return true; +} + +u64 vfsStream::GetSize() +{ + u64 last_pos = Tell(); + Seek(0, vfsSeekEnd); + u64 size = Tell(); + Seek(last_pos, vfsSeekSet); + + return size; +} + +u32 vfsStream::Write(const void* src, u32 size) +{ + m_pos += size; + + return size; +} + +u32 vfsStream::Read(void* dst, u32 size) +{ + m_pos += size; + + return size; +} + +u64 vfsStream::Seek(s64 offset, vfsSeekMode mode) +{ + switch(mode) + { + case vfsSeekSet: m_pos = offset; break; + case vfsSeekCur: m_pos += offset; break; + case vfsSeekEnd: m_pos = GetSize() + offset; break; + } + + return m_pos; +} + +u64 vfsStream::Tell() const +{ + return m_pos; +} + +bool vfsStream::Eof() +{ + return Tell() >= GetSize(); +} + +bool vfsStream::IsOpened() const +{ + return true; +} \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsStream.h b/rpcs3/Emu/FS/vfsStream.h new file mode 100644 index 0000000000..be2325e5c9 --- /dev/null +++ b/rpcs3/Emu/FS/vfsStream.h @@ -0,0 +1,33 @@ +#pragma once + +enum vfsSeekMode +{ + vfsSeekSet, + vfsSeekCur, + vfsSeekEnd, +}; + +struct vfsStream +{ +protected: + u64 m_pos; + +public: + vfsStream(); + + virtual ~vfsStream(); + + virtual void Reset(); + virtual bool Close(); + + virtual u64 GetSize(); + + virtual u32 Write(const void* src, u32 size); + virtual u32 Read(void* dst, u32 size); + + virtual u64 Seek(s64 offset, vfsSeekMode mode = vfsSeekSet); + virtual u64 Tell() const; + virtual bool Eof(); + + virtual bool IsOpened() const; +}; \ No newline at end of file diff --git a/rpcs3/Emu/FS/vfsStreamMemory.cpp b/rpcs3/Emu/FS/vfsStreamMemory.cpp new file mode 100644 index 0000000000..29aa7a853e --- /dev/null +++ b/rpcs3/Emu/FS/vfsStreamMemory.cpp @@ -0,0 +1,36 @@ +#include "stdafx.h" +#include "vfsStreamMemory.h" + +vfsStreamMemory::vfsStreamMemory() : vfsStream() +{ +} + +vfsStreamMemory::vfsStreamMemory(u64 addr) : vfsStream() +{ + Open(addr); +} + +void vfsStreamMemory::Open(u64 addr) +{ + m_addr = addr; + + vfsStream::Reset(); +} + +u32 vfsStreamMemory::Write(const void* src, u32 size) +{ + if(!Memory.IsGoodAddr(m_addr + Tell(), size)) return 0; + + memcpy(&Memory[m_addr + Tell()], src, size); + + return vfsStream::Write(src, size); +} + +u32 vfsStreamMemory::Read(void* dst, u32 size) +{ + if(!Memory.IsGoodAddr(m_addr + Tell(), size)) return 0; + + memcpy(dst, &Memory[m_addr + Tell()], size); + + return vfsStream::Read(dst, size); +} diff --git a/rpcs3/Emu/FS/vfsStreamMemory.h b/rpcs3/Emu/FS/vfsStreamMemory.h new file mode 100644 index 0000000000..7acb0d8713 --- /dev/null +++ b/rpcs3/Emu/FS/vfsStreamMemory.h @@ -0,0 +1,16 @@ +#pragma once +#include "vfsStream.h" + +struct vfsStreamMemory : public vfsStream +{ + u64 m_addr; + +public: + vfsStreamMemory(); + vfsStreamMemory(u64 addr); + + void Open(u64 addr); + + virtual u32 Write(const void* src, u32 size); + virtual u32 Read(void* dst, u32 size); +}; \ No newline at end of file diff --git a/rpcs3/Emu/GS/GCM.h b/rpcs3/Emu/GS/GCM.h index 8318c5939c..80218b991e 100644 --- a/rpcs3/Emu/GS/GCM.h +++ b/rpcs3/Emu/GS/GCM.h @@ -1,10 +1,17 @@ #pragma once +enum +{ + CELL_GCM_DISPLAY_HSYNC = 1, + CELL_GCM_DISPLAY_VSYNC = 2, + CELL_GCM_DISPLAY_HSYNC_WITH_NOISE = 3, +}; + struct CellGcmControl { - volatile u32 put; - volatile u32 get; - volatile u32 ref; + u32 put; + u32 get; + u32 ref; }; struct CellGcmConfig @@ -332,12 +339,12 @@ enum NV3089_IMAGE_IN = 0x0000C40C, }; -static const wxString getMethodName(const u32 id) +static const wxString GetMethodName(const u32 id) { struct MethodName { const u32 id; - const wxString name; + const wxString& name; } static const METHOD_NAME_LIST[] = { { NV4097_NO_OPERATION , "NoOperation" } , { NV4097_NOTIFY , "Notify" } , diff --git a/rpcs3/Emu/GS/GL/FragmentProgram.cpp b/rpcs3/Emu/GS/GL/FragmentProgram.cpp index 3db47a5a43..a2678419ff 100644 --- a/rpcs3/Emu/GS/GL/FragmentProgram.cpp +++ b/rpcs3/Emu/GS/GL/FragmentProgram.cpp @@ -49,7 +49,12 @@ wxString FragmentDecompilerThread::GetMask() wxString FragmentDecompilerThread::AddReg(u32 index) { //if(!index) return "gl_FragColor"; - return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4", wxString::Format("r%d", index)); + return m_parr.AddParam(index ? PARAM_NONE : PARAM_OUT, "vec4", wxString::Format("r%d", index), index ? -1 : 0); +} + +wxString FragmentDecompilerThread::AddConst() +{ + return m_parr.AddParam(PARAM_CONST, "vec4", wxString::Format("fc%d", m_const_index++)); } wxString FragmentDecompilerThread::AddTex() @@ -96,8 +101,10 @@ template wxString FragmentDecompilerThread::GetSRC(T src) } break; - //case 2: //imm - //break; + case 2: //const + ConLog.Write("reg index = %d", src.tmp_reg_index); + ret += AddConst(); + break; default: ConLog.Error("Bad src type %d", src.reg_type); @@ -126,17 +133,11 @@ wxString FragmentDecompilerThread::BuildCode() for(u32 i=0; iIsAlive()) m_decompiler_thread->Delete(); - safe_delete(m_decompiler_thread); + if(m_decompiler_thread->IsAlive()) + { + m_decompiler_thread->Stop(); + } + + delete m_decompiler_thread; + m_decompiler_thread = nullptr; } Delete(); @@ -207,13 +272,17 @@ void ShaderProgram::Decompile() if(m_decompiler_thread) { Wait(); - if(m_decompiler_thread->IsAlive()) m_decompiler_thread->Delete(); - safe_delete(m_decompiler_thread); + if(m_decompiler_thread->IsAlive()) + { + m_decompiler_thread->Stop(); + } + + delete m_decompiler_thread; + m_decompiler_thread = nullptr; } m_decompiler_thread = new FragmentDecompilerThread(shader, parr, addr, size); - m_decompiler_thread->Create(); - m_decompiler_thread->Run(); + m_decompiler_thread->Start(); #endif } @@ -242,7 +311,7 @@ void ShaderProgram::Compile() memset(buf, 0, r+1); glGetShaderInfoLog(id, r, &len, buf); ConLog.Error("Failed to compile shader: %s", buf); - free(buf); + delete[] buf; } ConLog.Write(shader); @@ -255,9 +324,10 @@ void ShaderProgram::Delete() { for(u32 i=0; i wxString GetSRC(T src); wxString BuildCode(); - ExitCode Entry(); + virtual void Task(); u32 GetData(const u32 d) const { return d << 16 | d >> 16; } }; @@ -138,7 +142,13 @@ struct ShaderProgram u32 id; - void Wait() { if(m_decompiler_thread && m_decompiler_thread->IsRunning()) m_decompiler_thread->Wait(); } + void Wait() + { + if(m_decompiler_thread && m_decompiler_thread->IsAlive()) + { + m_decompiler_thread->Wait(); + } + } void Decompile(); void Compile(); diff --git a/rpcs3/Emu/GS/GL/GLBuffers.cpp b/rpcs3/Emu/GS/GL/GLBuffers.cpp index 587a702733..8d8e96957b 100644 --- a/rpcs3/Emu/GS/GL/GLBuffers.cpp +++ b/rpcs3/Emu/GS/GL/GLBuffers.cpp @@ -2,52 +2,118 @@ #include "GLBuffers.h" #include "GLGSRender.h" -BufferObject::BufferObject() - : m_id(0) - , m_type(0) +GLBufferObject::GLBufferObject() { } -BufferObject::BufferObject(u32 type) - : m_id(0) - , m_type(0) +GLBufferObject::GLBufferObject(u32 type) { Create(type); } -void BufferObject::Create(u32 type) +GLBufferObject::~GLBufferObject() { - if(m_id) return; - glGenBuffers(1, &m_id); + Delete(); +} + +void GLBufferObject::Create(GLuint type, u32 count) +{ + if(IsCreated()) return; + + m_id.InsertRoomEnd(count); + glGenBuffers(count, &m_id[0]); m_type = type; } -void BufferObject::Delete() +void GLBufferObject::Delete() { - if(!m_id) return; - glDeleteBuffers(1, &m_id); - m_id = 0; + if(!IsCreated()) return; + + glDeleteBuffers(m_id.GetCount(), &m_id[0]); + m_id.Clear(); m_type = 0; } -void BufferObject::Bind() +void GLBufferObject::Bind(u32 type, u32 num) { - if(m_id) glBindBuffer(m_type, m_id); + glBindBuffer(type, m_id[num]); } -void BufferObject::UnBind() +void GLBufferObject::UnBind(u32 type) { - glBindBuffer(m_type, 0); + glBindBuffer(type, 0); } -void BufferObject::SetData(const void* data, u32 size, u32 type) +void GLBufferObject::Bind(u32 num) { - if(!m_type) return; - Bind(); - glBufferData(m_type, size, data, type); + Bind(m_type, num); } -void VBO::Create() +void GLBufferObject::UnBind() { - BufferObject::Create(GL_ARRAY_BUFFER); + UnBind(m_type); +} + +void GLBufferObject::SetData(u32 type, const void* data, u32 size, u32 usage) +{ + glBufferData(type, size, data, usage); +} + +void GLBufferObject::SetData(const void* data, u32 size, u32 usage) +{ + SetData(m_type, data, size, usage); +} + +void GLBufferObject::SetAttribPointer(int location, int size, int type, int pointer, int stride, bool normalized) +{ + if(location < 0) return; + + glVertexAttribPointer(location, size, type, normalized ? GL_TRUE : GL_FALSE, stride, (const GLvoid*)pointer); + glEnableVertexAttribArray(location); +} + +bool GLBufferObject::IsCreated() const +{ + return m_id.GetCount() != 0; +} + +GLvbo::GLvbo() +{ +} + +void GLvbo::Create(u32 count) +{ + GLBufferObject::Create(GL_ARRAY_BUFFER, count); +} + +GLvao::GLvao() : m_id(0) +{ +} + +GLvao::~GLvao() +{ + Delete(); +} + +void GLvao::Create() +{ + if(!IsCreated()) glGenVertexArrays(1, &m_id); +} + +void GLvao::Bind() const +{ + glBindVertexArray(m_id); +} + +void GLvao::Delete() +{ + if(!IsCreated()) return; + + glDeleteVertexArrays(1, &m_id); + m_id = 0; +} + +bool GLvao::IsCreated() const +{ + return m_id != 0; } \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/GLBuffers.h b/rpcs3/Emu/GS/GL/GLBuffers.h index 8b334ece58..e42a7b4078 100644 --- a/rpcs3/Emu/GS/GL/GLBuffers.h +++ b/rpcs3/Emu/GS/GL/GLBuffers.h @@ -1,24 +1,48 @@ #pragma once #include "OpenGL.h" -struct BufferObject +struct GLBufferObject { protected: - u32 m_id; - u32 m_type; + Array m_id; + GLuint m_type; public: - BufferObject(); - BufferObject(u32 type); - - void Create(u32 type); + GLBufferObject(); + GLBufferObject(u32 type); + + ~GLBufferObject(); + + void Create(GLuint type, u32 count = 1); void Delete(); - void Bind(); + void Bind(u32 type, u32 num); + void UnBind(u32 type); + void Bind(u32 num = 0); void UnBind(); - void SetData(const void* data, u32 size, u32 type = GL_DYNAMIC_DRAW); + void SetData(u32 type, const void* data, u32 size, u32 usage = GL_DYNAMIC_DRAW); + void SetData(const void* data, u32 size, u32 usage = GL_DYNAMIC_DRAW); + void SetAttribPointer(int location, int size, int type, int pointer, int stride, bool normalized = false); + bool IsCreated() const; }; -struct VBO : public BufferObject +struct GLvbo : public GLBufferObject { + GLvbo(); + + void Create(u32 count = 1); +}; + +class GLvao +{ +protected: + GLuint m_id; + +public: + GLvao(); + ~GLvao(); + void Create(); + void Bind() const; + void Delete(); + bool IsCreated() const; }; \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/GLGSRender.cpp b/rpcs3/Emu/GS/GL/GLGSRender.cpp index e9e0ddce64..51a42300a0 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.cpp +++ b/rpcs3/Emu/GS/GL/GLGSRender.cpp @@ -1,8 +1,8 @@ #include "stdafx.h" #include "GLGSRender.h" -#include "ProgramBuffer.h" #define CMD_DEBUG 0 +#define DUMP_VERTEX_DATA 1 #if CMD_DEBUG #define CMD_LOG ConLog.Write @@ -12,19 +12,6 @@ gcmBuffer gcmBuffers[2]; -static VBO m_vbo; -static u32 m_vao_id; - -static ShaderProgram m_shader_prog; -static VertexData m_vertex_data[16]; -static Array m_vdata; -static VertexProgram m_vertex_progs[16]; -static VertexProgram* m_cur_vertex_prog; -static Program m_program; -static int m_fp_buf_num = -1; -static int m_vp_buf_num = -1; -static ProgramBuffer m_prog_buffer; - void checkForGlError(const char* situation) { GLenum err = glGetError(); @@ -35,6 +22,10 @@ void checkForGlError(const char* situation) } } +#if 0 + #define checkForGlError(x) /*x*/ +#endif + GLGSFrame::GLGSFrame() : GSFrame(NULL, "GSFrame[OpenGL]") , m_frames(0) @@ -42,12 +33,7 @@ GLGSFrame::GLGSFrame() canvas = new wxGLCanvas(this, wxID_ANY, NULL); canvas->SetSize(GetClientSize()); - Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GLGSFrame::OnLeftDclick)); - - //Flip(); - - //Connect(canvas->GetId(), wxEVT_LEFT_DCLICK, wxMouseEventHandler(GLGSFrame::OnLeftDclick)); - //Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GLGSFrame::OnLeftDclick)); + canvas->Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GSFrame::OnLeftDclick), (wxObject*)0, this); } void GLGSFrame::Flip() @@ -75,6 +61,7 @@ void GLGSFrame::OnSize(wxSizeEvent& event) void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h) { + /* //ConLog.Warning("SetViewport(x=%d, y=%d, w=%d, h=%d)", x, y, w, h); const wxSize client = GetClientSize(); @@ -84,15 +71,17 @@ void GLGSFrame::SetViewport(int x, int y, u32 w, u32 h) const int vy = (client.GetY() - viewport.GetY()) / 2; glViewport(vx + x, vy + y, viewport.GetWidth(), viewport.GetHeight()); + */ } GLGSRender::GLGSRender() : m_frame(NULL) - , m_draw(false) , m_rsx_thread(NULL) + , m_fp_buf_num(-1) + , m_vp_buf_num(-1) { + m_draw = false; m_frame = new GLGSFrame(); - m_vao_id = 0; } GLGSRender::~GLGSRender() @@ -103,40 +92,25 @@ GLGSRender::~GLGSRender() void GLGSRender::Enable(bool enable, const u32 cap) { - if(enable) glEnable(cap); - else glDisable(cap); + if(enable) + { + glEnable(cap); + } + else + { + glDisable(cap); + } } GLRSXThread::GLRSXThread(wxWindow* parent) - : wxThread(wxTHREAD_JOINABLE) + : ThreadBase(true, "OpenGL Thread") , m_parent(parent) - , m_paused(false) { } -void GLRSXThread::OnExit() -{ - call_stack.Clear(); - m_paused = true; -} - -void GLRSXThread::Start() -{ - Create(); - Run(); -} - extern CellGcmContextData current_context; -enum Method -{ - CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000, - CELL_GCM_METHOD_FLAG_JUMP = 0x20000000, - CELL_GCM_METHOD_FLAG_CALL = 0x00000002, - CELL_GCM_METHOD_FLAG_RETURN = 0x00020000, -}; - -wxThread::ExitCode GLRSXThread::Entry() +void GLRSXThread::Task() { ConLog.Write("GL RSX thread entry"); @@ -146,19 +120,50 @@ wxThread::ExitCode GLRSXThread::Entry() InitProcTable(); glEnable(GL_TEXTURE_2D); + glSwapInterval(Ini.GSVSyncEnable.GetValue() ? 1 : 0); - m_vbo.Create(); - if(!m_vao_id) glGenVertexArrays(1, &m_vao_id); + bool draw = true; + u32 drawed = 0; + u32 skipped = 0; + + p.Init(); while(!TestDestroy() && p.m_frame && !p.m_frame->IsBeingDeleted()) { - if(m_paused || p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunned()) + wxCriticalSectionLocker lock(p.m_cs_main); + + if(p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunned()) { + SemaphorePostAndWait(p.m_sem_flush); + if(p.m_draw) { p.m_draw = false; - p.m_frame->Flip(); + + if(p.m_skip_frames) + { + if(!draw) + { + if(skipped++ >= p.m_skip_frames) + { + skipped = 0; + draw = true; + } + } + else + { + if(drawed++ >= p.m_draw_frames) + { + drawed = 0; + draw = false; + } + } + } + + if(draw) p.m_frame->Flip(); + p.m_flip_status = 0; + if(SemaphorePostAndWait(p.m_sem_flip)) continue; } Sleep(1); @@ -171,21 +176,24 @@ wxThread::ExitCode GLRSXThread::Entry() if(cmd & CELL_GCM_METHOD_FLAG_JUMP) { - p.m_ctrl->get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT)); - ConLog.Warning("rsx jump!"); + u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT); + p.m_ctrl->get = re32(addr); + ConLog.Warning("rsx jump(0x%x)", addr); continue; } if(cmd & CELL_GCM_METHOD_FLAG_CALL) { call_stack.Push(get + 4); - p.m_ctrl->get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL); - ConLog.Warning("rsx call!"); + u32 addr = cmd & ~CELL_GCM_METHOD_FLAG_CALL; + p.m_ctrl->get = re32(addr); + ConLog.Warning("rsx call(0x%x)", addr); continue; } if(cmd & CELL_GCM_METHOD_FLAG_RETURN) { - p.m_ctrl->get = re32(call_stack.Pop()); - ConLog.Warning("rsx return!"); + u32 addr = call_stack.Pop(); + p.m_ctrl->get = re32(addr); + ConLog.Warning("rsx return(0x%x)", addr); continue; } if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) @@ -200,40 +208,37 @@ wxThread::ExitCode GLRSXThread::Entry() continue; } - p.DoCmd(cmd, cmd & 0x3ffff, mem32_t(p.m_ioAddress + get + 4), count); - p.m_ctrl->get = re32(get + (count + 1) * 4); - memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4); + mem32_t args(p.m_ioAddress + get + 4); + + if(!draw) + { + if((cmd & 0x3ffff) == NV406E_SET_REFERENCE) + { + p.m_ctrl->ref = re32(args[0]); + } + } + else + { + p.DoCmd(cmd, cmd & 0x3ffff, args, count); + } + + re(p.m_ctrl->get, get + (count + 1) * 4); + //memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4); } ConLog.Write("GL RSX thread exit..."); call_stack.Clear(); - m_vbo.Delete(); - m_cur_vertex_prog = 0; - m_program.Delete(); - m_shader_prog.Delete(); - - for(u32 i=0; i<16; ++i) m_vertex_progs[i].Delete(); - - m_prog_buffer.Clear(); - - return (ExitCode)0; -} - -void GLGSRender::Pause() -{ - if(m_rsx_thread) m_rsx_thread->m_paused = true; -} - -void GLGSRender::Resume() -{ - if(m_rsx_thread) m_rsx_thread->m_paused = false; + p.CloseOpenGL(); } void GLGSRender::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress) { if(m_frame->IsShown()) return; + m_draw_frames = 1; + m_skip_frames = 0; + m_frame->Show(); m_ioAddress = ioAddress; @@ -253,13 +258,17 @@ void GLGSRender::Draw() void GLGSRender::Close() { - if(m_rsx_thread) m_rsx_thread->Delete(); + if(m_rsx_thread) + { + m_rsx_thread->Stop(); + delete m_rsx_thread; + } if(m_frame->IsShown()) m_frame->Hide(); m_ctrl = NULL; } -void EnableVertexData() +void GLGSRender::EnableVertexData(bool indexed_draw) { Array offset_list; u32 cur_offset = 0; @@ -276,90 +285,80 @@ void EnableVertexData() memcpy(&m_vdata[pos], &m_vertex_data[i].data[0], m_vertex_data[i].data.GetCount()); } - glBindVertexArray(m_vao_id); - checkForGlError("glBindVertexArray"); - m_vbo.SetData(&m_vdata[0], m_vdata.GetCount()); - checkForGlError("m_vbo.SetData"); + m_vao.Create(); + m_vao.Bind(); + checkForGlError("initializing vao"); -#if CMD_DEBUG + m_vbo.Create(indexed_draw ? 2 : 1); + m_vbo.Bind(0); + m_vbo.SetData(&m_vdata[0], m_vdata.GetCount()); + + if(indexed_draw) + { + m_vbo.Bind(GL_ELEMENT_ARRAY_BUFFER, 1); + m_vbo.SetData(GL_ELEMENT_ARRAY_BUFFER, &m_indexed_array.m_data[0], m_indexed_array.m_data.GetCount()); + } + + checkForGlError("initializing vbo"); + +#if DUMP_VERTEX_DATA wxFile dump("VertexDataArray.dump", wxFile::write); #endif for(u32 i=0; i<16; ++i) { if(!m_vertex_data[i].IsEnabled()) continue; -#if CMD_DEBUG - dump.Write(wxString::Format("VertexData[%d]:\n", i)); -#endif - u32 gltype; - bool normalized = false; +#if DUMP_VERTEX_DATA + dump.Write(wxString::Format("VertexData[%d]:\n", i)); switch(m_vertex_data[i].type) { case 1: - gltype = GL_SHORT; normalized = true; -#if CMD_DEBUG for(u32 j = 0; j= 1 && m_vertex_data[i].type <= 7) + { + u32 gltype = gl_types[m_vertex_data[i].type - 1]; + bool normalized = gl_normalized[m_vertex_data[i].type - 1]; + + glEnableVertexAttribArray(i); + checkForGlError("glEnableVertexAttribArray"); + glVertexAttribPointer(i, m_vertex_data[i].size, gltype, normalized, 0, (void*)offset_list[i]); + checkForGlError("glVertexAttribPointer"); + } } } -void DisableVertexData() +void GLGSRender::DisableVertexData() { m_vdata.Clear(); for(u32 i=0; i<16; ++i) @@ -388,7 +413,7 @@ void DisableVertexData() } } -void LoadVertexData(u32 first, u32 count) +void GLGSRender::LoadVertexData(u32 first, u32 count) { for(u32 i=0; i<16; ++i) { @@ -398,13 +423,14 @@ void LoadVertexData(u32 first, u32 count) } } -void InitVertexData() +void GLGSRender::InitVertexData() { for(u32 i=0; iconstants4.GetCount(); ++i) { const VertexProgram::Constant4& c = m_cur_vertex_prog->constants4[i]; const wxString& name = wxString::Format("vc%d", c.id); - const int l = glGetUniformLocation(m_program.id, name); + //const int l = glGetUniformLocation(m_program.id, name); + const int l = m_program.GetLocation(name); checkForGlError("glGetUniformLocation " + name); //ConLog.Write(name + " x: %.02f y: %.02f z: %.02f w: %.02f", c.x, c.y, c.z, c.w); @@ -442,10 +468,11 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c ConLog.Write(debug); #endif - static int draw_mode = 0; + //static int draw_mode = 0; + static u32 semaphore_offset = 0; u32 index = 0; - static u32 draw_array_count = 0; + //static u32 draw_array_count = 0; switch(cmd) { @@ -465,8 +492,8 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c const u8 dimension = (args[1] >> 4) & 0xf; const u8 format = (args[1] >> 8) & 0xff; const u16 mipmap = (args[1] >> 16) & 0xffff; - CMD_LOG("offset=0x%x, location=0x%x, cubemap=0x%x, dimension=0x%x, format=0x%x, mipmap=0x%x", - offset, location, cubemap, dimension, format, mipmap); + CMD_LOG("index = %d, offset=0x%x, location=0x%x, cubemap=0x%x, dimension=0x%x, format=0x%x, mipmap=0x%x", + index, offset, location, cubemap, dimension, format, mipmap); tex.SetOffset(GetAddress(offset, location)); tex.SetFormat(cubemap, dimension, format, mipmap); @@ -480,6 +507,23 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c } break; + case_16(NV4097_SET_VERTEX_DATA4UB_M, 4): + { + u32 v = args[0]; + u8 v0 = v; + u8 v1 = v >> 8; + u8 v2 = v >> 16; + u8 v3 = v >> 24; + + m_vertex_data[index].type = 7; + m_vertex_data[index].data.AddCpy(v0); + m_vertex_data[index].data.AddCpy(v1); + m_vertex_data[index].data.AddCpy(v2); + m_vertex_data[index].data.AddCpy(v3); + ConLog.Warning("index = %d, v0 = 0x%x, v1 = 0x%x, v2 = 0x%x, v3 = 0x%x", index, v0, v1, v2, v3); + } + break; + case_16(NV4097_SET_TEXTURE_CONTROL1, 0x20): //TODO break; @@ -530,44 +574,62 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c } break; - case NV4097_SET_COLOR_MASK: - { - const u32 flags = args[0]; - - glColorMask( - flags & 0x0010000 ? GL_TRUE : GL_FALSE, - flags & 0x0000100 ? GL_TRUE : GL_FALSE, - flags & 0x0000001 ? GL_TRUE : GL_FALSE, - flags & 0x1000000 ? GL_TRUE : GL_FALSE); - } - break; - case NV4097_SET_COLOR_MASK_MRT: { } break; + case NV4097_SET_COLOR_MASK: + { + const u32 flags = args[0]; + + m_set_color_mask = true; + m_color_mask_a = flags & 0x1000000 ? true : false; + m_color_mask_r = flags & 0x0010000 ? true : false; + m_color_mask_g = flags & 0x0000100 ? true : false; + m_color_mask_b = flags & 0x0000001 ? true : false; + } + break; + case NV4097_SET_ALPHA_TEST_ENABLE: - Enable(args[0] ? true : false, GL_ALPHA_TEST); + m_set_alpha_test = args[0] ? true : false; + //Enable(args[0] ? true : false, GL_ALPHA_TEST); break; case NV4097_SET_BLEND_ENABLE: - Enable(args[0] ? true : false, GL_BLEND); + m_set_blend = args[0] ? true : false; + //Enable(args[0] ? true : false, GL_BLEND); break; case NV4097_SET_DEPTH_BOUNDS_TEST_ENABLE: - Enable(args[0] ? true : false, GL_DEPTH_CLAMP); + m_set_depth_bounds_test = args[0] ? true : false; + //Enable(args[0] ? true : false, GL_DEPTH_CLAMP); + break; + + case NV4097_SET_VIEWPORT_VERTICAL: + { + m_set_viewport_vertical = true; + m_viewport_y = args[0] & 0xffff; + m_viewport_h = args[0] >> 16; + } break; case NV4097_SET_VIEWPORT_HORIZONTAL: { - const u16 x = args[0] & 0xffff; - const u16 w = args[0] >> 16; - const u16 y = args[1] & 0xffff; - const u16 h = args[1] >> 16; - CMD_LOG("x=%d, y=%d, w=%d, h=%d", x, y, w, h); + m_set_viewport_horizontal = true; + m_viewport_x = args[0] & 0xffff; + m_viewport_w = args[0] >> 16; - m_frame->SetViewport(x, y, w, h); + if(count == 2) + { + m_set_viewport_vertical = true; + m_viewport_y = args[1] & 0xffff; + m_viewport_h = args[1] >> 16; + } + + CMD_LOG("x=%d, y=%d, w=%d, h=%d", m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); + + //m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); //glViewport(x, y, w, h); } break; @@ -577,18 +639,25 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c const u32 clip_min = args[0]; const u32 clip_max = args[1]; - CMD_LOG("clip_min=%.01f, clip_max=%.01f", *(float*)&clip_min, *(float*)&clip_max); + m_set_clip = true; + m_clip_min = (float&)clip_min; + m_clip_max = (float&)clip_max; - glDepthRangef(*(float*)&clip_min, *(float*)&clip_max); + CMD_LOG("clip_min=%.01f, clip_max=%.01f", m_clip_min, m_clip_max); + + //glDepthRangef(m_clip_min, m_clip_max); } break; case NV4097_SET_DEPTH_FUNC: - glDepthFunc(args[0]); + m_set_depth_func = true; + m_depth_func = args[0]; + //glDepthFunc(m_depth_func); break; case NV4097_SET_DEPTH_TEST_ENABLE: - Enable(args[0] ? true : false, GL_DEPTH_TEST); + m_depth_test_enable = args[0] ? true : false; + //Enable(args[0] ? true : false, GL_DEPTH_TEST); break; case NV4097_SET_FRONT_POLYGON_MODE: @@ -656,130 +725,74 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c LoadVertexData(first, _count); - draw_array_count += _count; + m_draw_array_count += _count; + } + } + break; + + case NV4097_SET_INDEX_ARRAY_ADDRESS: + { + m_indexed_array.m_addr = GetAddress(args[0], args[1] & 0xf); + m_indexed_array.m_type = args[1] >> 4; + } + break; + + case NV4097_DRAW_INDEX_ARRAY: + { + for(u32 c=0; c> 24) + 1; + + if(first < m_indexed_array.m_first) m_indexed_array.m_first = first; + + for(u32 i=first; i<_count; ++i) + { + u32 index; + switch(m_indexed_array.m_type) + { + case 0: + { + int pos = m_indexed_array.m_data.GetCount(); + m_indexed_array.m_data.InsertRoomEnd(4); + index = Memory.Read32(m_indexed_array.m_addr + i * 4); + *(u32*)&m_indexed_array.m_data[pos] = index; + ConLog.Warning("index 4: %d", *(u32*)&m_indexed_array.m_data[pos]); + } + break; + + case 1: + { + int pos = m_indexed_array.m_data.GetCount(); + m_indexed_array.m_data.InsertRoomEnd(2); + index = Memory.Read16(m_indexed_array.m_addr + i * 2); + ConLog.Warning("index 2: %d", index); + *(u32*)&m_indexed_array.m_data[pos] = index; + } + break; + } + + if(index < m_indexed_array.index_min) m_indexed_array.index_min = index; + if(index > m_indexed_array.index_max) m_indexed_array.index_max = index; + } + + m_indexed_array.m_count += _count; } } break; case NV4097_SET_BEGIN_END: { - if(args[0]) //begin + if(args[0]) { - draw_mode = args[0] - 1; - break; + //begin + m_draw_mode = args[0] - 1; } - - //end - - if(!m_cur_vertex_prog) + else { - ConLog.Warning("NV4097_SET_BEGIN_END: m_cur_vertex_prog == NULL"); - - memset(m_vertex_data, 0, sizeof(VertexData) * 16); - - draw_array_count = 0; - m_vbo.UnBind(); - break; + //end + ExecCMD(); } - - if(!m_program.IsCreated()) - { - //ConLog.Write("Create program"); - m_vp_buf_num = m_prog_buffer.SearchVp(*m_cur_vertex_prog); - - if(m_vp_buf_num == -1) - { - ConLog.Warning("VP not found in buffer!"); - m_cur_vertex_prog->Decompile(); - } - - if(m_fp_buf_num == -1) - { - ConLog.Warning("FP not found in buffer!"); - m_shader_prog.Wait(); - m_shader_prog.Compile(); - - wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write); - f.Write(m_shader_prog.shader); - } - - if(m_vp_buf_num == -1) - { - m_cur_vertex_prog->Wait(); - m_cur_vertex_prog->Compile(); - - wxFile f(wxGetCwd() + "/VertexProgram.txt", wxFile::write); - f.Write(m_cur_vertex_prog->shader); - } - - if(m_fp_buf_num != -1 && m_vp_buf_num != -1) - { - m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); - } - - if(!m_program.id) - { - m_program.Create(m_cur_vertex_prog->id, m_shader_prog.id); - m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_vertex_prog); - - m_program.Use(); - - GLint r = GL_FALSE; - glGetProgramiv(m_program.id, GL_VALIDATE_STATUS, &r); - if(r != GL_TRUE) - { - glGetProgramiv(m_program.id, GL_INFO_LOG_LENGTH, &r); - - if(r) - { - char* buf = new char[r+1]; - GLsizei len; - memset(buf, 0, r+1); - glGetProgramInfoLog(m_program.id, r, &len, buf); - ConLog.Error("Failed to validate program: %s", buf); - free(buf); - } - - Emu.Pause(); - } - } - } - else m_program.Use(); - - for(u32 i=0; i<16; ++i) - { - GLTexture& tex = m_frame->GetTexture(i); - if(!tex.IsEnabled()) continue; - - glActiveTexture(GL_TEXTURE0_ARB + i); - checkForGlError("glActiveTexture"); - tex.Bind(); - checkForGlError("tex.Bind"); - m_program.SetTex(i); - checkForGlError("m_program.SetTex"); - tex.Init(); - checkForGlError("tex.Init"); - //tex.Save(); - } - - if(draw_array_count) - { - EnableVertexData(); - InitVertexData(); - glDrawArrays(draw_mode, 0, draw_array_count); - checkForGlError("glDrawArrays"); - - DisableVertexData(); - draw_array_count = 0; - } - - m_program.id = 0; - m_shader_prog.id = 0; - m_cur_vertex_prog->id = 0; - - memset(m_vertex_data, 0, sizeof(VertexData) * 16); - - m_vbo.UnBind(); } break; @@ -802,11 +815,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c { m_shader_prog.Delete(); m_shader_prog.addr = GetAddress(args[0] & ~0x3, (args[0] & 0x3) - 1); - m_program.Delete(); - - m_fp_buf_num = m_prog_buffer.SearchFp(m_shader_prog); - - if(m_fp_buf_num == -1) m_shader_prog.Decompile(); + //m_program.Delete(); } break; @@ -829,7 +838,7 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c case NV4097_SET_TRANSFORM_PROGRAM_LOAD: { - m_program.Delete(); + //m_program.Delete(); m_cur_vertex_prog = &m_vertex_progs[args[0]]; m_cur_vertex_prog->Delete(); @@ -893,10 +902,10 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c VertexProgram::Constant4 c; c.id = id; - c.x = *(float*)&x; - c.y = *(float*)&y; - c.z = *(float*)&z; - c.w = *(float*)&w; + c.x = (float&)x; + c.y = (float&)y; + c.z = (float&)z; + c.w = (float&)w; CMD_LOG("SET_TRANSFORM_CONSTANT_LOAD[%d : %d] = (%f, %f, %f, %f)", i, id, c.x, c.y, c.z, c.w); m_cur_vertex_prog->constants4.AddCpy(c); @@ -969,16 +978,30 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c glDepthMask(args[0]); break; + case NV4097_SET_SCISSOR_VERTICAL: + { + m_set_scissor_vertical = true; + m_scissor_y = args[0] & 0xffff; + m_scissor_h = args[0] >> 16; + } + break; + case NV4097_SET_SCISSOR_HORIZONTAL: { - const u16 x = args[0] & 0xffff; - const u16 w = args[0] >> 16; - const u16 y = args[1] & 0xffff; - const u16 h = args[1] >> 16; - - CMD_LOG("x=%d, y=%d, w=%d, h=%d", x, y, w, h); + m_set_scissor_horizontal = true; + m_scissor_x = args[0] & 0xffff; + m_scissor_w = args[0] >> 16; - glScissor(x, y, w, h); + if(count == 2) + { + m_set_scissor_vertical = true; + m_scissor_y = args[1] & 0xffff; + m_scissor_h = args[1] >> 16; + } + + CMD_LOG("x=%d, y=%d, w=%d, h=%d", m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + + //glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); } break; @@ -990,18 +1013,36 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c } break; - case NV406E_SEMAPHORE_OFFSET: + case NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE: { //TODO } break; + case NV4097_SET_SEMAPHORE_OFFSET: + case NV406E_SEMAPHORE_OFFSET: + { + semaphore_offset = args[0]; + } + break; + case NV406E_SEMAPHORE_ACQUIRE: { //TODO } break; + case NV4097_SET_RESTART_INDEX: + { + //TODO + } + break; + + case NV4097_INVALIDATE_L2: + { + //TODO + } + break; case NV4097_SET_CONTEXT_DMA_COLOR_A: { //TODO @@ -1074,10 +1115,21 @@ void GLGSRender::DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 c } break; + case NV4097_SET_ANTI_ALIASING_CONTROL: + { + //TODO + } + break; + + case NV4097_SET_ZSTENCIL_CLEAR_VALUE: + case NV4097_SET_ZCULL_CONTROL0: + case NV4097_SET_ZCULL_CONTROL1: + case NV4097_SET_SCULL_CONTROL: + break; default: { - wxString log = getMethodName(cmd); + wxString log = GetMethodName(cmd); log += "("; for(u32 i=0; iDecompile(); + } + + if(m_fp_buf_num == -1) + { + ConLog.Warning("FP not found in buffer!"); + m_shader_prog.Wait(); + m_shader_prog.Compile(); + + wxFile f(wxGetCwd() + "/FragmentProgram.txt", wxFile::write); + f.Write(m_shader_prog.shader); + } + + if(m_vp_buf_num == -1) + { + m_cur_vertex_prog->Wait(); + m_cur_vertex_prog->Compile(); + + wxFile f(wxGetCwd() + "/VertexProgram.txt", wxFile::write); + f.Write(m_cur_vertex_prog->shader); + } + + if(m_fp_buf_num != -1 && m_vp_buf_num != -1) + { + m_program.id = m_prog_buffer.GetProg(m_fp_buf_num, m_vp_buf_num); + } + + if(!m_program.id) + { + m_program.Create(m_cur_vertex_prog->id, m_shader_prog.id); + m_prog_buffer.Add(m_program, m_shader_prog, *m_cur_vertex_prog); + + m_program.Use(); + + GLint r = GL_FALSE; + glGetProgramiv(m_program.id, GL_VALIDATE_STATUS, &r); + if(r != GL_TRUE) + { + glGetProgramiv(m_program.id, GL_INFO_LOG_LENGTH, &r); + + if(r) + { + char* buf = new char[r+1]; + GLsizei len; + memset(buf, 0, r+1); + glGetProgramInfoLog(m_program.id, r, &len, buf); + ConLog.Error("Failed to validate program: %s", buf); + delete[] buf; + } + + Emu.Pause(); + } + } + + return true; +} + +void GLGSRender::ExecCMD() +{ + if(LoadProgram()) + { + if(m_set_color_mask) + { + glColorMask(m_color_mask_r, m_color_mask_g, m_color_mask_b, m_color_mask_a); + } + + 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)) + m_frame->SetClientSize(m_viewport_w, m_viewport_h); + //m_frame->SetViewport(m_viewport_x, m_viewport_y, m_viewport_w, m_viewport_h); + } + + if(m_set_scissor_horizontal && m_set_scissor_vertical) + { + glScissor(m_scissor_x, m_scissor_y, m_scissor_w, m_scissor_h); + } + + Enable(m_depth_test_enable, GL_DEPTH_TEST); + Enable(m_set_alpha_test, GL_ALPHA_TEST); + Enable(m_set_depth_bounds_test, GL_DEPTH_CLAMP); + Enable(m_set_blend, GL_BLEND); + + if(m_set_depth_func) + { + glDepthFunc(m_depth_func); + } + + if(m_set_clip) + { + glDepthRangef(m_clip_min, m_clip_max); + } + + for(u32 i=0; i<16; ++i) + { + GLTexture& tex = m_frame->GetTexture(i); + if(!tex.IsEnabled()) continue; + + glActiveTexture(GL_TEXTURE0_ARB + i); + checkForGlError("glActiveTexture"); + tex.Bind(); + checkForGlError("tex.Bind"); + m_program.SetTex(i); + checkForGlError("m_program.SetTex"); + tex.Init(); + checkForGlError("tex.Init"); + tex.Save(); + } + + if(m_indexed_array.m_count && m_draw_array_count) + { + ConLog.Warning("m_indexed_array.m_count && draw_array_count"); + } + + if(m_indexed_array.m_count) + { + LoadVertexData(m_indexed_array.index_min, m_indexed_array.index_max - m_indexed_array.index_min + 1); + EnableVertexData(true); + InitVertexData(); + + wxFile log("IndexedDrawLog.txt", wxFile::write); + log.Write(wxString::Format("Draw mode: %d\n", m_draw_mode)); + + m_vao.Bind(); + switch(m_indexed_array.m_type) + { + case 0: + glDrawElements(m_draw_mode, m_indexed_array.m_count, GL_UNSIGNED_INT, nullptr); + checkForGlError("glDrawElements #4"); + for(uint i=0; iid = 0; + + memset(m_vertex_data, 0, sizeof(VertexData) * 16); + + if(m_vbo.IsCreated()) + { + m_vbo.UnBind(); + m_vbo.Delete(); + } + + m_vao.Delete(); + + Init(); +} + +void GLGSRender::Init() +{ + m_draw_array_count = 0; + m_draw_mode = 0; + ExecRSXCMDdata::Reset(); +} + +void GLGSRender::CloseOpenGL() +{ + Reset(); } \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/GLGSRender.h b/rpcs3/Emu/GS/GL/GLGSRender.h index 6153b2ea91..e8aef91f04 100644 --- a/rpcs3/Emu/GS/GL/GLGSRender.h +++ b/rpcs3/Emu/GS/GL/GLGSRender.h @@ -1,9 +1,11 @@ #pragma once #include "Emu/GS/GSRender.h" +#include "Emu/GS/RSXThread.h" #include "wx/glcanvas.h" #include "GLBuffers.h" #include "Program.h" #include "OpenGL.h" +#include "ProgramBuffer.h" #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "gl.lib") @@ -66,9 +68,6 @@ public: void Init() { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - if(!m_id) { glGenTextures(1, &m_id); @@ -87,9 +86,9 @@ public: //TODO: safe init checkForGlError("GLTexture::Init() -> glBindTexture"); - switch(m_format) + switch(m_format & ~(0x20 | 0x40)) { - case 0xA1: + case 0x81: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RED, GL_UNSIGNED_BYTE, Memory.GetMemFromAddr(m_offset)); checkForGlError("GLTexture::Init() -> glTexImage2D"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); @@ -99,7 +98,7 @@ public: checkForGlError("GLTexture::Init() -> glTexParameteri"); break; - case 0xA5: + case 0x85: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, Memory.GetMemFromAddr(m_offset)); checkForGlError("GLTexture::Init() -> glTexImage2D"); break; @@ -114,42 +113,32 @@ public: { if(!m_id || !m_offset) return; + ConLog.Write("start"); + u32* alldata = new u32[m_width * m_height]; + + glBindTexture(GL_TEXTURE_2D, m_id); + glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, alldata); + u8* data = new u8[m_width * m_height * 3]; u8* alpha = new u8[m_width * m_height]; - u8* src = Memory.GetMemFromAddr(m_offset); - u8* dst = data; + + u8* src = (u8*)alldata; + u8* dst_d = data; u8* dst_a = alpha; - - switch(m_format) + for(u32 i=0; i m_data; + int m_type; + u32 m_first; + u32 m_count; + u32 m_addr; + u32 index_max; + u32 index_min; + + IndexArrayData() + { + Reset(); + } + + void Reset() + { + m_type = 0; + m_first = ~0; + m_count = 0; + m_addr = 0; + index_min = ~0; + index_max = 0; + m_data.Clear(); + } +}; + struct GLGSFrame : public GSFrame { wxGLCanvas* canvas; @@ -197,42 +213,66 @@ private: extern gcmBuffer gcmBuffers[2]; -struct GLRSXThread : public wxThread +struct GLRSXThread : public ThreadBase { wxWindow* m_parent; Stack call_stack; - volatile bool m_paused; - GLRSXThread(wxWindow* parent); - virtual void OnExit(); - void Start(); - ExitCode Entry(); + virtual void Task(); }; class GLGSRender : public wxWindow , public GSRender + , public ExecRSXCMDdata { private: GLRSXThread* m_rsx_thread; + IndexArrayData m_indexed_array; + + ShaderProgram m_shader_prog; + VertexData m_vertex_data[16]; + Array m_vdata; + VertexProgram m_vertex_progs[16]; + VertexProgram* m_cur_vertex_prog; + Program m_program; + int m_fp_buf_num; + int m_vp_buf_num; + int m_draw_array_count; + int m_draw_mode; + ProgramBuffer m_prog_buffer; + + GLvao m_vao; + GLvbo m_vbo; + public: GLGSFrame* m_frame; - volatile bool m_draw; + u32 m_draw_frames; + u32 m_skip_frames; GLGSRender(); ~GLGSRender(); private: + void EnableVertexData(bool indexed_draw=false); + void DisableVertexData(); + void LoadVertexData(u32 first, u32 count); + void InitVertexData(); + void Enable(bool enable, const u32 cap); virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress); virtual void Draw(); virtual void Close(); - virtual void Pause(); - virtual void Resume(); + bool LoadProgram(); public: void DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count); + void CloseOpenGL(); + + virtual void ExecCMD(); + virtual void Reset(); + void Init(); }; \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/GLProcTable.tbl b/rpcs3/Emu/GS/GL/GLProcTable.tbl index 3d218ee8d9..2ebe4199e7 100644 --- a/rpcs3/Emu/GS/GL/GLProcTable.tbl +++ b/rpcs3/Emu/GS/GL/GLProcTable.tbl @@ -1,42 +1,45 @@ - -OPENGL_PROC(PFNGLGENBUFFERSPROC,glGenBuffers); -OPENGL_PROC(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); -OPENGL_PROC(PFNGLBINDBUFFERPROC, glBindBuffer); -OPENGL_PROC(PFNGLISBUFFERPROC, glIsBuffer); -OPENGL_PROC(PFNGLBUFFERDATAPROC, glBufferData); -OPENGL_PROC(PFNGLBUFFERSUBDATAPROC, glBufferSubData); -OPENGL_PROC(PFNGLGETBUFFERSUBDATAPROC, glGetBufferSubData); -OPENGL_PROC(PFNGLMAPBUFFERPROC, glMapBuffer); -OPENGL_PROC(PFNGLUNMAPBUFFERPROC, glUnmapBuffer); -OPENGL_PROC(PFNGLGETBUFFERPARAMETERIVPROC, glGetBufferParameteriv); -OPENGL_PROC(PFNGLGETBUFFERPOINTERVPROC, glGetBufferPointerv); -OPENGL_PROC(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); -OPENGL_PROC(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); -OPENGL_PROC(PFNGLBLENDCOLORPROC, glBlendColor); -OPENGL_PROC(PFNGLBLENDEQUATIONPROC, glBlendEquation); -OPENGL_PROC(PFNGLCREATESHADERPROC, glCreateShader); -OPENGL_PROC(PFNGLDELETESHADERPROC, glDeleteShader); -OPENGL_PROC(PFNGLCOMPILESHADERPROC, glCompileShader); -OPENGL_PROC(PFNGLSHADERSOURCEPROC, glShaderSource); -OPENGL_PROC(PFNGLGETSHADERIVPROC, glGetShaderiv); -OPENGL_PROC(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); -OPENGL_PROC(PFNGLACTIVETEXTUREPROC, glActiveTexture); -OPENGL_PROC(PFNGLCREATEPROGRAMPROC, glCreateProgram); -OPENGL_PROC(PFNGLDELETEPROGRAMPROC, glDeleteProgram); -OPENGL_PROC(PFNGLATTACHSHADERPROC, glAttachShader); -OPENGL_PROC(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation); -OPENGL_PROC(PFNGLLINKPROGRAMPROC, glLinkProgram); -OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, glBindFragDataLocation); -OPENGL_PROC(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); -OPENGL_PROC(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); -OPENGL_PROC(PFNGLGETPROGRAMIVPROC, glGetProgramiv); -OPENGL_PROC(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); -OPENGL_PROC(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); -OPENGL_PROC(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); -OPENGL_PROC(PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVertexAttribArray); -OPENGL_PROC(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); -OPENGL_PROC(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); -OPENGL_PROC(PFNGLDEPTHRANGEFPROC, glDepthRangef); -OPENGL_PROC(PFNGLUNIFORM1IPROC, glUniform1i); -OPENGL_PROC(PFNGLUNIFORM4FPROC, glUniform4f); -OPENGL_PROC(PFNGLUSEPROGRAMPROC, glUseProgram); \ No newline at end of file +OPENGL_PROC(PFNGLGENBUFFERSPROC, GenBuffers); +OPENGL_PROC(PFNGLDELETEBUFFERSPROC, DeleteBuffers); +OPENGL_PROC(PFNGLBINDBUFFERPROC, BindBuffer); +OPENGL_PROC(PFNGLISBUFFERPROC, IsBuffer); +OPENGL_PROC(PFNGLBUFFERDATAPROC, BufferData); +OPENGL_PROC(PFNGLBUFFERSUBDATAPROC, BufferSubData); +OPENGL_PROC(PFNGLGETBUFFERSUBDATAPROC, GetBufferSubData); +OPENGL_PROC(PFNGLMAPBUFFERPROC, MapBuffer); +OPENGL_PROC(PFNGLUNMAPBUFFERPROC, UnmapBuffer); +OPENGL_PROC(PFNGLGETBUFFERPARAMETERIVPROC, GetBufferParameteriv); +OPENGL_PROC(PFNGLGETBUFFERPOINTERVPROC, GetBufferPointerv); +OPENGL_PROC(PFNGLBLENDFUNCSEPARATEPROC, BlendFuncSeparate); +OPENGL_PROC(PFNGLBLENDEQUATIONSEPARATEPROC, BlendEquationSeparate); +OPENGL_PROC(PFNGLBLENDCOLORPROC, BlendColor); +OPENGL_PROC(PFNGLBLENDEQUATIONPROC, BlendEquation); +OPENGL_PROC(PFNGLCREATESHADERPROC, CreateShader); +OPENGL_PROC(PFNGLDELETESHADERPROC, DeleteShader); +OPENGL_PROC(PFNGLCOMPILESHADERPROC, CompileShader); +OPENGL_PROC(PFNGLSHADERSOURCEPROC, ShaderSource); +OPENGL_PROC(PFNGLGETSHADERIVPROC, GetShaderiv); +OPENGL_PROC(PFNGLGETSHADERINFOLOGPROC, GetShaderInfoLog); +OPENGL_PROC(PFNGLACTIVETEXTUREPROC, ActiveTexture); +OPENGL_PROC(PFNGLCREATEPROGRAMPROC, CreateProgram); +OPENGL_PROC(PFNGLDELETEPROGRAMPROC, DeleteProgram); +OPENGL_PROC(PFNGLATTACHSHADERPROC, AttachShader); +OPENGL_PROC(PFNGLGETATTRIBLOCATIONPROC, GetAttribLocation); +OPENGL_PROC(PFNGLLINKPROGRAMPROC, LinkProgram); +OPENGL_PROC(PFNGLBINDFRAGDATALOCATIONPROC, BindFragDataLocation); +OPENGL_PROC(PFNGLBINDATTRIBLOCATIONPROC, BindAttribLocation); +OPENGL_PROC(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation); +OPENGL_PROC(PFNGLGETPROGRAMIVPROC, GetProgramiv); +OPENGL_PROC(PFNGLGETPROGRAMINFOLOGPROC, GetProgramInfoLog); +OPENGL_PROC(PFNGLVERTEXATTRIBPOINTERPROC, VertexAttribPointer); +OPENGL_PROC(PFNGLENABLEVERTEXATTRIBARRAYPROC, EnableVertexAttribArray); +OPENGL_PROC(PFNGLDISABLEVERTEXATTRIBARRAYPROC, DisableVertexAttribArray); +OPENGL_PROC(PFNGLGENVERTEXARRAYSPROC, GenVertexArrays); +OPENGL_PROC(PFNGLBINDVERTEXARRAYPROC, BindVertexArray); +OPENGL_PROC(PFNGLDELETEVERTEXARRAYSPROC, DeleteVertexArrays); +OPENGL_PROC(PFNGLDEPTHRANGEFPROC, DepthRangef); +OPENGL_PROC(PFNGLUNIFORM1IPROC, Uniform1i); +OPENGL_PROC(PFNGLUNIFORM1FPROC, Uniform1f); +OPENGL_PROC(PFNGLUNIFORM4FPROC, Uniform4f); +OPENGL_PROC(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv); +OPENGL_PROC(PFNGLUSEPROGRAMPROC, UseProgram); +OPENGL_PROC2(PFNWGLSWAPINTERVALEXTPROC, SwapInterval, wglSwapIntervalEXT); \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/OpenGL.cpp b/rpcs3/Emu/GS/GL/OpenGL.cpp index faab88d627..4ac3fb3951 100644 --- a/rpcs3/Emu/GS/GL/OpenGL.cpp +++ b/rpcs3/Emu/GS/GL/OpenGL.cpp @@ -3,11 +3,44 @@ void InitProcTable() { - #define OPENGL_PROC(p, n) n = (p)wglGetProcAddress(#n) +#define OPENGL_PROC(p, n) OPENGL_PROC2(p, n, gl##n) +#define OPENGL_PROC2(p, n, tn) /*if(!gl##n)*/ if(!(gl##n = (p)wglGetProcAddress(#tn))) ConLog.Error("OpenGL: initialization of " #tn " failed.") #include "GLProcTable.tbl" - #undef OPENGL_PROC +#undef OPENGL_PROC +#undef OPENGL_PROC2 } -#define OPENGL_PROC(p, n) p n = NULL -#include "GLProcTable.tbl" -#undef OPENGL_PROC \ No newline at end of file +#define OPENGL_PROC(p, n) p gl##n = nullptr +#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n) + #include "GLProcTable.tbl" +#undef OPENGL_PROC +#undef OPENGL_PROC2 + +OpenGL::OpenGL() +{ + Close(); + Init(); +} + +OpenGL::~OpenGL() +{ + Close(); +} + +void OpenGL::Init() +{ +#define OPENGL_PROC(p, n) OPENGL_PROC2(p, n, gl##n) +#define OPENGL_PROC2(p, n, tn) if(!(n = (p)wglGetProcAddress(#tn))) ConLog.Error("OpenGL: initialization of " #tn " failed.") + #include "GLProcTable.tbl" +#undef OPENGL_PROC +#undef OPENGL_PROC2 +} + +void OpenGL::Close() +{ +#define OPENGL_PROC(p, n) n = nullptr +#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n) + #include "GLProcTable.tbl" +#undef OPENGL_PROC +#undef OPENGL_PROC2 +} \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/OpenGL.h b/rpcs3/Emu/GS/GL/OpenGL.h index 4c5055ad51..2614038244 100644 --- a/rpcs3/Emu/GS/GL/OpenGL.h +++ b/rpcs3/Emu/GS/GL/OpenGL.h @@ -2,8 +2,27 @@ #include #include "GL/glext.h" -#define OPENGL_PROC(p, n) extern p n -#include "GLProcTable.tbl" -#undef OPENGL_PROC +typedef BOOL (WINAPI* PFNWGLSWAPINTERVALEXTPROC) (int interval); -void InitProcTable(); \ No newline at end of file +#define OPENGL_PROC(p, n) extern p gl##n +#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n) + #include "GLProcTable.tbl" +#undef OPENGL_PROC +#undef OPENGL_PROC2 + +void InitProcTable(); + +struct OpenGL +{ +#define OPENGL_PROC2(p, n, tn) OPENGL_PROC(p, n) +#define OPENGL_PROC(p, n) p n + #include "GLProcTable.tbl" +#undef OPENGL_PROC +#undef OPENGL_PROC2 + + OpenGL(); + ~OpenGL(); + + void Init(); + void Close(); +}; \ No newline at end of file diff --git a/rpcs3/Emu/GS/GL/Program.cpp b/rpcs3/Emu/GS/GL/Program.cpp index 6fa6da6228..bc90e28628 100644 --- a/rpcs3/Emu/GS/GL/Program.cpp +++ b/rpcs3/Emu/GS/GL/Program.cpp @@ -6,6 +6,22 @@ Program::Program() : id(0) { } +int Program::GetLocation(const wxString& name) +{ + for(u32 i=0; i 0; @@ -19,23 +35,6 @@ void Program::Create(const u32 vp, const u32 fp) glAttachShader(id, vp); glAttachShader(id, fp); - glBindFragDataLocation(id, 0, "r0"); - static const wxString reg_table[] = - { - "in_pos", "in_weight", "in_normal", - "in_col0", "in_col1", - "in_fogc", - "in_6", "in_7", - "in_tc0", "in_tc1", "in_tc2", "in_tc3", - "in_tc4", "in_tc5", "in_tc6", "in_tc7" - }; - - for(u32 i=0; i m_locations; + +public: u32 id; Program(); + int GetLocation(const wxString& name); bool IsCreated() const; void Create(const u32 vp, const u32 fp); void Use(); diff --git a/rpcs3/Emu/GS/GL/ProgramBuffer.cpp b/rpcs3/Emu/GS/GL/ProgramBuffer.cpp index 90ca17bc49..ee6a292e73 100644 --- a/rpcs3/Emu/GS/GL/ProgramBuffer.cpp +++ b/rpcs3/Emu/GS/GL/ProgramBuffer.cpp @@ -70,11 +70,9 @@ u32 ProgramBuffer::GetProg(u32 fp, u32 vp) const void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp) { - const u32 pos = m_buf.GetCount(); - m_buf.Add(new BufferInfo()); - BufferInfo& new_buf = m_buf[pos]; + BufferInfo& new_buf = *new BufferInfo(); - ConLog.Write("Add program (%d):", pos); + ConLog.Write("Add program (%d):", m_buf.GetCount()); ConLog.Write("*** prog id = %d", prog.id); ConLog.Write("*** vp id = %d", vp.id); ConLog.Write("*** fp id = %d", fp.id); @@ -88,14 +86,13 @@ void ProgramBuffer::Add(Program& prog, ShaderProgram& fp, VertexProgram& vp) new_buf.vp_id = vp.id; new_buf.fp_id = fp.id; - new_buf.fp_data.SetCount(fp.size); - memcpy(&new_buf.fp_data[0], &Memory[fp.addr], fp.size); - - new_buf.vp_data.SetCount(vp.data.GetCount()); - memcpy(&new_buf.vp_data[0], &vp.data[0], vp.data.GetCount() * 4); + new_buf.fp_data.AddCpy(&Memory[fp.addr], fp.size); + new_buf.vp_data.CopyFrom(vp.data); new_buf.vp_shader = vp.shader; new_buf.fp_shader = fp.shader; + + m_buf.Move(&new_buf); } void ProgramBuffer::Clear() diff --git a/rpcs3/Emu/GS/GL/ShaderParam.h b/rpcs3/Emu/GS/GL/ShaderParam.h index c99679a1a2..f90ba43acc 100644 --- a/rpcs3/Emu/GS/GL/ShaderParam.h +++ b/rpcs3/Emu/GS/GL/ShaderParam.h @@ -9,11 +9,23 @@ enum ParamFlag PARAM_NONE, }; +struct ParamItem +{ + wxString name; + wxString location; + + ParamItem(const wxString& _name, int _location) + : name(_name) + , location(_location > -1 ? wxString::Format("layout (location = %d) ", _location) : "") + { + } +}; + struct ParamType { const ParamFlag flag; wxString type; - wxArrayString names; + Array items; ParamType(const ParamFlag _flag, const wxString& _type) : type(_type) @@ -23,13 +35,29 @@ struct ParamType bool SearchName(const wxString& name) { - for(u32 i=0; iSearchName(name)) t->names.Add(name); + if(!t->SearchName(name)) t->items.Move(new ParamItem(name, location)); } else { const u32 num = params.GetCount(); - params.Add(new ParamType(flag, type)); - params[num].names.Add(name); + params.Move(new ParamType(flag, type)); + params[num].items.Move(new ParamItem(name, location)); } return name; diff --git a/rpcs3/Emu/GS/GL/VertexProgram.cpp b/rpcs3/Emu/GS/GL/VertexProgram.cpp index 861f0c808b..9938ad184f 100644 --- a/rpcs3/Emu/GS/GL/VertexProgram.cpp +++ b/rpcs3/Emu/GS/GL/VertexProgram.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "VertexProgram.h" -wxString VertexDecompilerThread::GetMask() +wxString VertexDecompilerThread::GetVecMask() { wxString ret = wxEmptyString; @@ -13,7 +13,19 @@ wxString VertexDecompilerThread::GetMask() return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); } -wxString VertexDecompilerThread::GetDST() +wxString VertexDecompilerThread::GetScaMask() +{ + wxString ret = wxEmptyString; + + if(d3.sca_writemask_x) ret += "x"; + if(d3.sca_writemask_y) ret += "y"; + if(d3.sca_writemask_z) ret += "z"; + if(d3.sca_writemask_w) ret += "w"; + + return ret.IsEmpty() || ret == "xyzw" ? wxEmptyString : ("." + ret); +} + +wxString VertexDecompilerThread::GetDST(bool isSca) { static const wxString reg_table[] = { @@ -26,11 +38,12 @@ wxString VertexDecompilerThread::GetDST() }; wxString ret = wxEmptyString; + u32 dst = isSca ? d3.sca_dst : d3.dst; - switch(d3.dst) + switch(dst) { case 0x0: case 0x6: - ret += reg_table[d3.dst]; + ret += reg_table[dst]; break; case 0x1f: @@ -38,13 +51,13 @@ wxString VertexDecompilerThread::GetDST() break; default: - if(d3.dst < WXSIZEOF(reg_table)) + if(dst < WXSIZEOF(reg_table)) { - ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[d3.dst]); + ret += m_parr.AddParam(PARAM_OUT, "vec4", reg_table[dst]); } else { - ConLog.Error("Bad dst reg num: %d", d3.dst); + ConLog.Error("Bad dst reg num: %d", dst); ret += m_parr.AddParam(PARAM_OUT, "vec4", "unk"); } break; @@ -53,7 +66,7 @@ wxString VertexDecompilerThread::GetDST() return ret; } -wxString VertexDecompilerThread::GetSRC(const u32 n) +wxString VertexDecompilerThread::GetSRC(const u32 n, bool isSca) { static const wxString reg_table[] = { @@ -75,12 +88,12 @@ wxString VertexDecompilerThread::GetSRC(const u32 n) case 2: //input if(d1.input_src < WXSIZEOF(reg_table)) { - ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[d1.input_src]); + ret += m_parr.AddParam(PARAM_IN, "vec4", reg_table[d1.input_src], d1.input_src); } else { ConLog.Error("Bad input src num: %d", d1.input_src); - ret += m_parr.AddParam(PARAM_IN, "vec4", "in_unk"); + ret += m_parr.AddParam(PARAM_IN, "vec4", "in_unk", d1.input_src); } break; case 3: //const @@ -94,15 +107,27 @@ wxString VertexDecompilerThread::GetSRC(const u32 n) } static const char f[4] = {'x', 'z', 'w', 'y'}; + static const char fSca[4] = {'x', 'z', 'y', 'w'}; wxString swizzle = wxEmptyString; - swizzle += f[src[n].swz_x]; - swizzle += f[src[n].swz_y]; - swizzle += f[src[n].swz_z]; - swizzle += f[src[n].swz_w]; + if (isSca) + { + assert(src[n].swz_x == src[n].swz_y); + assert(src[n].swz_z == src[n].swz_w); + assert(src[n].swz_x == src[n].swz_z); - if(swizzle != "xyzw") ret += "." + swizzle; + ret += "." + fSca[src[n].swz_x]; + } + else + { + swizzle += f[src[n].swz_x]; + swizzle += f[src[n].swz_y]; + swizzle += f[src[n].swz_z]; + swizzle += f[src[n].swz_w]; + + if(swizzle != "xyzw") ret += "." + swizzle; + } bool abs; @@ -119,7 +144,7 @@ wxString VertexDecompilerThread::GetSRC(const u32 n) return ret; } -void VertexDecompilerThread::AddCode(wxString code, bool src_mask) +void VertexDecompilerThread::AddVecCode(wxString code, bool src_mask) { if(d0.cond == 0) return; if(d0.cond != 7) @@ -129,7 +154,22 @@ void VertexDecompilerThread::AddCode(wxString code, bool src_mask) return; } - code = GetDST() + GetMask() + " = " + (src_mask ? code + GetMask() : code); + code = GetDST() + GetVecMask() + " = " + (src_mask ? code + GetVecMask() : code); + + main += "\t" + code + ";\n"; +} + +void VertexDecompilerThread::AddScaCode(wxString code, bool src_mask) +{ + if(d0.cond == 0) return; + if(d0.cond != 7) + { + ConLog.Error("Bad cond! %d", d0.cond); + Emu.Pause(); + return; + } + + code = GetDST(true) + GetScaMask() + " = " + (src_mask ? code + GetScaMask() : code); main += "\t" + code + ";\n"; } @@ -140,17 +180,11 @@ wxString VertexDecompilerThread::BuildCode() for(u32 i=0; iIsAlive()) m_decompiler_thread->Delete(); - safe_delete(m_decompiler_thread); + if(m_decompiler_thread->IsAlive()) + { + m_decompiler_thread->Stop(); + } + + delete m_decompiler_thread; + m_decompiler_thread = nullptr; } Delete(); @@ -237,13 +306,17 @@ void VertexProgram::Decompile() if(m_decompiler_thread) { Wait(); - if(m_decompiler_thread->IsAlive()) m_decompiler_thread->Delete(); - safe_delete(m_decompiler_thread); + if(m_decompiler_thread->IsAlive()) + { + m_decompiler_thread->Stop(); + } + + delete m_decompiler_thread; + m_decompiler_thread = nullptr; } m_decompiler_thread = new VertexDecompilerThread(data, shader, parr); - m_decompiler_thread->Create(); - m_decompiler_thread->Run(); + m_decompiler_thread->Start(); #endif } @@ -272,7 +345,7 @@ void VertexProgram::Compile() memset(buf, 0, r+1); glGetShaderInfoLog(id, r, &len, buf); ConLog.Error("Failed to compile vertex shader: %s", buf); - free(buf); + delete[] buf; } ConLog.Write(shader); @@ -287,7 +360,7 @@ void VertexProgram::Delete() data.Clear(); for(u32 i=0; i& data, wxString& shader, ParamArray& parr) - : wxThread(wxTHREAD_JOINABLE) + : ThreadBase(false, "Vertex Shader Decompiler Thread") , m_data(data) , m_shader(shader) , m_parr(parr) { } - wxString GetMask(); - wxString GetDST(); - wxString GetSRC(const u32 n); - void AddCode(wxString code, bool src_mask = true); + wxString GetVecMask(); + wxString GetScaMask(); + wxString GetDST(bool isSca = false); + wxString GetSRC(const u32 n, bool isSca = false); + void AddVecCode(wxString code, bool src_mask = true); + void AddScaCode(wxString code, bool src_mask = true); wxString BuildCode(); - ExitCode Entry(); + virtual void Task(); }; struct VertexProgram @@ -149,7 +151,13 @@ struct VertexProgram Array data; ParamArray parr; - void Wait() { if(m_decompiler_thread && m_decompiler_thread->IsRunning()) m_decompiler_thread->Wait(); } + void Wait() + { + if(m_decompiler_thread && m_decompiler_thread->IsRunning()) + { + m_decompiler_thread->Wait(); + } + } void Decompile(); void Compile(); void Delete(); diff --git a/rpcs3/Emu/GS/GSManager.cpp b/rpcs3/Emu/GS/GSManager.cpp index 314f09ce73..7f9b2f1e07 100644 --- a/rpcs3/Emu/GS/GSManager.cpp +++ b/rpcs3/Emu/GS/GSManager.cpp @@ -15,6 +15,9 @@ GSManager::GSManager() : m_render(NULL) void GSManager::Init() { if(m_render) return; + + m_info.Init(); + switch(Ini.GSRenderMode.GetValue()) { default: @@ -29,9 +32,8 @@ void GSManager::Close() if(m_render) { m_render->Close(); - //free(m_render); + m_render = nullptr; } - m_render = NULL; } u8 GSManager::GetState() diff --git a/rpcs3/Emu/GS/GSManager.h b/rpcs3/Emu/GS/GSManager.h index 28ef38f34f..bac7ce4233 100644 --- a/rpcs3/Emu/GS/GSManager.h +++ b/rpcs3/Emu/GS/GSManager.h @@ -4,19 +4,31 @@ struct GSInfo { - CellVideoOutResolution outresolution; - CellVideoOutDisplayMode mode; + struct + { + u8 resolutionId; + u8 scanMode; + u8 conversion; + u8 aspect; + u8 format; + u16 refreshRates; + u32 pitch; + } mode; + //CellVideoOutDisplayMode mode; GSInfo() { - outresolution.width = 740; - outresolution.height = 480; + } - mode.resolutionId = CELL_VIDEO_OUT_RESOLUTION_576; + void Init() + { + mode.resolutionId = Ini.GSResolution.GetValue(); mode.scanMode = CELL_VIDEO_OUT_SCAN_MODE_INTERLACE; mode.conversion = CELL_VIDEO_OUT_DISPLAY_CONVERSION_NONE; - mode.aspect = CELL_VIDEO_OUT_ASPECT_4_3; + mode.aspect = Ini.GSAspectRatio.GetValue(); mode.refreshRates = CELL_VIDEO_OUT_REFRESH_RATE_50HZ; + mode.format = CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8; + mode.pitch = 4; } }; @@ -47,7 +59,7 @@ public: void Close(); GSInfo& GetInfo() { return m_info; } - GSRender& GetRender() { return *m_render; } + GSRender& GetRender() { assert(m_render); return *m_render; } u8 GetState(); u8 GetColorSpace(); diff --git a/rpcs3/Emu/GS/GSRender.cpp b/rpcs3/Emu/GS/GSRender.cpp index 4ba5bb97f8..3055b66733 100644 --- a/rpcs3/Emu/GS/GSRender.cpp +++ b/rpcs3/Emu/GS/GSRender.cpp @@ -21,10 +21,10 @@ wxSize AspectRatio(wxSize rs, const wxSize as) GSFrame::GSFrame(wxWindow* parent, const wxString& title) : wxFrame(parent, wxID_ANY, title) { - SetClientSize(720, 576); - //Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GSFrame::OnLeftDclick)); + CellVideoOutResolution res = ResolutionTable[ResolutionIdToNum(Ini.GSResolution.GetValue())]; + SetClientSize(res.width, res.height); wxGetApp().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(GSFrame::OnKeyDown), (wxObject*)0, this); - wxGetApp().Connect(GetId(), wxEVT_CLOSE_WINDOW, wxCloseEventHandler(GSFrame::OnClose), (wxObject*)0, this); + Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(GSFrame::OnClose)); } void GSFrame::OnPaint(wxPaintEvent& event) @@ -54,7 +54,7 @@ void GSFrame::OnKeyDown(wxKeyEvent& event) { switch(event.GetKeyCode()) { - case WXK_RETURN: if(event.ControlDown()) { OnFullScreen(); return; } break; + case WXK_RETURN: if(event.AltDown()) { OnFullScreen(); return; } break; case WXK_ESCAPE: if(IsFullScreen()) { ShowFullScreen(false); return; } break; } event.Skip(); @@ -79,7 +79,8 @@ void GSFrame::SetSize(int width, int height) GSRender::GSRender() : m_ctrl(NULL) - , m_flip_status(-1) + , m_flip_status(0) + , m_flip_mode(CELL_GCM_DISPLAY_VSYNC) { } @@ -91,4 +92,8 @@ u32 GSRender::GetAddress(u32 offset, u8 location) case CELL_GCM_LOCATION_MAIN: return offset; } return 0; +} + +GSLockCurrent::GSLockCurrent(GSLockType type) : GSLock(Emu.GetGSManager().GetRender(), type) +{ } \ No newline at end of file diff --git a/rpcs3/Emu/GS/GSRender.h b/rpcs3/Emu/GS/GSRender.h index 5c81926545..86c05ece7b 100644 --- a/rpcs3/Emu/GS/GSRender.h +++ b/rpcs3/Emu/GS/GSRender.h @@ -1,6 +1,15 @@ #pragma once #include "Emu/GS/GCM.h" +enum Method +{ + CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000, + CELL_GCM_METHOD_FLAG_JUMP = 0x20000000, + CELL_GCM_METHOD_FLAG_CALL = 0x00000002, + CELL_GCM_METHOD_FLAG_RETURN = 0x00020000, +}; + + wxSize AspectRatio(wxSize rs, const wxSize as); class GSFrame : public wxFrame @@ -14,15 +23,15 @@ protected: //virtual void OnSize(wxSizeEvent&); + void OnKeyDown(wxKeyEvent& event); + void OnFullScreen(); + +public: void OnLeftDclick(wxMouseEvent&) { OnFullScreen(); } - void OnKeyDown(wxKeyEvent& event); - void OnFullScreen(); - -public: //void SetSize(int width, int height); private: @@ -33,15 +42,60 @@ struct GSRender { u32 m_ioAddress, m_ioSize, m_ctrlAddress, m_localAddress; CellGcmControl* m_ctrl; + wxCriticalSection m_cs_main; + wxSemaphore m_sem_flush; + wxSemaphore m_sem_flip; int m_flip_status; + int m_flip_mode; + volatile bool m_draw; GSRender(); virtual void Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)=0; virtual void Draw()=0; virtual void Close()=0; - virtual void Pause()=0; - virtual void Resume()=0; u32 GetAddress(u32 offset, u8 location); +}; + +enum GSLockType +{ + GS_LOCK_NOT_WAIT, + GS_LOCK_WAIT_FLUSH, + GS_LOCK_WAIT_FLIP, +}; + +struct GSLock +{ +private: + GSRender& m_renderer; + GSLockType m_type; + +public: + GSLock(GSRender& renderer, GSLockType type) + : m_renderer(renderer) + , m_type(type) + { + switch(m_type) + { + case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Enter(); break; + case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Wait(); break; + case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Wait(); break; + } + } + + ~GSLock() + { + switch(m_type) + { + case GS_LOCK_NOT_WAIT: m_renderer.m_cs_main.Leave(); break; + case GS_LOCK_WAIT_FLUSH: m_renderer.m_sem_flush.Post(); break; + case GS_LOCK_WAIT_FLIP: m_renderer.m_sem_flip.Post(); break; + } + } +}; + +struct GSLockCurrent : GSLock +{ + GSLockCurrent(GSLockType type); }; \ No newline at end of file diff --git a/rpcs3/Emu/GS/Null/NullGSRender.h b/rpcs3/Emu/GS/Null/NullGSRender.h index 32ba3aa938..d9c9443b1a 100644 --- a/rpcs3/Emu/GS/Null/NullGSRender.h +++ b/rpcs3/Emu/GS/Null/NullGSRender.h @@ -5,6 +5,7 @@ struct NullGSFrame : public GSFrame { NullGSFrame() : GSFrame(NULL, "GSFrame[Null]") { + Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler(GSFrame::OnLeftDclick)); } void Draw() { Draw(wxClientDC(this)); } @@ -23,22 +24,33 @@ private: } }; +struct NullRSXThread : public wxThread +{ + wxWindow* m_parent; + Stack call_stack; + + NullRSXThread(wxWindow* parent); + + virtual void OnExit(); + void Start(); + ExitCode Entry(); +}; + class NullGSRender : public wxWindow , public GSRender { private: - NullGSFrame* m_frame; - wxTimer* m_update_timer; - bool m_paused; + NullRSXThread* m_rsx_thread; public: + NullGSFrame* m_frame; + NullGSRender() - : m_frame(NULL) - , m_paused(false) + : m_frame(nullptr) + , m_rsx_thread(nullptr) { - m_update_timer = new wxTimer(this); - Connect(m_update_timer->GetId(), wxEVT_TIMER, wxTimerEventHandler(NullGSRender::OnTimer)); + m_draw = false; m_frame = new NullGSFrame(); } @@ -62,24 +74,10 @@ private: m_localAddress = localAddress; m_ctrl = (CellGcmControl*)Memory.GetMemFromAddr(m_ctrlAddress); - m_update_timer->Start(1); - } - - void OnTimer(wxTimerEvent&) - { - while(!m_paused && m_ctrl->get != m_ctrl->put && Emu.IsRunned()) - { - const u32 get = re(m_ctrl->get); - const u32 cmd = Memory.Read32(m_ioAddress + get); - const u32 count = (cmd >> 18) & 0x7ff; - mem32_t data(m_ioAddress + get + 4); - - m_ctrl->get = re32(get + (count + 1) * 4); - DoCmd(cmd, cmd & 0x3ffff, data, count); - memset(Memory.GetMemFromAddr(m_ioAddress + get), 0, (count + 1) * 4); - } + (m_rsx_thread = new NullRSXThread(this))->Start(); } +public: void DoCmd(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count) { switch(cmd) @@ -87,32 +85,107 @@ private: case NV406E_SET_REFERENCE: m_ctrl->ref = re32(args[0]); break; - - case NV4097_SET_BEGIN_END: - if(!args[0]) m_flip_status = 0; - break; } } virtual void Draw() { //if(m_frame && !m_frame->IsBeingDeleted()) m_frame->Draw(); + m_draw = true; } virtual void Close() { - m_update_timer->Stop(); + if(m_rsx_thread) m_rsx_thread->Delete(); if(m_frame->IsShown()) m_frame->Hide(); m_ctrl = NULL; } +}; - void Pause() +NullRSXThread::NullRSXThread(wxWindow* parent) + : wxThread(wxTHREAD_DETACHED) + , m_parent(parent) +{ +} + +void NullRSXThread::OnExit() +{ + call_stack.Clear(); +} + +void NullRSXThread::Start() +{ + Create(); + Run(); +} + +wxThread::ExitCode NullRSXThread::Entry() +{ + ConLog.Write("Null RSX thread entry"); + + NullGSRender& p = *(NullGSRender*)m_parent; + + while(!TestDestroy() && p.m_frame && !p.m_frame->IsBeingDeleted()) { - m_paused = true; + wxCriticalSectionLocker lock(p.m_cs_main); + + if(p.m_ctrl->get == p.m_ctrl->put || !Emu.IsRunned()) + { + SemaphorePostAndWait(p.m_sem_flush); + + if(p.m_draw) + { + p.m_draw = false; + p.m_flip_status = 0; + if(SemaphorePostAndWait(p.m_sem_flip)) continue; + } + + Sleep(1); + continue; + } + + const u32 get = re(p.m_ctrl->get); + const u32 cmd = Memory.Read32(p.m_ioAddress + get); + const u32 count = (cmd >> 18) & 0x7ff; + + if(cmd & CELL_GCM_METHOD_FLAG_JUMP) + { + p.m_ctrl->get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT)); + ConLog.Warning("rsx jump!"); + continue; + } + if(cmd & CELL_GCM_METHOD_FLAG_CALL) + { + call_stack.Push(get + 4); + p.m_ctrl->get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL); + ConLog.Warning("rsx call!"); + continue; + } + if(cmd & CELL_GCM_METHOD_FLAG_RETURN) + { + p.m_ctrl->get = re32(call_stack.Pop()); + ConLog.Warning("rsx return!"); + continue; + } + if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) + { + //ConLog.Warning("non increment cmd! 0x%x", cmd); + } + + if(cmd == 0) + { + ConLog.Warning("null cmd: addr=0x%x, put=0x%x, get=0x%x", p.m_ioAddress + get, re(p.m_ctrl->put), get); + Emu.Pause(); + continue; + } + + p.DoCmd(cmd, cmd & 0x3ffff, mem32_t(p.m_ioAddress + get + 4), count); + re(p.m_ctrl->get, get + (count + 1) * 4); } - void Resume() - { - m_paused = false; - } -}; \ No newline at end of file + ConLog.Write("Null RSX thread exit..."); + + call_stack.Clear(); + + return (ExitCode)0; +} \ No newline at end of file diff --git a/rpcs3/Emu/GS/RSXThread.cpp b/rpcs3/Emu/GS/RSXThread.cpp index 83ff3eaac5..910a7ed0e4 100644 --- a/rpcs3/Emu/GS/RSXThread.cpp +++ b/rpcs3/Emu/GS/RSXThread.cpp @@ -1,81 +1,14 @@ #include "stdafx.h" #include "RSXThread.h" -enum MethodFlag -{ - CELL_GCM_METHOD_FLAG_NON_INCREMENT = 0x40000000, - CELL_GCM_METHOD_FLAG_JUMP = 0x20000000, - CELL_GCM_METHOD_FLAG_CALL = 0x00000002, - CELL_GCM_METHOD_FLAG_RETURN = 0x00020000, -}; - -RSXThread::RSXThread( - CellGcmControl* ctrl, - u32 ioAddress, - void (&cmd)(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count), - bool (&_flip)(), - bool (&_TestExit)() - ) +RSXThread::RSXThread(CellGcmControl* ctrl, u32 ioAddress) : m_ctrl(*ctrl) , m_ioAddress(ioAddress) - , DoCmd(cmd) - , flip(_flip) - , TestExit(_TestExit) { } void RSXThread::Task() { - while(!TestDestroy() && !TestExit()) - { - if(m_ctrl.get == m_ctrl.put) - { - flip(); - - Sleep(1); - continue; - } - - const u32 get = re(m_ctrl.get); - const u32 cmd = Memory.Read32(m_ioAddress + get); - const u32 count = (cmd >> 18) & 0x7ff; - mem32_t data(m_ioAddress + get + 4); - - if(cmd & CELL_GCM_METHOD_FLAG_JUMP) - { - m_ctrl.get = re32(cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT)); - continue; - } - if(cmd & CELL_GCM_METHOD_FLAG_CALL) - { - call_stack.AddCpy(get + 4); - m_ctrl.get = re32(cmd & ~CELL_GCM_METHOD_FLAG_CALL); - continue; - } - if(cmd & CELL_GCM_METHOD_FLAG_RETURN) - { - const u32 pos = call_stack.GetCount() - 1; - m_ctrl.get = re32(call_stack[pos]); - call_stack.RemoveAt(pos); - continue; - } - if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) - { - //ConLog.Warning("non increment cmd! 0x%x", cmd); - } - -#if 0 - wxString debug = getMethodName(cmd & 0x3ffff); - debug += "("; - for(u32 i=0; i call_stack; - void (&DoCmd)(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count); - bool (&flip)(); - bool (&TestExit)(); CellGcmControl& m_ctrl; u32 m_ioAddress; protected: - RSXThread( - CellGcmControl* ctrl, - u32 ioAddress, - void (&cmd)(const u32 fcmd, const u32 cmd, mem32_t& args, const u32 count), - bool (&_flip)(), - bool (&_TestExit)() - ); + RSXThread(CellGcmControl* ctrl, u32 ioAddress); private: virtual void Task(); diff --git a/rpcs3/Emu/GS/sysutil_video.h b/rpcs3/Emu/GS/sysutil_video.h index 139bd03800..a1a0d4c920 100644 --- a/rpcs3/Emu/GS/sysutil_video.h +++ b/rpcs3/Emu/GS/sysutil_video.h @@ -14,7 +14,6 @@ enum VideoErrorCode CELL_VIDEO_OUT_ERROR_VALUE_IS_NOT_SET = 0x8002b228, }; - enum CellVideoOut { CELL_VIDEO_OUT_PRIMARY, @@ -166,22 +165,22 @@ struct CellVideoOutDisplayMode struct CellVideoOutResolution { - u16 width; - u16 height; + u16 width; + u16 height; }; struct CellVideoOutDeviceInfo { - u8 portType; - u8 colorSpace; - u16 latency; - u8 availableModeCount; - u8 state; - u8 rgbOutputRange; - u8 reserved[5]; - CellVideoOutColorInfo colorInfo; - CellVideoOutDisplayMode availableModes[32]; - CellVideoOutKSVList ksvList; + u8 portType; + u8 colorSpace; + u16 latency; + u8 availableModeCount; + u8 state; + u8 rgbOutputRange; + u8 reserved[5]; + CellVideoOutColorInfo colorInfo; + CellVideoOutDisplayMode availableModes[32]; + CellVideoOutKSVList ksvList; }; struct CellVideoOutState @@ -194,11 +193,11 @@ struct CellVideoOutState struct CellVideoOutConfiguration { - u8 resolutionId; - u8 format; - u8 aspect; - u8 reserved[9]; - u32 pitch; + u8 resolutionId; + u8 format; + u8 aspect; + u8 reserved[9]; + u32 pitch; }; enum CellVideoOutEvent @@ -220,4 +219,58 @@ enum CellVideoOutRGBOutputRange { CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_LIMITED, CELL_VIDEO_OUT_RGB_OUTPUT_RANGE_FULL, -}; \ No newline at end of file +}; + +static const CellVideoOutResolution ResolutionTable[] = +{ + {-1, -1}, //0 - 0 + {1920, 1080}, //1 - 1 + {1280, 720}, //2 - 2 + {720, 480}, //4 - 3 + {720, 576}, //5 - 4 + {1600, 1080}, //10 - 5 + {1440, 1080}, //11 - 6 + {1280, 1080}, //12 - 7 + {960, 1080}, //13 - 8 +}; + +inline static u32 ResolutionIdToNum(u32 id) +{ + static const u32 res[] = + { + 0, //0 + 1, //1 + 2, //2 + 0, //3 + 3, //4 + 4, //5 + 0, //6 + 0, //7 + 0, //8 + 0, //9 + 5, //10 + 6, //11 + 7, //12 + 8, //13 + }; + + return id <= 13 ? res[id] : 0; +} + +inline static u32 ResolutionNumToId(u32 num) +{ + static const u32 res[] = + { + 0, + 1, + 2, + 4, + 5, + 10, + 11, + 12, + 13, + }; + + return num <= 8 ? res[num] : 0; +} \ No newline at end of file diff --git a/rpcs3/Emu/Io/Windows/WindowsPadHandler.h b/rpcs3/Emu/Io/Windows/WindowsPadHandler.h index b450eed2c9..c7a8c9743e 100644 --- a/rpcs3/Emu/Io/Windows/WindowsPadHandler.h +++ b/rpcs3/Emu/Io/Windows/WindowsPadHandler.h @@ -6,11 +6,13 @@ class WindowsPadHandler : public wxWindow , public PadHandlerBase { + AppConnector m_app_connector; + public: WindowsPadHandler() : wxWindow() { - wxGetApp().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(WindowsPadHandler::KeyDown), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_KEY_UP, wxKeyEventHandler(WindowsPadHandler::KeyUp), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(WindowsPadHandler::KeyDown), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_KEY_UP, wxKeyEventHandler(WindowsPadHandler::KeyUp), (wxObject*)0, this); } virtual void KeyDown(wxKeyEvent& event) { Key(event.GetKeyCode(), 1); event.Skip(); } @@ -32,27 +34,27 @@ public: void LoadSettings() { - m_pads.Add(new Pad( + m_pads.Move(new Pad( CELL_PAD_STATUS_CONNECTED, CELL_PAD_SETTING_PRESS_ON | CELL_PAD_SETTING_SENSOR_OFF, CELL_PAD_CAPABILITY_PS3_CONFORMITY | CELL_PAD_CAPABILITY_PRESS_MODE, CELL_PAD_DEV_TYPE_STANDARD)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'A', CELL_PAD_CTRL_LEFT)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'S', CELL_PAD_CTRL_DOWN)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'D', CELL_PAD_CTRL_RIGHT)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'W', CELL_PAD_CTRL_UP)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, WXK_RETURN, CELL_PAD_CTRL_START)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'X', CELL_PAD_CTRL_R3)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'Z', CELL_PAD_CTRL_L3)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, WXK_SPACE, CELL_PAD_CTRL_SELECT)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'A', CELL_PAD_CTRL_LEFT)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'S', CELL_PAD_CTRL_DOWN)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'D', CELL_PAD_CTRL_RIGHT)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'W', CELL_PAD_CTRL_UP)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, WXK_RETURN, CELL_PAD_CTRL_START)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'X', CELL_PAD_CTRL_R3)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, 'Z', CELL_PAD_CTRL_L3)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL1, WXK_SPACE, CELL_PAD_CTRL_SELECT)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'K', CELL_PAD_CTRL_SQUARE)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'L', CELL_PAD_CTRL_CROSS)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, ';', CELL_PAD_CTRL_CIRCLE)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'O', CELL_PAD_CTRL_TRIANGLE)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'I', CELL_PAD_CTRL_R1)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'Q', CELL_PAD_CTRL_L1)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'P', CELL_PAD_CTRL_R2)); - m_pads[0].m_buttons.Add(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'E', CELL_PAD_CTRL_L2)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'K', CELL_PAD_CTRL_SQUARE)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'L', CELL_PAD_CTRL_CROSS)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, ';', CELL_PAD_CTRL_CIRCLE)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'O', CELL_PAD_CTRL_TRIANGLE)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'I', CELL_PAD_CTRL_R1)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'Q', CELL_PAD_CTRL_L1)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'P', CELL_PAD_CTRL_R2)); + m_pads[0].m_buttons.Move(new Button(CELL_PAD_BTN_OFFSET_DIGITAL2, 'E', CELL_PAD_CTRL_L2)); } }; \ No newline at end of file diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index be3bb49802..0c08be11b7 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -20,13 +20,15 @@ void MemoryBlock::Init() range_start = 0; range_size = 0; - mem = NULL; + mem = nullptr; } void MemoryBlock::InitMemory() { + if(!range_size) return; + safe_delete(mem); - mem = new u8[range_size]; + mem = (u8*)malloc(range_size); memset(mem, 0, range_size); } @@ -43,32 +45,36 @@ u64 MemoryBlock::FixAddr(const u64 addr) const bool MemoryBlock::GetMemFromAddr(void* dst, const u64 addr, const u32 size) { - if(!IsMyAddress(addr)) return false; - if(FixAddr(addr) + size > GetSize()) return false; - memcpy(dst, &mem[FixAddr(addr)], size); + if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false; + + memcpy(dst, GetMem(FixAddr(addr)), size); + return true; } bool MemoryBlock::SetMemFromAddr(void* src, const u64 addr, const u32 size) { - if(!IsMyAddress(addr)) return false; - if(FixAddr(addr) + size > GetSize()) return false; - memcpy(&mem[FixAddr(addr)], src, size); + if(!IsMyAddress(addr) || FixAddr(addr) + size > GetSize()) return false; + + memcpy(GetMem(FixAddr(addr)), src, size); + return true; } bool MemoryBlock::GetMemFFromAddr(void* dst, const u64 addr) { if(!IsMyAddress(addr)) return false; - dst = &mem[FixAddr(addr)]; + + dst = GetMem(FixAddr(addr)); + return true; } u8* MemoryBlock::GetMemFromAddr(const u64 addr) { - if(!IsMyAddress(addr)) return NULL; + if(!IsMyAddress(addr) || IsNULL()) return nullptr; - return &mem[FixAddr(addr)]; + return GetMem(FixAddr(addr)); } MemoryBlock* MemoryBlock::SetRange(const u64 start, const u32 size) @@ -80,24 +86,6 @@ MemoryBlock* MemoryBlock::SetRange(const u64 start, const u32 size) return this; } -bool MemoryBlock::SetNewSize(const u32 size) -{ - if(range_size >= size) return false; - - u8* new_mem = (u8*)realloc(mem, size); - if(!new_mem) - { - ConLog.Error("Not enought free memory"); - Emu.Pause(); - return false; - } - - mem = new_mem; - range_size = size; - - return true; -} - bool MemoryBlock::IsMyAddress(const u64 addr) { return addr >= GetStartAddr() && addr < GetEndAddr(); @@ -105,7 +93,7 @@ bool MemoryBlock::IsMyAddress(const u64 addr) __forceinline const u8 MemoryBlock::FastRead8(const u64 addr) const { - return mem[addr]; + return *GetMem(addr); } __forceinline const u16 MemoryBlock::FastRead16(const u64 addr) const @@ -126,8 +114,8 @@ __forceinline const u64 MemoryBlock::FastRead64(const u64 addr) const __forceinline const u128 MemoryBlock::FastRead128(const u64 addr) { u128 ret; - ret.hi = FastRead64(addr); - ret.lo = FastRead64(addr + 8); + ret.lo = FastRead64(addr); + ret.hi = FastRead64(addr + 8); return ret; } @@ -193,7 +181,7 @@ bool MemoryBlock::Read128(const u64 addr, u128* value) __forceinline void MemoryBlock::FastWrite8(const u64 addr, const u8 value) { - mem[addr] = value; + *GetMem(addr) = value; } __forceinline void MemoryBlock::FastWrite16(const u64 addr, const u16 value) @@ -216,8 +204,8 @@ __forceinline void MemoryBlock::FastWrite64(const u64 addr, const u64 value) __forceinline void MemoryBlock::FastWrite128(const u64 addr, const u128 value) { - FastWrite64(addr, value.hi); - FastWrite64(addr+8, value.lo); + FastWrite64(addr, value.lo); + FastWrite64(addr+8, value.hi); } bool MemoryBlock::Write8(const u64 addr, const u8 value) @@ -332,11 +320,22 @@ bool NullMemoryBlock::Write128(const u64 addr, const u128 value) } //DynamicMemoryBlock -DynamicMemoryBlock::DynamicMemoryBlock() : m_point(0) - , m_max_size(0) +DynamicMemoryBlock::DynamicMemoryBlock() : m_max_size(0) { } +const u32 DynamicMemoryBlock::GetUsedSize() const +{ + u32 size = 0; + + for(u32 i=0; i= GetStartAddr() && addr < GetStartAddr() + GetSize(); @@ -363,8 +362,7 @@ bool DynamicMemoryBlock::IsMyAddress(const u64 addr) MemoryBlock* DynamicMemoryBlock::SetRange(const u64 start, const u32 size) { m_max_size = size; - MemoryBlock::SetRange(start, 4); - m_point = GetStartAddr(); + MemoryBlock::SetRange(start, 0); return this; } @@ -372,146 +370,64 @@ MemoryBlock* DynamicMemoryBlock::SetRange(const u64 start, const u32 size) void DynamicMemoryBlock::Delete() { m_used_mem.Clear(); - m_free_mem.Clear(); - m_point = 0; m_max_size = 0; MemoryBlock::Delete(); } -void DynamicMemoryBlock::UpdateSize(u64 addr, u32 size) -{ - u32 used_size = addr + size - GetStartAddr(); - if(used_size > GetUsedSize()) SetNewSize(used_size); -} - -void DynamicMemoryBlock::CombineFreeMem() -{ - if(m_free_mem.GetCount() < 2) return; - - for(u32 i1=0; i1 m_point) + for(u32 i=0; i= free_mem_addr && m_free_mem[i].addr < addr) - { - free_mem_addr = m_free_mem[i].addr + m_free_mem[i].size; - } - } - - for(u32 i=0; i= free_mem_addr && m_used_mem[i].addr < addr) - { - free_mem_addr = m_used_mem[i].addr + m_used_mem[i].size; - } - } - - m_free_mem.AddCpy(MemBlockInfo(free_mem_addr, addr - GetStartAddr())); - } - - UpdateSize(addr, size); - - m_used_mem.AddCpy(MemBlockInfo(addr, size)); - memset(mem + (addr - GetStartAddr()), 0, size); - - m_point = addr + size; - - return true; + if(addr >= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) return false; } - for(u32 i=0; i= m_free_mem[i].addr + m_free_mem[i].size - || m_free_mem[i].size < size) continue; + AppendUsedMem(addr, size); - if(m_free_mem[i].addr != addr) - { - m_free_mem.AddCpy(MemBlockInfo(m_free_mem[i].addr, addr - m_free_mem[i].addr)); - } + return true; +} - if(m_free_mem[i].size != size) - { - m_free_mem.AddCpy(MemBlockInfo(m_free_mem[i].addr + size, m_free_mem[i].size - size)); - } - - m_free_mem.RemoveAt(i); - m_used_mem.AddCpy(MemBlockInfo(addr, size)); - - memset(mem + (addr - GetStartAddr()), 0, size); - return true; - } - - return false; +void DynamicMemoryBlock::AppendUsedMem(u64 addr, u32 size) +{ + m_used_mem.Move(new MemBlockInfo(addr, size)); } u64 DynamicMemoryBlock::Alloc(u32 size) { - for(u32 i=0; i= m_used_mem[i].addr && addr < m_used_mem[i].addr + m_used_mem[i].size) || + (m_used_mem[i].addr >= addr && m_used_mem[i].addr < addr + size)) + { + is_good_addr = false; + addr = m_used_mem[i].addr + m_used_mem[i].size; + break; + } } - m_free_mem.RemoveAt(i); - m_used_mem.AddCpy(MemBlockInfo(addr, size)); + if(!is_good_addr) continue; + + AppendUsedMem(addr, size); - memset(mem + (addr - GetStartAddr()), 0, size); return addr; } - UpdateSize(m_point, size); - - MemBlockInfo res(m_point, size); - m_used_mem.AddCpy(res); - memset(mem + (m_point - GetStartAddr()), 0, size); - - m_point += size; - - return res.addr; + return 0; } bool DynamicMemoryBlock::Alloc() @@ -520,14 +436,12 @@ bool DynamicMemoryBlock::Alloc() } bool DynamicMemoryBlock::Free(u64 addr) -{ +{ for(u32 i=0; i= _addr && addr < _addr + m_used_mem[i].size) + { + return (u8*)m_used_mem[i].mem + addr - _addr; + } + } + + ConLog.Error("GetMem(%llx) from not allocated address.", addr); + assert(0); + return nullptr; +} + //MemoryBase void MemoryBase::Write8(u64 addr, const u8 data) { diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index ac49500875..5fdcaa0b8f 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -1,44 +1,6 @@ #pragma once #include "MemoryBlock.h" -class MemoryFlags -{ - struct Flag - { - const u64 addr; - const u64 waddr; - const u64 fid; - - Flag(const u64 _addr, const u64 _waddr, const u64 _fid) - : addr(_addr) - , waddr(_waddr) - , fid(_fid) - { - } - }; - - Array m_memflags; - -public: - void Add(const u64 addr, const u64 waddr, const u64 fid) {m_memflags.Add(new Flag(addr, waddr, fid));} - void Clear() { m_memflags.Clear(); } - - bool IsFlag(const u64 addr, u64& waddr, u64& fid) - { - for(u32 i=0; i> 8) & 0xff) | ((val << 8) & 0xff00); + return _byteswap_ushort(val); + //return ((val >> 8) & 0xff) | ((val << 8) & 0xff00); } - static u32 Reverse32(const u32 val) + static __forceinline u32 Reverse32(const u32 val) { + return _byteswap_ulong(val); + /* return ((val >> 24) & 0x000000ff) | ((val >> 8) & 0x0000ff00) | ((val << 8) & 0x00ff0000) | ((val << 24) & 0xff000000); + */ } - static u64 Reverse64(const u64 val) + static __forceinline u64 Reverse64(const u64 val) { + return _byteswap_uint64(val); + /* return ((val >> 56) & 0x00000000000000ff) | ((val >> 40) & 0x000000000000ff00) | @@ -94,19 +60,19 @@ public: ((val << 24) & 0x0000ff0000000000) | ((val << 40) & 0x00ff000000000000) | ((val << 56) & 0xff00000000000000); + */ } - template static T Reverse(T val) - { - switch(sizeof(T)) - { - case 2: return Reverse16(val); - case 4: return Reverse32(val); - case 8: return Reverse64(val); - } + template static __forceinline T Reverse(T val); + template<> static __forceinline u8 Reverse(u8 val) { return val; }; + template<> static __forceinline u16 Reverse(u16 val) { return Reverse16(val); }; + template<> static __forceinline u32 Reverse(u32 val) { return Reverse32(val); }; + template<> static __forceinline u64 Reverse(u64 val) { return Reverse64(val); }; - return val; - } + template<> static __forceinline s8 Reverse(s8 val) { return val; }; + template<> static __forceinline s16 Reverse(s16 val) { return Reverse16(val); }; + template<> static __forceinline s32 Reverse(s32 val) { return Reverse32(val); }; + template<> static __forceinline s64 Reverse(s64 val) { return Reverse64(val); }; MemoryBlock& GetMemByNum(const u8 num) { @@ -170,7 +136,7 @@ public: MemoryBlocks.Add(MainMem.SetRange(0x00010000, 0x2FFF0000)); MemoryBlocks.Add(PRXMem.SetRange(0x30000000, 0x10000000)); MemoryBlocks.Add(RSXCMDMem.SetRange(0x40000000, 0x10000000)); - //MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000)); + MemoryBlocks.Add(MmaperMem.SetRange(0xB0000000, 0x10000000)); MemoryBlocks.Add(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.Add(StackMem.SetRange(0xD0000000, 0x10000000)); //MemoryBlocks.Add(SpuRawMem.SetRange(0xE0000000, 0x10000000)); @@ -213,7 +179,6 @@ public: } MemoryBlocks.Clear(); - MemFlags.Clear(); } void Reset() @@ -243,6 +208,66 @@ public: u64 Read64(const u64 addr); u128 Read128(const u64 addr); + void ReadLeft(u8* dst, const u64 addr, const u32 size) + { + MemoryBlock& mem = GetMemByAddr(addr); + + if(mem.IsNULL()) + { + ConLog.Error("ReadLeft[%d] from null block (0x%llx)", size, addr); + return; + } + + u32 offs = mem.FixAddr(addr); + + for(u32 i=0; i void WriteData(const u64 addr, const T* data) { memcpy(GetMemFromAddr(addr), data, sizeof(T)); @@ -264,26 +289,18 @@ public: wxString ReadString(const u64 addr) { - wxString buf = wxEmptyString; - - for(u32 i=addr; ; i++) - { - const u8 c = Read8(i); - if(c == 0) break; - buf += c; - } - - return buf; + return wxString((const char*)GetMemFromAddr(addr)); } void WriteString(const u64 addr, const wxString& str) { - for(u32 i=0; i m_used_mem; - Array m_free_mem; - u64 m_point; u32 m_max_size; public: DynamicMemoryBlock(); const u32 GetSize() const { return m_max_size; } - const u32 GetUsedSize() const { return range_size; } + const u32 GetUsedSize() const; bool IsInMyRange(const u64 addr); bool IsInMyRange(const u64 addr, const u32 size); @@ -112,11 +125,13 @@ public: virtual void Delete(); - void UpdateSize(u64 addr, u32 size); - void CombineFreeMem(); - bool Alloc(u64 addr, u32 size); u64 Alloc(u32 size); bool Alloc(); bool Free(u64 addr); + + virtual u8* GetMem(u64 addr) const; + +private: + void AppendUsedMem(u64 addr, u32 size); }; diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp new file mode 100644 index 0000000000..e9e98593e2 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -0,0 +1,66 @@ +#include "stdafx.h" +#include "Callback.h" + +#include "Emu/Cell/PPCThread.h" + +Callback::Callback(u32 slot, u64 addr) + : m_addr(addr) + , m_slot(slot) + , a1(0) + , a2(0) + , a3(0) + , m_has_data(false) +{ +} + +void Callback::Handle(u64 _a1, u64 _a2, u64 _a3) +{ + a1 = _a1; + a2 = _a2; + a3 = _a3; + m_has_data = true; +} + +void Callback::Branch() +{ + m_has_data = false; + + PPCThread& new_thread = Emu.GetCPU().AddThread(true); + + new_thread.SetPc(m_addr); + new_thread.SetPrio(0x1001); + new_thread.stack_size = 0x10000; + new_thread.SetName("Callback"); + new_thread.Run(); + + ((PPUThread&)new_thread).LR = Emu.GetPPUThreadExit(); + ((PPUThread&)new_thread).GPR[3] = a1; + ((PPUThread&)new_thread).GPR[4] = a2; + ((PPUThread&)new_thread).GPR[5] = a3; + new_thread.Exec(); + + while(new_thread.IsAlive()) Sleep(1); + Emu.GetCPU().RemoveThread(new_thread.GetId()); + + ConLog.Write("Callback EXIT!"); +} + +Callback2::Callback2(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr) +{ + a2 = userdata; +} + +void Callback2::Handle(u64 status) +{ + Callback::Handle(status, a2, 0); +} + +Callback3::Callback3(u32 slot, u64 addr, u64 userdata) : Callback(slot, addr) +{ + a3 = userdata; +} + +void Callback3::Handle(u64 status, u64 param) +{ + Callback::Handle(status, param, a3); +} diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h new file mode 100644 index 0000000000..fe720ab18e --- /dev/null +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -0,0 +1,146 @@ +#pragma once + +struct Callback +{ + u64 m_addr; + u32 m_slot; + + u64 a1; + u64 a2; + u64 a3; + + bool m_has_data; + + Callback(u32 slot, u64 addr); + void Handle(u64 a1, u64 a2, u64 a3); + void Branch(); +}; + +struct Callback2 : public Callback +{ + Callback2(u32 slot, u64 addr, u64 userdata); + void Handle(u64 status); +}; + +struct Callback3 : public Callback +{ + Callback3(u32 slot, u64 addr, u64 userdata); + void Handle(u64 status, u64 param); +}; + +struct Callbacks +{ + Array m_callbacks; + bool m_in_manager; + + Callbacks() : m_in_manager(false) + { + } + + virtual void Register(u32 slot, u64 addr, u64 userdata) + { + Unregister(slot); + } + + void Unregister(u32 slot) + { + for(u32 i=0; i m_callbacks; + Callbacks3 m_exit_callback; + + void Add(Callbacks& c) + { + if(c.m_in_manager) return; + + c.m_in_manager = true; + m_callbacks.Add(c); + } + + void Init() + { + Add(m_exit_callback); + } + + void Clear() + { + for(u32 i=0; i); + //sysPrxForUser.AddFunc(0x8a561d92, bind_func(sys_heap_delete_heap>); + sysPrxForUser.AddFunc(0xb2fcf2c8, bind_func(sys_heap_create_heap)); + } +} sysPrxForUser_init; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp new file mode 100644 index 0000000000..6c0c9f0633 --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -0,0 +1,26 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" + +Module sys_fs("sys_fs", 0x000e); + +struct _sys_fs_init +{ + _sys_fs_init() + { + sys_fs.AddFunc(0x718bf5f8, bind_func(cellFsOpen)); + sys_fs.AddFunc(0x4d5ff8e2, bind_func(cellFsRead)); + sys_fs.AddFunc(0xecdcf2ab, bind_func(cellFsWrite)); + sys_fs.AddFunc(0x2cb51f0d, bind_func(cellFsClose)); + sys_fs.AddFunc(0x3f61245c, bind_func(cellFsOpendir)); + sys_fs.AddFunc(0x5c74903d, bind_func(cellFsReaddir)); + sys_fs.AddFunc(0xff42dcc3, bind_func(cellFsClosedir)); + sys_fs.AddFunc(0x7de6dced, bind_func(cellFsStat)); + sys_fs.AddFunc(0xef3efa34, bind_func(cellFsFstat)); + sys_fs.AddFunc(0xba901fe6, bind_func(cellFsMkdir)); + sys_fs.AddFunc(0xf12eecc8, bind_func(cellFsRename)); + sys_fs.AddFunc(0x2796fdf3, bind_func(cellFsRmdir)); + sys_fs.AddFunc(0x7f4677a8, bind_func(cellFsUnlink)); + sys_fs.AddFunc(0xa397d042, bind_func(cellFsLseek)); + } +} sys_fs_init; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/sys_io.cpp b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp new file mode 100644 index 0000000000..7bea344fdb --- /dev/null +++ b/rpcs3/Emu/SysCalls/Modules/sys_io.cpp @@ -0,0 +1,20 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "Emu/SysCalls/SC_FUNC.h" + +Module sys_io("sys_io", 0x0017); + +struct _sys_io_init +{ + _sys_io_init() + { + sys_io.AddFunc(0x1cf98800, bind_func(cellPadInit)); + sys_io.AddFunc(0x4d9b75d5, bind_func(cellPadEnd)); + sys_io.AddFunc(0x0d5f2c14, bind_func(cellPadClearBuf)); + sys_io.AddFunc(0x8b72cda1, bind_func(cellPadGetData)); + sys_io.AddFunc(0x6bc09c61, bind_func(cellPadGetDataExtra)); + sys_io.AddFunc(0xf65544ee, bind_func(cellPadSetActDirect)); + sys_io.AddFunc(0xa703a51d, bind_func(cellPadGetInfo2)); + sys_io.AddFunc(0x578e3c98, bind_func(cellPadSetPortSetting)); + } +} sys_io_init; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/SC_FUNC.h b/rpcs3/Emu/SysCalls/SC_FUNC.h new file mode 100644 index 0000000000..9cee74bba0 --- /dev/null +++ b/rpcs3/Emu/SysCalls/SC_FUNC.h @@ -0,0 +1,367 @@ +#pragma once + +#define RESULT(x) SC_ARGS_1 = (x) + +template +class binder_func_0 : public func_caller +{ + typedef TR (*func_t)(); + const func_t m_call; + +public: + binder_func_0(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call()); } +}; + +template<> +class binder_func_0 : public func_caller +{ + typedef void (*func_t)(); + const func_t m_call; + +public: + binder_func_0(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(); } +}; + +template +class binder_func_1 : public func_caller +{ + typedef TR (*func_t)(T1); + const func_t m_call; + +public: + binder_func_1(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_1)); } +}; + +template +class binder_func_1 : public func_caller +{ + typedef void (*func_t)(T1); + const func_t m_call; + +public: + binder_func_1(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_1); } +}; + +template +class binder_func_2 : public func_caller +{ + typedef TR (*func_t)(T1, T2); + const func_t m_call; + +public: + binder_func_2(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_2)); } +}; + +template +class binder_func_2 : public func_caller +{ + typedef void (*func_t)(T1, T2); + const func_t m_call; + +public: + binder_func_2(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_2); } +}; + +template +class binder_func_3 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3); + const func_t m_call; + +public: + binder_func_3(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_3)); } +}; + +template +class binder_func_3 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3); + const func_t m_call; + +public: + binder_func_3(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_3); } +}; + +template +class binder_func_4 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4); + const func_t m_call; + +public: + binder_func_4(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_4)); } +}; + +template +class binder_func_4 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4); + const func_t m_call; + +public: + binder_func_4(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_4); } +}; + +template +class binder_func_5 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5); + const func_t m_call; + +public: + binder_func_5(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_5)); } +}; + +template +class binder_func_5 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5); + const func_t m_call; + +public: + binder_func_5(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_5); } +}; + +template +class binder_func_6 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6); + const func_t m_call; + +public: + binder_func_6(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_6)); } +}; + +template +class binder_func_6 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6); + const func_t m_call; + +public: + binder_func_6(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_6); } +}; + +template +class binder_func_7 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7); + const func_t m_call; + +public: + binder_func_7(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_7)); } +}; + +template +class binder_func_7 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7); + const func_t m_call; + +public: + binder_func_7(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_7); } +}; + +template +class binder_func_8 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8); + const func_t m_call; + +public: + binder_func_8(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_8)); } +}; + +template +class binder_func_8 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8); + const func_t m_call; + +public: + binder_func_8(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_8); } +}; + +template +class binder_func_9 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9); + const func_t m_call; + +public: + binder_func_9(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_9)); } +}; + +template +class binder_func_9 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9); + const func_t m_call; + +public: + binder_func_9(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_9); } +}; + +template +class binder_func_10 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); + const func_t m_call; + +public: + binder_func_10(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_10)); } +}; + +template +class binder_func_10 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); + const func_t m_call; + +public: + binder_func_10(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_10); } +}; + +template +class binder_func_11 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); + const func_t m_call; + +public: + binder_func_11(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_11)); } +}; + +template +class binder_func_11 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); + const func_t m_call; + +public: + binder_func_11(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_11); } +}; + +template +class binder_func_12 : public func_caller +{ + typedef TR (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); + const func_t m_call; + +public: + binder_func_12(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); RESULT(m_call(SC_ARGS_12)); } +}; + +template +class binder_func_12 : public func_caller +{ + typedef void (*func_t)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); + const func_t m_call; + +public: + binder_func_12(func_t call) : func_caller(), m_call(call) {} + virtual void operator()() { declCPU(); m_call(SC_ARGS_12); } +}; + +template +func_caller* bind_func(TR (*call)()) +{ + return new binder_func_0(call); +} + +template +func_caller* bind_func(TR (*call)(T1)) +{ + return new binder_func_1(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2)) +{ + return new binder_func_2(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3)) +{ + return new binder_func_3(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4)) +{ + return new binder_func_4(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5)) +{ + return new binder_func_5(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6)) +{ + return new binder_func_6(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7)) +{ + return new binder_func_7(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8)) +{ + return new binder_func_8(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) +{ + return new binder_func_9(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)) +{ + return new binder_func_10(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)) +{ + return new binder_func_11(call); +} + +template +func_caller* bind_func(TR (*call)(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12)) +{ + return new binder_func_12(call); +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp new file mode 100644 index 0000000000..b81c86d8c2 --- /dev/null +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -0,0 +1,404 @@ +#include "stdafx.h" +#include "SysCalls.h" +#include "SC_FUNC.h" +#include + +ArrayF g_modules_funcs_list; +ArrayF g_modules_list; + +bool IsLoadedFunc(u32 id) +{ + for(u32 i=0; i -//#include #include "ErrorCodes.h" //#define SYSCALLS_DEBUG -class SysCallBase +#define declCPU PPUThread& CPU = GetCurrentPPUThread + +class func_caller +{ +public: + virtual void operator()() = 0; +}; + +static func_caller *null_func = nullptr; + +//TODO +struct ModuleFunc +{ + u32 id; + func_caller* func; + + ModuleFunc(u32 id, func_caller* func) + : id(id) + , func(func) + { + } +}; + +class Module +{ + const char* m_name; + const u16 m_id; + bool m_is_loaded; + +public: + Array m_funcs_list; + + Module(const char* name, u16 id); + + void Load(); + void UnLoad(); + bool Load(u32 id); + bool UnLoad(u32 id); + + void SetLoaded(bool loaded = true) + { + m_is_loaded = loaded; + } + + bool IsLoaded() const + { + return m_is_loaded; + } + + u16 GetID() const + { + return m_id; + } + + wxString GetName() const + { + return m_name; + } + +public: + void Log(const u32 id, wxString fmt, ...) + { +#ifdef SYSCALLS_DEBUG + va_list list; + va_start(list, fmt); + ConLog.Write(GetName() + wxString::Format("[%d]: ", id) + wxString::FormatV(fmt, list)); + va_end(list); +#endif + } + + void Log(wxString fmt, ...) + { +#ifdef SYSCALLS_DEBUG + va_list list; + va_start(list, fmt); + ConLog.Write(GetName() + ": " + wxString::FormatV(fmt, list)); + va_end(list); +#endif + } + + void Warning(const u32 id, wxString fmt, ...) + { +//#ifdef SYSCALLS_DEBUG + va_list list; + va_start(list, fmt); + ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list)); + va_end(list); +//#endif + } + + void Warning(wxString fmt, ...) + { +//#ifdef SYSCALLS_DEBUG + va_list list; + va_start(list, fmt); + ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list)); + va_end(list); +//#endif + } + + void Error(const u32 id, wxString fmt, ...) + { + va_list list; + va_start(list, fmt); + ConLog.Error(GetName() + wxString::Format("[%d] error: ", id) + wxString::FormatV(fmt, list)); + va_end(list); + } + + void Error(wxString fmt, ...) + { + va_list list; + va_start(list, fmt); + ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list)); + va_end(list); + } + + bool CheckId(u32 id) const + { + return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName()); + } + + bool CheckId(u32 id, ID& _id) const + { + return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName()); + } + + template bool CheckId(u32 id, T*& data) + { + ID id_data; + + if(!CheckId(id, id_data)) return false; + + data = (T*)id_data.m_data; + + return true; + } + + u32 GetNewId(void* data = nullptr, u8 flags = 0) + { + return Emu.GetIdManager().GetNewID(GetName(), data, flags); + } + +//protected: + __forceinline void AddFunc(u32 id, func_caller* func) + { + m_funcs_list.Move(new ModuleFunc(id, func)); + } +}; + +static s64 null_function() { return 0; } + +bool IsLoadedFunc(u32 id); +bool CallFunc(u32 id); +bool UnloadFunc(u32 id); +void UnloadModules(); +Module* GetModuleByName(const wxString& name); +Module* GetModuleById(u16 id); + +class SysCallBase //Module { private: wxString m_module_name; + //u32 m_id; public: - SysCallBase(const wxString& name) : m_module_name(name) + SysCallBase(const wxString& name/*, u32 id*/) + : m_module_name(name) + //, m_id(id) { } - wxString GetName() { return m_module_name; } + const wxString& GetName() const { return m_module_name; } void Log(const u32 id, wxString fmt, ...) { @@ -39,22 +198,22 @@ public: void Warning(const u32 id, wxString fmt, ...) { -#ifdef SYSCALLS_DEBUG +//#ifdef SYSCALLS_DEBUG va_list list; va_start(list, fmt); ConLog.Warning(GetName() + wxString::Format("[%d] warning: ", id) + wxString::FormatV(fmt, list)); va_end(list); -#endif +//#endif } void Warning(wxString fmt, ...) { -#ifdef SYSCALLS_DEBUG +//#ifdef SYSCALLS_DEBUG va_list list; va_start(list, fmt); - ConLog.Warning(GetName() + wxString::Format(" warning: ") + wxString::FormatV(fmt, list)); + ConLog.Warning(GetName() + " warning: " + wxString::FormatV(fmt, list)); va_end(list); -#endif +//#endif } void Error(const u32 id, wxString fmt, ...) @@ -69,11 +228,38 @@ public: { va_list list; va_start(list, fmt); - ConLog.Error(GetName() + wxString::Format(" error: ") + wxString::FormatV(fmt, list)); + ConLog.Error(GetName() + " error: " + wxString::FormatV(fmt, list)); va_end(list); } + + bool CheckId(u32 id) const + { + return Emu.GetIdManager().CheckID(id) && !Emu.GetIdManager().GetIDData(id).m_name.Cmp(GetName()); + } + + bool CheckId(u32 id, ID& _id) const + { + return Emu.GetIdManager().CheckID(id) && !(_id = Emu.GetIdManager().GetIDData(id)).m_name.Cmp(GetName()); + } + + template bool CheckId(u32 id, T*& data) + { + ID id_data; + + if(!CheckId(id, id_data)) return false; + + data = (T*)id_data.m_data; + + return true; + } + + u32 GetNewId(void* data = nullptr, u8 flags = 0) + { + return Emu.GetIdManager().GetNewID(GetName(), data, flags); + } }; +/* static bool CmpPath(const wxString& path1, const wxString& path2) { return path1.Len() >= path2.Len() && path1(0, path2.Len()).CmpNoCase(path2) == 0; @@ -99,37 +285,97 @@ static wxString GetWinPath(const wxString& path) return wxFileName(Emu.m_path).GetPath() + (path[0] == '/' ? path : "/" + path); } +*/ //process extern int sys_process_getpid(); +extern int sys_process_exit(int errorcode); extern int sys_game_process_exitspawn(u32 path_addr, u32 argv_addr, u32 envp_addr, u32 data, u32 data_size, int prio, u64 flags ); +//sys_semaphore +extern int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_val, int max_val); +extern int sys_semaphore_destroy(u32 sem); +extern int sys_semaphore_wait(u32 sem, u64 timeout); +extern int sys_semaphore_trywait(u32 sem); +extern int sys_semaphore_post(u32 sem, int count); + +//sys_lwmutex +extern int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr); +extern int sys_lwmutex_destroy(u64 lwmutex_addr); +extern int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout); +extern int sys_lwmutex_trylock(u64 lwmutex_addr); +extern int sys_lwmutex_unlock(u64 lwmutex_addr); + +//sys_cond +extern int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr); +extern int sys_cond_destroy(u32 cond_id); +extern int sys_cond_wait(u32 cond_id, u64 timeout); +extern int sys_cond_signal(u32 cond_id); +extern int sys_cond_signal_all(u32 cond_id); + +//sys_mutex +extern int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr); +extern int sys_mutex_destroy(u32 mutex_id); +extern int sys_mutex_lock(u32 mutex_id, u64 timeout); +extern int sys_mutex_trylock(u32 mutex_id); +extern int sys_mutex_unlock(u32 mutex_id); + +//ppu_thread +extern int sys_ppu_thread_exit(int errorcode); +extern int sys_ppu_thread_yield(); +extern int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr); +extern int sys_ppu_thread_detach(u32 thread_id); +extern void sys_ppu_thread_get_join_state(u32 isjoinable_addr); +extern int sys_ppu_thread_set_priority(u32 thread_id, int prio); +extern int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr); +extern int sys_ppu_thread_get_stack_information(u32 info_addr); +extern int sys_ppu_thread_stop(u32 thread_id); +extern int sys_ppu_thread_restart(u32 thread_id); +extern int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr); +extern int sys_ppu_thread_get_id(); + //memory extern int sys_memory_container_create(u32 cid_addr, u32 yield_size); extern int sys_memory_container_destroy(u32 cid); extern int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr); +extern int sys_memory_free(u32 start_addr); extern int sys_memory_get_user_memory_size(u32 mem_info_addr); +extern int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr); +extern int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr); +extern int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags); //cellFs -extern int cellFsOpen(const u32 path_addr, const int flags, const u32 fd_addr, const u32 arg_addr, const u64 size); -extern int cellFsRead(const u32 fd, const u32 buf_addr, const u64 nbytes, const u32 nread_addr); -extern int cellFsWrite(const u32 fd, const u32 buf_addr, const u64 nbytes, const u32 nwrite_addr); -extern int cellFsClose(const u32 fd); -extern int cellFsOpendir(const u32 path_addr, const u32 fd_addr); -extern int cellFsReaddir(const u32 fd, const u32 dir_addr, const u32 nread_addr); -extern int cellFsClosedir(const u32 fd); -extern int cellFsStat(const u32 path_addr, const u32 sb_addr); -extern int cellFsFstat(const u32 fd, const u32 sb_addr); -extern int cellFsMkdir(const u32 path_addr, const u32 mode); -extern int cellFsRename(const u32 from_addr, const u32 to_addr); -extern int cellFsRmdir(const u32 path_addr); -extern int cellFsUnlink(const u32 path_addr); -extern int cellFsLseek(const u32 fd, const s64 offset, const u32 whence, const u32 pos_addr); +extern int cellFsOpen(u32 path_addr, int flags, u32 fd_addr, u32 arg_addr, u64 size); +extern int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, u32 nread_addr); +extern int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, u32 nwrite_addr); +extern int cellFsClose(u32 fd); +extern int cellFsOpendir(u32 path_addr, u32 fd_addr); +extern int cellFsReaddir(u32 fd, u32 dir_addr, u32 nread_addr); +extern int cellFsClosedir(u32 fd); +extern int cellFsStat(u32 path_addr, u32 sb_addr); +extern int cellFsFstat(u32 fd, u32 sb_addr); +extern int cellFsMkdir(u32 path_addr, u32 mode); +extern int cellFsRename(u32 from_addr, u32 to_addr); +extern int cellFsRmdir(u32 path_addr); +extern int cellFsUnlink(u32 path_addr); +extern int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr); //cellVideo extern int cellVideoOutGetState(u32 videoOut, u32 deviceIndex, u32 state_addr); extern int cellVideoOutGetResolution(u32 resolutionId, u32 resolution_addr); +extern int cellVideoOutConfigure(u32 videoOut, u32 config_addr, u32 option_addr, u32 waitForEvent); +extern int cellVideoOutGetConfiguration(u32 videoOut, u32 config_addr, u32 option_addr); +extern int cellVideoOutGetNumberOfDevice(u32 videoOut); +extern int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option); + +//cellSysutil +extern int cellSysutilCheckCallback(); +extern int cellSysutilRegisterCallback(int slot, u64 func_addr, u64 userdata); +extern int cellSysutilUnregisterCallback(int slot); + +//cellMsgDialog +extern int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 userData, u32 extParam); //cellPad extern int cellPadInit(u32 max_connect); @@ -142,17 +388,29 @@ extern int cellPadGetInfo2(u32 info_addr); extern int cellPadSetPortSetting(u32 port_no, u32 port_setting); //cellGcm -extern int cellGcmInit(const u32 context_addr, const u32 cmdSize, const u32 ioSize, const u32 ioAddress); -extern int cellGcmGetConfiguration(const u32 config_addr); -extern int cellGcmAddressToOffset(const u32 address, const u32 offset_addr); -extern int cellGcmSetDisplayBuffer(const u8 id, const u32 offset, const u32 pitch, const u32 width, const u32 height); -extern u32 cellGcmGetLabelAddress(const u32 index); +extern int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress); +extern int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr); +extern int cellGcmCallback(u32 context_addr, u32 count); +extern int cellGcmGetConfiguration(u32 config_addr); +extern int cellGcmAddressToOffset(u32 address, u32 offset_addr); +extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); +extern u32 cellGcmGetLabelAddress(u32 index); extern u32 cellGcmGetControlRegister(); -extern int cellGcmFlush(const u32 ctx, const u8 id); -extern int cellGcmSetTile(const u8 index, const u8 location, const u32 offset, const u32 size, const u32 pitch, const u8 comp, const u16 base, const u8 bank); +extern int cellGcmFlush(u32 ctx, u32 id); +extern void cellGcmSetTile(u32 index, u32 location, u32 offset, u32 size, u32 pitch, u32 comp, u32 base, u32 bank); +extern int cellGcmBindTile(u32 index); +extern int cellGcmBindZcull(u32 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask); extern int cellGcmGetFlipStatus(); extern int cellGcmResetFlipStatus(); -extern u32 cellGcmGetTiledPitchSize(const u32 size); +extern u32 cellGcmGetTiledPitchSize(u32 size); +extern int cellGcmSetFlipMode(u32 mode); +extern u32 cellGcmGetDefaultCommandWordSize(); +extern u32 cellGcmGetDefaultSegmentWordSize(); +extern int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize); + +//sys_tty +extern int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr); +extern int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr); //cellResc extern int cellRescSetSrc(const int idx, const u32 src_addr); @@ -173,7 +431,7 @@ extern int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr); extern s64 sys_time_get_system_time(); extern u64 sys_time_get_timebase_frequency(); -#define SC_ARGS_1 CPU.GPR[3] +#define SC_ARGS_1 CPU.GPR[3] #define SC_ARGS_2 SC_ARGS_1,CPU.GPR[4] #define SC_ARGS_3 SC_ARGS_2,CPU.GPR[5] #define SC_ARGS_4 SC_ARGS_3,CPU.GPR[6] @@ -181,11 +439,18 @@ extern u64 sys_time_get_timebase_frequency(); #define SC_ARGS_6 SC_ARGS_5,CPU.GPR[8] #define SC_ARGS_7 SC_ARGS_6,CPU.GPR[9] #define SC_ARGS_8 SC_ARGS_7,CPU.GPR[10] +#define SC_ARGS_9 SC_ARGS_8,CPU.GPR[11] +#define SC_ARGS_10 SC_ARGS_9,CPU.GPR[12] +#define SC_ARGS_11 SC_ARGS_10,CPU.GPR[13] +#define SC_ARGS_12 SC_ARGS_11,CPU.GPR[14] extern bool dump_enable; +class PPUThread; class SysCalls { + PPUThread& CPU; + public: //process int lv2ProcessGetPid(PPUThread& CPU); @@ -196,138 +461,16 @@ public: int lv2ProcessGetId(PPUThread& CPU); int lv2ProcessGetPpid(PPUThread& CPU); int lv2ProcessKill(PPUThread& CPU); - int lv2ProcessExit(PPUThread& CPU); int lv2ProcessWaitForChild2(PPUThread& CPU); int lv2ProcessGetSdkVersion(PPUThread& CPU); - //ppu thread - int lv2PPUThreadCreate(PPUThread& CPU); - int lv2PPUThreadExit(PPUThread& CPU); - int lv2PPUThreadYield(PPUThread& CPU); - int lv2PPUThreadJoin(PPUThread& CPU); - int lv2PPUThreadDetach(PPUThread& CPU); - int lv2PPUThreadGetJoinState(PPUThread& CPU); - int lv2PPUThreadSetPriority(PPUThread& CPU); - int lv2PPUThreadGetPriority(PPUThread& CPU); - int lv2PPUThreadGetStackInformation(PPUThread& CPU); - int lv2PPUThreadRename(PPUThread& CPU); - int lv2PPUThreadRecoverPageFault(PPUThread& CPU); - int lv2PPUThreadGetPageFaultContext(PPUThread& CPU); - int lv2PPUThreadGetId(PPUThread& CPU); - - //lwmutex - int Lv2LwmutexCreate(PPUThread& CPU); - int Lv2LwmutexDestroy(PPUThread& CPU); - int Lv2LwmutexLock(PPUThread& CPU); - int Lv2LwmutexTrylock(PPUThread& CPU); - int Lv2LwmutexUnlock(PPUThread& CPU); - - //tty - int lv2TtyRead(PPUThread& CPU); - int lv2TtyWrite(PPUThread& CPU); +protected: + SysCalls(PPUThread& cpu); + ~SysCalls(); public: - SysCalls()// : CPU(cpu) - { - } - - ~SysCalls() - { - Close(); - } - - void Close() - { - } - - s64 DoSyscall(u32 code, PPUThread& CPU) - { - switch(code) - { - //=== lv2 === - //process - case 1: return sys_process_getpid(); - case 2: return lv2ProcessWaitForChild(CPU); - case 3: return lv2ProcessExit(CPU); - case 4: return lv2ProcessGetStatus(CPU); - case 5: return lv2ProcessDetachChild(CPU); - case 12: return lv2ProcessGetNumberOfObject(CPU); - case 13: return lv2ProcessGetId(CPU); - case 18: return lv2ProcessGetPpid(CPU); - case 19: return lv2ProcessKill(CPU); - case 22: return lv2ProcessExit(CPU); - case 23: return lv2ProcessWaitForChild2(CPU); - case 25: return lv2ProcessGetSdkVersion(CPU); - //ppu thread - //case ?: return lv2PPUThreadCreate(CPU); - //case ?: return lv2PPUThreadExit(CPU); - case 43: return lv2PPUThreadYield(CPU); - case 44: return lv2PPUThreadJoin(CPU); - case 45: return lv2PPUThreadDetach(CPU); - case 46: return lv2PPUThreadGetJoinState(CPU); - case 47: return lv2PPUThreadSetPriority(CPU); - case 48: return lv2PPUThreadGetPriority(CPU); - case 49: return lv2PPUThreadGetStackInformation(CPU); - case 56: return lv2PPUThreadRename(CPU); - case 57: return lv2PPUThreadRecoverPageFault(CPU); - case 58: return lv2PPUThreadGetPageFaultContext(CPU); - //case ?: return lv2PPUThreadGetId(CPU); - //lwmutex - case 95: return Lv2LwmutexCreate(CPU); - case 96: return Lv2LwmutexDestroy(CPU); - case 97: return Lv2LwmutexLock(CPU); - case 98: return Lv2LwmutexTrylock(CPU); - case 99: return Lv2LwmutexUnlock(CPU); - //timer - case 141: - case 142: - //wxSleep(Emu.GetCPU().GetThreads().GetCount() > 1 ? 1 : /*SC_ARGS_1*/1); - return 0; - //time - case 145: return sys_time_get_current_time(SC_ARGS_2); - case 146: return sys_time_get_system_time(); - case 147: return sys_time_get_timebase_frequency(); - //sys_spu - case 160: return sys_raw_spu_create(SC_ARGS_2); - case 169: return sys_spu_initialize(SC_ARGS_2); - case 170: return sys_spu_thread_group_create(SC_ARGS_4); - //memory - case 324: return sys_memory_container_create(SC_ARGS_2); - case 325: return sys_memory_container_destroy(SC_ARGS_1); - case 348: return sys_memory_allocate(SC_ARGS_3); - case 352: return sys_memory_get_user_memory_size(SC_ARGS_1); - //tty - case 402: return lv2TtyRead(CPU); - case 403: return lv2TtyWrite(CPU); - //file system - case 801: return cellFsOpen(SC_ARGS_5); - case 802: return cellFsRead(SC_ARGS_4); - case 803: return cellFsWrite(SC_ARGS_4); - case 804: return cellFsClose(SC_ARGS_1); - case 805: return cellFsOpendir(SC_ARGS_2); - case 806: return cellFsReaddir(SC_ARGS_3); - case 807: return cellFsClosedir(SC_ARGS_1); - case 809: return cellFsFstat(SC_ARGS_2); - case 811: return cellFsMkdir(SC_ARGS_2); - case 812: return cellFsRename(SC_ARGS_2); - case 813: return cellFsRmdir(SC_ARGS_1); - case 818: return cellFsLseek(SC_ARGS_4); - case 988: - ConLog.Warning("SysCall 988! r3: 0x%llx, r4: 0x%llx, pc: 0x%llx", - CPU.GPR[3], CPU.GPR[4], CPU.PC); - return 0; - - case 999: - dump_enable = !dump_enable; - ConLog.Warning("Dump %s", dump_enable ? "enabled" : "disabled"); - return 0; - } - - ConLog.Error("Unknown syscall: %d - %08x", code, code); - return 0; - } - - s64 DoFunc(const u32 id, PPUThread& CPU); + s64 DoSyscall(u32 code); + s64 DoFunc(const u32 id); }; -extern SysCalls SysCallsManager; \ No newline at end of file +//extern SysCalls SysCallsManager; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp new file mode 100644 index 0000000000..723fe1bfc2 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Condition.cpp @@ -0,0 +1,98 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "SC_Mutex.h" + +SysCallBase sys_cond("sys_cond"); +extern SysCallBase sys_mtx; + +struct condition_attr +{ + u32 pshared; + int flags; + u64 ipc_key; + char name[8]; +}; + +struct condition +{ + wxCondition cond; + condition_attr attr; + + condition(wxMutex& mtx, const condition_attr& attr) + : cond(mtx) + , attr(attr) + { + } +}; + +int sys_cond_create(u32 cond_addr, u32 mutex_id, u32 attr_addr) +{ + sys_cond.Log("sys_cond_create(cond_addr=0x%x, mutex_id=0x%x, attr_addr=%d)", + cond_addr, mutex_id, attr_addr); + + if(!Memory.IsGoodAddr(cond_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT; + + condition_attr attr = (condition_attr&)Memory[attr_addr]; + + attr.pshared = re(attr.pshared); + attr.ipc_key = re(attr.ipc_key); + attr.flags = re(attr.flags); + + sys_cond.Log("*** pshared = %d", attr.pshared); + sys_cond.Log("*** ipc_key = 0x%llx", attr.ipc_key); + sys_cond.Log("*** flags = 0x%x", attr.flags); + sys_cond.Log("*** name = %s", attr.name); + + mutex* mtx_data = nullptr; + if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; + + Memory.Write32(cond_addr, sys_cond.GetNewId(new condition(mtx_data->mtx, attr))); + + return CELL_OK; +} + +int sys_cond_destroy(u32 cond_id) +{ + sys_cond.Log("sys_cond_destroy(cond_id=0x%x)", cond_id); + + if(!sys_cond.CheckId(cond_id)) return CELL_ESRCH; + + Emu.GetIdManager().RemoveID(cond_id); + return CELL_OK; +} + +int sys_cond_wait(u32 cond_id, u64 timeout) +{ + sys_cond.Log("sys_cond_wait(cond_id=0x%x, timeout=0x%llx)", cond_id, timeout); + + condition* cond_data = nullptr; + if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH; + + cond_data->cond.WaitTimeout(timeout ? timeout : INFINITE); + + return CELL_OK; +} + +int sys_cond_signal(u32 cond_id) +{ + sys_cond.Log("sys_cond_signal(cond_id=0x%x)", cond_id); + + condition* cond_data = nullptr; + if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH; + + cond_data->cond.Signal(); + + return CELL_OK; +} + +int sys_cond_signal_all(u32 cond_id) +{ + sys_cond.Log("sys_cond_signal_all(cond_id=0x%x)", cond_id); + + condition* cond_data = nullptr; + if(!sys_cond.CheckId(cond_id, cond_data)) return CELL_ESRCH; + + cond_data->cond.Broadcast(); + + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp index c2f728bbeb..55e88107ef 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_FileSystem.cpp @@ -1,7 +1,6 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" -typedef u64 GPRtype; enum Lv2FsOflag { LV2_O_RDONLY = 000000, @@ -83,26 +82,22 @@ enum FsDirentType CELL_FS_TYPE_SYMLINK = 3, }; -SysCallBase sc_log("cellFs"); +extern Module sys_fs; -wxString ReadString(const u32 addr) -{ - return GetWinPath(Memory.ReadString(addr)); -} - -int cellFsOpen(const u32 path_addr, const int flags, const u32 fd_addr, const u32 arg_addr, const u64 size) +int cellFsOpen(u32 path_addr, int flags, u32 fd_addr, u32 arg_addr, u64 size) { const wxString& path = Memory.ReadString(path_addr); - sc_log.Log("cellFsOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx)", + sys_fs.Log("cellFsOpen(path: %s, flags: 0x%x, fd_addr: 0x%x, arg_addr: 0x%x, size: 0x%llx)", path, flags, fd_addr, arg_addr, size); - const wxString& ppath = GetWinPath(path); + const wxString& ppath = path; //ConLog.Warning("path: %s [%s]", ppath, path); s32 _oflags = flags; if(flags & LV2_O_CREAT) { _oflags &= ~LV2_O_CREAT; + /* //create path for(uint p=1;pIsOpened()) { - sc_log.Error("'%s' not found! flags: 0x%08x", ppath, flags); + sys_fs.Error("'%s' not found! flags: 0x%08x", ppath, flags); + delete stream; + return CELL_ENOENT; } - Memory.Write32(fd_addr, - Emu.GetIdManager().GetNewID(sc_log.GetName(), new wxFile(ppath, o_mode), flags)); + Memory.Write32(fd_addr, sys_fs.GetNewId(stream, flags)); return CELL_OK; } -int cellFsRead(const u32 fd, const u32 buf_addr, const u64 nbytes, const u32 nread_addr) +int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, u32 nread_addr) { - sc_log.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)", + sys_fs.Log("cellFsRead(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nread_addr: 0x%x)", fd, buf_addr, nbytes, nread_addr); - if(!Emu.GetIdManager().CheckID(fd)) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(fd); - if(!!id.m_name.Cmp(sc_log.GetName())) return CELL_ESRCH; - wxFile& file = *(wxFile*)id.m_data; + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; Memory.Write64NN(nread_addr, file.Read(Memory.GetMemFromAddr(buf_addr), nbytes)); return CELL_OK; } -int cellFsWrite(const u32 fd, const u32 buf_addr, const u64 nbytes, const u32 nwrite_addr) +int cellFsWrite(u32 fd, u32 buf_addr, u64 nbytes, u32 nwrite_addr) { - sc_log.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)", + sys_fs.Log("cellFsWrite(fd: %d, buf_addr: 0x%x, nbytes: 0x%llx, nwrite_addr: 0x%x)", fd, buf_addr, nbytes, nwrite_addr); - if(!Emu.GetIdManager().CheckID(fd)) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(fd); - if(!!id.m_name.Cmp(sc_log.GetName())) return CELL_ESRCH; - wxFile& file = *(wxFile*)id.m_data; + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; Memory.Write64NN(nwrite_addr, file.Write(Memory.GetMemFromAddr(buf_addr), nbytes)); return CELL_OK; } -int cellFsClose(const u32 fd) +int cellFsClose(u32 fd) { - sc_log.Log("cellFsClose(fd: %d)", fd); - if(!Emu.GetIdManager().CheckID(fd)) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(fd); - if(!!id.m_name.Cmp(sc_log.GetName())) return CELL_ESRCH; - wxFile& file = *(wxFile*)id.m_data; + sys_fs.Log("cellFsClose(fd: %d)", fd); + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; file.Close(); Emu.GetIdManager().RemoveID(fd); return CELL_OK; } -int cellFsOpendir(const u32 path_addr, const u32 fd_addr) +int cellFsOpendir(u32 path_addr, u32 fd_addr) { const wxString& path = Memory.ReadString(path_addr); - sc_log.Error("cellFsOpendir(path: %s, fd_addr: 0x%x)", path, fd_addr); + sys_fs.Error("cellFsOpendir(path_addr: 0x%x(%s), fd_addr: 0x%x)", path_addr, path, fd_addr); + if(!Memory.IsGoodAddr(path_addr, sizeof(u32)) || !Memory.IsGoodAddr(fd_addr, sizeof(u32))) return CELL_EFAULT; + return CELL_OK; } -int cellFsReaddir(const u32 fd, const u32 dir_addr, const u32 nread_addr) +int cellFsReaddir(u32 fd, u32 dir_addr, u32 nread_addr) { - sc_log.Error("cellFsReaddir(fd: %d, dir_addr: 0x%x, nread_addr: 0x%x)", fd, dir_addr, nread_addr); + sys_fs.Error("cellFsReaddir(fd: %d, dir_addr: 0x%x, nread_addr: 0x%x)", fd, dir_addr, nread_addr); return CELL_OK; } -int cellFsClosedir(const u32 fd) +int cellFsClosedir(u32 fd) { - sc_log.Error("cellFsClosedir(fd: %d)", fd); + sys_fs.Error("cellFsClosedir(fd: %d)", fd); return CELL_OK; } int cellFsStat(const u32 path_addr, const u32 sb_addr) { - const wxString& path = ReadString(path_addr); - sc_log.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb_addr); + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Log("cellFsFstat(path: %s, sb_addr: 0x%x)", path, sb_addr); if(!wxFileExists(path)) return CELL_ENOENT; @@ -275,11 +274,10 @@ int cellFsStat(const u32 path_addr, const u32 sb_addr) int cellFsFstat(u32 fd, u32 sb_addr) { - sc_log.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb_addr); - if(!Emu.GetIdManager().CheckID(fd)) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(fd); - if(!!id.m_name.Cmp(sc_log.GetName())) return CELL_ESRCH; - wxFile& file = *(wxFile*)id.m_data; + sys_fs.Log("cellFsFstat(fd: %d, sb_addr: 0x%x)", fd, sb_addr); + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; Lv2FsStat stat; stat.st_mode = @@ -293,7 +291,7 @@ int cellFsFstat(u32 fd, u32 sb_addr) stat.st_atime = 0; //TODO stat.st_mtime = 0; //TODO stat.st_ctime = 0; //TODO - stat.st_size = file.Length(); + stat.st_size = file.GetSize(); stat.st_blksize = 4096; mem_class_t stat_c(sb_addr); @@ -309,59 +307,58 @@ int cellFsFstat(u32 fd, u32 sb_addr) return CELL_OK; } -int cellFsMkdir(const u32 path_addr, const u32 mode) +int cellFsMkdir(u32 path_addr, u32 mode) { - const wxString& path = ReadString(path_addr); - sc_log.Log("cellFsMkdir(path: %s, mode: 0x%x)", path, mode); + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Log("cellFsMkdir(path: %s, mode: 0x%x)", path, mode); if(wxDirExists(path)) return CELL_EEXIST; if(!wxMkdir(path)) return CELL_EBUSY; return CELL_OK; } -int cellFsRename(const u32 from_addr, const u32 to_addr) +int cellFsRename(u32 from_addr, u32 to_addr) { - const wxString& from = ReadString(from_addr); - const wxString& to = ReadString(to_addr); - sc_log.Log("cellFsRename(from: %s, to: %s)", from, to); + const wxString& from = Memory.ReadString(from_addr); + const wxString& to = Memory.ReadString(to_addr); + sys_fs.Log("cellFsRename(from: %s, to: %s)", from, to); if(!wxFileExists(from)) return CELL_ENOENT; if(wxFileExists(to)) return CELL_EEXIST; if(!wxRenameFile(from, to)) return CELL_EBUSY; return CELL_OK; } -int cellFsRmdir(const u32 path_addr) +int cellFsRmdir(u32 path_addr) { - const wxString& path = ReadString(path_addr); - sc_log.Log("cellFsRmdir(path: %s)", path); + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Log("cellFsRmdir(path: %s)", path); if(!wxDirExists(path)) return CELL_ENOENT; if(!wxRmdir(path)) return CELL_EBUSY; return CELL_OK; } -int cellFsUnlink(const u32 path_addr) +int cellFsUnlink(u32 path_addr) { - const wxString& path = ReadString(path_addr); - sc_log.Error("cellFsUnlink(path: %s)", path); + const wxString& path = Memory.ReadString(path_addr); + sys_fs.Error("cellFsUnlink(path: %s)", path); return CELL_OK; } -int cellFsLseek(const u32 fd, const s64 offset, const u32 whence, const u32 pos_addr) +int cellFsLseek(u32 fd, s64 offset, u32 whence, u32 pos_addr) { - wxSeekMode seek_mode; - sc_log.Log("cellFsLseek(fd: %d, offset: 0x%llx, whence: %d, pos_addr: 0x%x)", fd, offset, whence, pos_addr); + vfsSeekMode seek_mode; + sys_fs.Log("cellFsLseek(fd: %d, offset: 0x%llx, whence: %d, pos_addr: 0x%x)", fd, offset, whence, pos_addr); switch(whence) { - case LV2_SEEK_SET: seek_mode = wxFromStart; break; - case LV2_SEEK_CUR: seek_mode = wxFromCurrent; break; - case LV2_SEEK_END: seek_mode = wxFromEnd; break; + case LV2_SEEK_SET: seek_mode = vfsSeekSet; break; + case LV2_SEEK_CUR: seek_mode = vfsSeekCur; break; + case LV2_SEEK_END: seek_mode = vfsSeekEnd; break; default: - sc_log.Error(fd, "Unknown seek whence! (%d)", whence); + sys_fs.Error(fd, "Unknown seek whence! (%d)", whence); return CELL_EINVAL; } - if(!Emu.GetIdManager().CheckID(fd)) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(fd); - if(!!id.m_name.Cmp(sc_log.GetName())) return CELL_ESRCH; - wxFile& file = *(wxFile*)id.m_data; + ID id; + if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH; + vfsStream& file = *(vfsStream*)id.m_data; Memory.Write64(pos_addr, file.Seek(offset, seek_mode)); return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_GCM.cpp b/rpcs3/Emu/SysCalls/lv2/SC_GCM.cpp index afedd391b0..d01f4e426a 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_GCM.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_GCM.cpp @@ -2,15 +2,24 @@ #include "Emu/SysCalls/SysCalls.h" #include "Emu/GS/GCM.h" -SysCallBase sc_gcm("cellGcm"); +extern Module cellGcmSys; CellGcmConfig current_config; CellGcmContextData current_context; gcmInfo gcm_info; -int cellGcmInit(const u32 context_addr, const u32 cmdSize, const u32 ioSize, const u32 ioAddress) +int cellGcmMapMainMemory(u32 address, u32 size, u32 offset_addr) { - sc_gcm.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); + cellGcmSys.Warning("cellGcmMapMainMemory(address=0x%x,size=0x%x,offset_addr=0x%x)", address, size, offset_addr); + if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT; + Memory.Write32(offset_addr, address & 0xffff); + + return CELL_OK; +} + +int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) +{ + cellGcmSys.Log("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); const u32 local_size = 0xf900000; //TODO const u32 local_addr = Memory.RSXFBMem.GetStartAddr(); @@ -38,7 +47,7 @@ int cellGcmInit(const u32 context_addr, const u32 cmdSize, const u32 ioSize, con Memory.WriteData(gcm_info.context_addr, current_context); Memory.Write32(context_addr, gcm_info.context_addr); - CellGcmControl& ctrl = *(CellGcmControl*)Memory.GetMemFromAddr(gcm_info.control_addr); + CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; ctrl.put = 0; ctrl.get = 0; ctrl.ref = -1; @@ -48,16 +57,40 @@ int cellGcmInit(const u32 context_addr, const u32 cmdSize, const u32 ioSize, con return CELL_OK; } -int cellGcmGetConfiguration(const u32 config_addr) +int cellGcmCallback(u32 context_addr, u32 count) { - sc_gcm.Log("cellGcmGetConfiguration(config_addr=0x%x)", config_addr); + GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); + + CellGcmContextData& ctx = (CellGcmContextData&)Memory[context_addr]; + CellGcmControl& ctrl = (CellGcmControl&)Memory[gcm_info.control_addr]; + + const s32 res = re(ctx.current) - re(ctx.begin) - re(ctrl.put); + + if(res > 0) memcpy(&Memory[re(ctx.begin)], &Memory[re(ctx.current) - res], res); + + ctx.current = re(re(ctx.begin) + res); + + ctrl.put = re(res); + ctrl.get = 0; + + return CELL_OK; +} + +int cellGcmGetConfiguration(u32 config_addr) +{ + cellGcmSys.Log("cellGcmGetConfiguration(config_addr=0x%x)", config_addr); + + if(!Memory.IsGoodAddr(config_addr, sizeof(CellGcmConfig))) return CELL_EFAULT; + Memory.WriteData(config_addr, current_config); return CELL_OK; } -int cellGcmAddressToOffset(const u32 address, const u32 offset_addr) +int cellGcmAddressToOffset(u32 address, u32 offset_addr) { - sc_gcm.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr); + cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset_addr); + if(!Memory.IsGoodAddr(offset_addr, sizeof(u32))) return CELL_EFAULT; + Memory.Write32(offset_addr, Memory.RSXFBMem.IsInMyRange(address) ? address - Memory.RSXFBMem.GetStartAddr() @@ -66,9 +99,9 @@ int cellGcmAddressToOffset(const u32 address, const u32 offset_addr) return CELL_OK; } -int cellGcmSetDisplayBuffer(const u8 id, const u32 offset, const u32 pitch, const u32 width, const u32 height) +int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height) { - sc_gcm.Log("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", + cellGcmSys.Warning("cellGcmSetDisplayBuffer(id=0x%x,offset=0x%x,pitch=%d,width=%d,height=%d)", id, offset, width ? pitch/width : pitch, width, height); if(id > 1) return CELL_EINVAL; @@ -81,22 +114,22 @@ int cellGcmSetDisplayBuffer(const u8 id, const u32 offset, const u32 pitch, cons return CELL_OK; } -u32 cellGcmGetLabelAddress(const u32 index) +u32 cellGcmGetLabelAddress(u32 index) { - sc_gcm.Log("cellGcmGetLabelAddress(index=%d)", index); + cellGcmSys.Log("cellGcmGetLabelAddress(index=%d)", index); return Memory.RSXCMDMem.GetStartAddr() + 0x10 * index; } u32 cellGcmGetControlRegister() { - sc_gcm.Log("cellGcmGetControlRegister()"); + cellGcmSys.Log("cellGcmGetControlRegister()"); return gcm_info.control_addr; } -int cellGcmFlush(const u32 ctx, const u8 id) +int cellGcmFlush(u32 ctx, u32 id) { - sc_gcm.Log("cellGcmFlush(ctx=0x%x, id=0x%x)", ctx, id); + cellGcmSys.Log("cellGcmFlush(ctx=0x%x, id=0x%x)", ctx, id); if(id > 1) return CELL_EINVAL; Emu.GetGSManager().GetRender().Draw(); @@ -104,12 +137,25 @@ int cellGcmFlush(const u32 ctx, const u8 id) return CELL_OK; } -int cellGcmSetTile(const u8 index, const u8 location, const u32 offset, const u32 size, - const u32 pitch, const u8 comp, const u16 base, const u8 bank) +void cellGcmSetTile(u32 index, u32 location, u32 offset, u32 size, u32 pitch, u32 comp, u32 base, u32 bank) { - sc_gcm.Log("cellGcmSetTile(index=%d, location=%d, offset=0x%x, size=0x%x, pitch=0x%x, comp=0x%x, base=0x%x, bank=0x%x)", + cellGcmSys.Warning("cellGcmSetTile(index=%d, location=%d, offset=0x%x, size=0x%x, pitch=0x%x, comp=0x%x, base=0x%x, bank=0x%x)", index, location, offset, size, pitch, comp, base, bank); + //return CELL_OK; +} + +int cellGcmBindTile(u32 index) +{ + cellGcmSys.Warning("TODO: cellGcmBindTile(index=%d)", index); + + return CELL_OK; +} + +int cellGcmBindZcull(u32 index, u32 offset, u32 width, u32 height, u32 cullStart, u32 zFormat, u32 aaFormat, u32 zCullDir, u32 zCullFormat, u32 sFunc, u32 sRef, u32 sMask) +{ + cellGcmSys.Warning("TODO: cellGcmBindZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)", index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask); + return CELL_OK; } @@ -121,13 +167,51 @@ int cellGcmGetFlipStatus() int cellGcmResetFlipStatus() { Emu.GetGSManager().GetRender().m_flip_status = 1; + return CELL_OK; } -u32 cellGcmGetTiledPitchSize(const u32 size) +int cellGcmSetFlipMode(u32 mode) +{ + cellGcmSys.Warning("cellGcmSetFlipMode(mode=%d)", mode); + + switch(mode) + { + case CELL_GCM_DISPLAY_HSYNC: + case CELL_GCM_DISPLAY_VSYNC: + case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE: + Emu.GetGSManager().GetRender().m_flip_mode = mode; + break; + + default: + return CELL_EINVAL; + } + + return CELL_OK; +} + +u32 cellGcmGetTiledPitchSize(u32 size) { //TODO - sc_gcm.Log("cellGcmGetTiledPitchSize(size=%d)", size); + cellGcmSys.Warning("cellGcmGetTiledPitchSize(size=%d)", size); return size; -} \ No newline at end of file +} + +u32 cellGcmGetDefaultCommandWordSize() +{ + cellGcmSys.Warning("cellGcmGetDefaultCommandWordSize()"); + return 0x400; +} + +u32 cellGcmGetDefaultSegmentWordSize() +{ + cellGcmSys.Warning("cellGcmGetDefaultSegmentWordSize()"); + return 0x100; +} + +int cellGcmSetDefaultFifoSize(u32 bufferSize, u32 segmentSize) +{ + cellGcmSys.Warning("cellGcmSetDefaultFifoSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize); + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 69d782c1d7..99dba6cfca 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -29,77 +29,85 @@ struct lwmutex_attr char name[8]; }; -SysCallBase sc_lwmutex("Lwmutex"); +SysCallBase sc_lwmutex("sys_wmutex"); -//TODO -int SysCalls::Lv2LwmutexCreate(PPUThread& CPU) +int sys_lwmutex_create(u64 lwmutex_addr, u64 lwmutex_attr_addr) { - /* - //int sys_lwmutex_create(sys_lwmutex_t *lwmutex, sys_lwmutex_attribute_t *attr) - const u64 lwmutex_addr = CPU.GPR[3]; - const u64 lwmutex_attr_addr = CPU.GPR[4]; + lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; + lwmutex_attr& lmtx_attr = (lwmutex_attr&)Memory[lwmutex_attr_addr]; - //ConLog.Write("Lv2LwmutexCreate[r3: 0x%llx, r4: 0x%llx]", lwmutex_addr, lwmutex_attr_addr); + //sc_lwmutex.Warning("sys_lwmutex_create(lwmutex_addr = 0x%llx, lwmutex_attr_addr = 0x%llx)", lwmutex_addr, lwmutex_attr_addr); - lwmutex& lmtx = *(lwmutex*)Memory.GetMemFromAddr(lwmutex_addr); - lwmutex_attr& lmtx_attr = *(lwmutex_attr*)Memory.GetMemFromAddr(lwmutex_attr_addr); - - lmtx.lock_var.info.owner = CPU.GetId(); - lmtx.attribute = Emu.GetIdManager().GetNewID(wxString::Format("Lwmutex[%s]", lmtx_attr.name), NULL, lwmutex_addr); - */ + lmtx.lock_var.info.owner = 0; + lmtx.lock_var.info.waiter = 0; + + lmtx.attribute = Emu.GetIdManager().GetNewID(wxString::Format("lwmutex[%s]", lmtx_attr.name), nullptr, lwmutex_addr); /* ConLog.Write("r3:"); - ConLog.Write("*** lock_var[owner: 0x%x, waiter: 0x%x]", lmtx.lock_var.info.owner, lmtx.lock_var.info.waiter); - ConLog.Write("*** attribute: 0x%x", lmtx.attribute); - ConLog.Write("*** recursive_count: 0x%x", lmtx.recursive_count); - ConLog.Write("*** sleep_queue: 0x%x", lmtx.sleep_queue); + ConLog.Write("*** lock_var[owner: 0x%x, waiter: 0x%x]", re(lmtx.lock_var.info.owner), re(lmtx.lock_var.info.waiter)); + ConLog.Write("*** attribute: 0x%x", re(lmtx.attribute)); + ConLog.Write("*** recursive_count: 0x%x", re(lmtx.recursive_count)); + ConLog.Write("*** sleep_queue: 0x%x", re(lmtx.sleep_queue)); ConLog.Write("r4:"); - ConLog.Write("*** attr_protocol: 0x%x", lmtx_attr.attr_protocol); - ConLog.Write("*** attr_recursive: 0x%x", lmtx_attr.attr_recursive); + ConLog.Write("*** attr_protocol: 0x%x", re(lmtx_attr.attr_protocol)); + ConLog.Write("*** attr_recursive: 0x%x", re(lmtx_attr.attr_recursive)); ConLog.Write("*** name: %s", lmtx_attr.name); */ - - return 0; + return CELL_OK; } -int SysCalls::Lv2LwmutexDestroy(PPUThread& CPU) +int sys_lwmutex_destroy(u64 lwmutex_addr) { - /* - const u64 lwmutex_addr = CPU.GPR[3]; - //ConLog.Write("Lv2LwmutexDestroy[r3: 0x%llx]", lwmutex_addr); + //sc_lwmutex.Warning("sys_lwmutex_destroy(lwmutex_addr = 0x%llx)", lwmutex_addr); - lwmutex& lmtx = *(lwmutex*)Memory.GetMemFromAddr(lwmutex_addr); + lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; Emu.GetIdManager().RemoveID(lmtx.attribute); - //memset(Memory.GetMemFromAddr(lwmutex_addr), 0, sizeof(lwmutex)); - */ - return 0; + + return CELL_OK; } -int SysCalls::Lv2LwmutexLock(PPUThread& CPU) +int sys_lwmutex_lock(u64 lwmutex_addr, u64 timeout) { - //int sys_lwmutex_lock(sys_lwmutex_t *lwmutex, usecond_t timeout) - const u64 lwmutex_addr = CPU.GPR[3]; - const u64 timeout = CPU.GPR[4]; - //ConLog.Write("Lv2LwmutexLock[r3: 0x%llx, r4: 0x%llx]", lwmutex_addr, timeout); + //sc_lwmutex.Warning("sys_lwmutex_lock(lwmutex_addr = 0x%llx, timeout = 0x%llx)", lwmutex_addr, timeout); - //lwmutex& lmtx = *(lwmutex*)Memory.GetMemFromAddr(lwmutex_addr); - //lmtx.lock_var.info.waiter = CPU.GetId(); + lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; - return 0;//CELL_ESRCH; + if(!lmtx.lock_var.info.owner) + { + re(lmtx.lock_var.info.owner, GetCurrentPPUThread().GetId()); + } + else if(!lmtx.lock_var.info.waiter) + { + re(lmtx.lock_var.info.waiter, GetCurrentPPUThread().GetId()); + while(re(lmtx.lock_var.info.owner) != GetCurrentPPUThread().GetId()) Sleep(1); + } + else + { + return -1; + } + + return CELL_OK; } -int SysCalls::Lv2LwmutexTrylock(PPUThread& CPU) +int sys_lwmutex_trylock(u64 lwmutex_addr) { - //int sys_lwmutex_trylock(sys_lwmutex_t *lwmutex) - const u64 lwmutex_addr = CPU.GPR[3]; - //ConLog.Write("Lv2LwmutexTrylock[r3: 0x%llx]", lwmutex_addr); - return 0; + //sc_lwmutex.Warning("sys_lwmutex_trylock(lwmutex_addr = 0x%llx)", lwmutex_addr); + + lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; + + if(lmtx.lock_var.info.owner) return CELL_EBUSY; + + return CELL_OK; } -int SysCalls::Lv2LwmutexUnlock(PPUThread& CPU) +int sys_lwmutex_unlock(u64 lwmutex_addr) { - //int sys_lwmutex_unlock(sys_lwmutex_t *lwmutex) - const u64 lwmutex_addr = CPU.GPR[3]; - //ConLog.Write("Lv2LwmutexUnlock[r3: 0x%llx]", lwmutex_addr); - return 0; + //sc_lwmutex.Warning("sys_lwmutex_unlock(lwmutex_addr = 0x%llx)", lwmutex_addr); + + lwmutex& lmtx = (lwmutex&)Memory[lwmutex_addr]; + lmtx.lock_var.info.owner = lmtx.lock_var.info.waiter; + lmtx.lock_var.info.waiter = 0; + + return CELL_OK; } + diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp index 1ad20fe42b..44981568ac 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Memory.cpp @@ -201,6 +201,62 @@ int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr) return CELL_OK; } +int sys_memory_free(u32 start_addr) +{ + sc_mem.Log("sys_memory_free(start_addr=0x%x)", start_addr); + + if(!Memory.Free(start_addr)) return CELL_EFAULT; + + return CELL_OK; +} + +struct mmapper_info +{ + u32 size; + u32 flags; + + mmapper_info(u32 _size, u32 _flags) + : size(_size) + , flags(_flags) + { + } + + mmapper_info() + { + } +}; + +int sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_addr) +{ + sc_mem.Warning("sys_mmapper_allocate_address(size=0x%x, flags=0x%llx, alignment=0x%x, alloc_addr=0x%x)", size, flags, alignment, alloc_addr); + + Memory.Write32(alloc_addr, Memory.Alloc(size, 4)); + + return CELL_OK; +} + +int sys_mmapper_allocate_memory(u32 size, u64 flags, u32 mem_id_addr) +{ + sc_mem.Warning("sys_mmapper_allocate_memory(size=0x%x, flags=0x%llx, mem_id_addr=0x%x)", size, flags, mem_id_addr); + + if(!Memory.IsGoodAddr(mem_id_addr)) return CELL_EFAULT; + Memory.Write32(mem_id_addr, sc_mem.GetNewId(new mmapper_info(size, flags))); + + return CELL_OK; +} + +int sys_mmapper_map_memory(u32 start_addr, u32 mem_id, u64 flags) +{ + sc_mem.Warning("sys_mmapper_map_memory(start_addr=0x%x, mem_id=0x%x, flags=0x%llx)", start_addr, mem_id, flags); + + mmapper_info* info; + if(!sc_mem.CheckId(mem_id, info)) return CELL_ESRCH; + + //Memory.MemoryBlocks.Add((new MemoryBlock())->SetRange(start_addr, info->size)); + + return CELL_OK; +} + struct sys_memory_info { u32 total_user_memory; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp new file mode 100644 index 0000000000..b700ec7ae3 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.cpp @@ -0,0 +1,78 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" +#include "SC_Mutex.h" + +SysCallBase sys_mtx("sys_mutex"); + +int sys_mutex_create(u32 mutex_id_addr, u32 attr_addr) +{ + sys_mtx.Log("sys_mutex_create(mutex_id_addr=0x%x, attr_addr=0x%x)", + mutex_id_addr, attr_addr); + + if(!Memory.IsGoodAddr(mutex_id_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT; + + mutex_attr attr = (mutex_attr&)Memory[attr_addr]; + attr.protocol = re(attr.protocol); + attr.recursive = re(attr.recursive); + attr.pshared = re(attr.pshared); + attr.adaptive = re(attr.adaptive); + attr.ipc_key = re(attr.ipc_key); + attr.flags = re(attr.flags); + + sys_mtx.Log("*** protocol = %d", attr.protocol); + sys_mtx.Log("*** recursive = %d", attr.recursive); + sys_mtx.Log("*** pshared = %d", attr.pshared); + sys_mtx.Log("*** ipc_key = 0x%llx", attr.ipc_key); + sys_mtx.Log("*** flags = 0x%x", attr.flags); + sys_mtx.Log("*** name = %s", attr.name); + + Memory.Write32(mutex_id_addr, sys_mtx.GetNewId(new mutex(attr))); + + return CELL_OK; +} + +int sys_mutex_destroy(u32 mutex_id) +{ + sys_mtx.Log("sys_mutex_destroy(mutex_id=0x%x)", mutex_id); + + if(!sys_mtx.CheckId(mutex_id)) return CELL_ESRCH; + + Emu.GetIdManager().RemoveID(mutex_id); + return CELL_OK; +} + +int sys_mutex_lock(u32 mutex_id, u64 timeout) +{ + sys_mtx.Log("sys_mutex_lock(mutex_id=0x%x, timeout=0x%llx)", mutex_id, timeout); + + mutex* mtx_data = nullptr; + if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; + + mtx_data->mtx.Lock(); + + return CELL_OK; +} + +int sys_mutex_trylock(u32 mutex_id) +{ + sys_mtx.Log("sys_mutex_trylock(mutex_id=0x%x)", mutex_id); + + mutex* mtx_data = nullptr; + if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; + + if(mtx_data->mtx.TryLock()) return 1; + + return CELL_OK; +} + +int sys_mutex_unlock(u32 mutex_id) +{ + sys_mtx.Log("sys_mutex_unlock(mutex_id=0x%x)", mutex_id); + + mutex* mtx_data = nullptr; + if(!sys_mtx.CheckId(mutex_id, mtx_data)) return CELL_ESRCH; + + mtx_data->mtx.Unlock(); + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h new file mode 100644 index 0000000000..b191061889 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Mutex.h @@ -0,0 +1,25 @@ +#pragma once + +struct mutex_attr +{ + u32 protocol; + u32 recursive; + u32 pshared; + u32 adaptive; + u64 ipc_key; + int flags; + u32 pad; + char name[8]; +}; + +struct mutex +{ + wxMutex mtx; + mutex_attr attr; + + mutex(const mutex_attr& attr) + : mtx() + , attr(attr) + { + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp index 8b511aa62e..eddf0ec52e 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_PPU_Thread.cpp @@ -1,126 +1,135 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" +extern Module sysPrxForUser; + #define PPU_THREAD_ID_INVALID 0xFFFFFFFFU -int SysCalls::lv2PPUThreadCreate(PPUThread& CPU) +int sys_ppu_thread_exit(int errorcode) { - ConLog.Write("lv2PPUThreadCreate:"); - //ConLog.Write("**** id: %d", CPU.GPR[3]); - ConLog.Write("**** entry: 0x%x", CPU.GPR[4]); - ConLog.Write("**** arg: 0x%x", CPU.GPR[5]); - ConLog.Write("**** prio: 0x%x", CPU.GPR[6]); - ConLog.Write("**** stacksize: 0x%x", CPU.GPR[7]); - ConLog.Write("**** flags: 0x%x", CPU.GPR[8]); - ConLog.Write("**** threadname: \"%s\"[0x%x]", Memory.ReadString(CPU.GPR[9]), CPU.GPR[9]); + sysPrxForUser.Log("sys_ppu_thread_exit(errorcode=%d)", errorcode); + Emu.GetCPU().RemoveThread(GetCurrentPPUThread().GetId()); - if(!Memory.IsGoodAddr(CPU.GPR[4])) return CELL_EFAULT; + return CELL_OK; +} + +int sys_ppu_thread_yield() +{ + sysPrxForUser.Log("sys_ppu_thread_yield()"); + wxThread::Yield(); + + return CELL_OK; +} + +int sys_ppu_thread_join(u32 thread_id, u32 vptr_addr) +{ + sysPrxForUser.Error("sys_ppu_thread_join(thread_id=%d, vptr_addr=0x%x)", thread_id, vptr_addr); + + return CELL_OK; +} + +int sys_ppu_thread_detach(u32 thread_id) +{ + sysPrxForUser.Error("sys_ppu_thread_detach(thread_id=%d)", thread_id); + + return CELL_OK; +} + +void sys_ppu_thread_get_join_state(u32 isjoinable_addr) +{ + sysPrxForUser.Warning("sys_ppu_thread_get_join_state(isjoinable_addr=0x%x)", isjoinable_addr); + Memory.Write32(isjoinable_addr, GetCurrentPPUThread().IsJoinable()); +} + +int sys_ppu_thread_set_priority(u32 thread_id, int prio) +{ + sysPrxForUser.Warning("sys_ppu_thread_set_priority(thread_id=%d, prio=%d)", thread_id, prio); + + PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + if(!thr) return CELL_ESRCH; + + thr->SetPrio(prio); + + return CELL_OK; +} + +int sys_ppu_thread_get_priority(u32 thread_id, u32 prio_addr) +{ + sysPrxForUser.Log("sys_ppu_thread_get_priority(thread_id=%d, prio_addr=0x%x)", thread_id, prio_addr); + + PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + if(!thr) return CELL_ESRCH; + if(!Memory.IsGoodAddr(prio_addr)) return CELL_EFAULT; + + Memory.Write32(prio_addr, thr->GetPrio()); + + return CELL_OK; +} + +int sys_ppu_thread_get_stack_information(u32 info_addr) +{ + sysPrxForUser.Log("sys_ppu_thread_get_stack_information(info_addr=0x%x)", info_addr); + + if(!Memory.IsGoodAddr(info_addr)) return CELL_EFAULT; + + declCPU(); + + Memory.Write32(info_addr, CPU.GetStackAddr()); + Memory.Write32(info_addr+4, CPU.GetStackSize()); + + return CELL_OK; +} + +int sys_ppu_thread_stop(u32 thread_id) +{ + sysPrxForUser.Warning("sys_ppu_thread_stop(thread_id=%d)", thread_id); + + PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + if(!thr) return CELL_ESRCH; + + thr->Stop(); + + return CELL_OK; +} + +int sys_ppu_thread_restart(u32 thread_id) +{ + sysPrxForUser.Warning("sys_ppu_thread_restart(thread_id=%d)", thread_id); + + PPCThread* thr = Emu.GetCPU().GetThread(thread_id); + if(!thr) return CELL_ESRCH; + + thr->Stop(); + thr->Run(); + + return CELL_OK; +} + +int sys_ppu_thread_create(u32 thread_id_addr, u32 entry, u32 arg, int prio, u32 stacksize, u64 flags, u32 threadname_addr) +{ + sysPrxForUser.Log("sys_ppu_thread_create(thread_id_addr=0x%x, entry=0x%x, arg=0x%x, prio=%d, stacksize=0x%x, flags=0x%llx, threadname_addr=0x%x('%s'))", + thread_id_addr, entry, arg, prio, stacksize, flags, threadname_addr, Memory.ReadString(threadname_addr)); + + if(!Memory.IsGoodAddr(entry) || !Memory.IsGoodAddr(thread_id_addr) || !Memory.IsGoodAddr(threadname_addr)) return CELL_EFAULT; PPCThread& new_thread = Emu.GetCPU().AddThread(true); - Memory.Write32(CPU.GPR[3], new_thread.GetId()); - new_thread.SetPc(CPU.GPR[4]); - new_thread.SetArg(CPU.GPR[5]); - new_thread.SetPrio(CPU.GPR[6]); - new_thread.stack_size = CPU.GPR[7]; - //new_thread.flags = CPU.GPR[8]; - new_thread.SetName(Memory.ReadString(CPU.GPR[9])); + Memory.Write32(thread_id_addr, new_thread.GetId()); + new_thread.SetEntry(entry); + new_thread.SetArg(arg); + new_thread.SetPrio(prio); + new_thread.stack_size = stacksize; + //new_thread.flags = flags; + new_thread.SetName(Memory.ReadString(threadname_addr)); new_thread.Run(); + new_thread.Exec(); + return CELL_OK; } -int SysCalls::lv2PPUThreadExit(PPUThread& CPU) +int sys_ppu_thread_get_id() { - ConLog.Warning("PPU[%d] thread exit(%lld)", CPU.GetId(), CPU.GPR[3]); - Emu.GetCPU().RemoveThread(CPU.GetId()); - return CELL_OK; -} + sysPrxForUser.Log("sys_ppu_thread_get_id()"); -int SysCalls::lv2PPUThreadYield(PPUThread& CPU) -{ - //ConLog.Warning("TODO: PPU[%d] thread yield!", CPU.GetId()); - return CELL_OK; + return GetCurrentPPUThread().GetId(); } - -int SysCalls::lv2PPUThreadJoin(PPUThread& CPU) -{ - ConLog.Warning("TODO: PPU[%d] thread join!", CPU.GPR[3]); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadDetach(PPUThread& CPU) -{ - ConLog.Warning("PPU[%d] thread detach", CPU.GPR[3]); - if(!Emu.GetIdManager().CheckID(CPU.GPR[3])) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(CPU.GPR[3]); - if(!id.m_used) return CELL_ESRCH; - PPCThread& thread = *(PPCThread*)id.m_data; - if(thread.IsJoinable()) return CELL_EINVAL; - if(thread.IsJoining()) return CELL_EBUSY; - thread.SetJoinable(false); - if(!thread.IsRunned()) Emu.GetCPU().RemoveThread(thread.GetId()); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadGetJoinState(PPUThread& CPU) -{ - ConLog.Warning("PPU[%d] get join state", CPU.GetId()); - Memory.Write32(CPU.GPR[3], CPU.IsJoinable() ? 1 : 0); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadSetPriority(PPUThread& CPU) -{ - ConLog.Write("PPU[%d] thread set priority", CPU.GPR[3]); - if(!Emu.GetIdManager().CheckID(CPU.GPR[3])) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(CPU.GPR[3]); - CPU.SetPrio(CPU.GPR[4]); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadGetPriority(PPUThread& CPU) -{ - ConLog.Write("PPU[%d] thread get priority", CPU.GPR[3]); - if(!Emu.GetIdManager().CheckID(CPU.GPR[3])) return CELL_ESRCH; - const ID& id = Emu.GetIdManager().GetIDData(CPU.GPR[3]); - Memory.Write32(CPU.GPR[4], CPU.GetPrio()); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadGetStackInformation(PPUThread& CPU) -{ - ConLog.Write("PPU[%d] thread get stack information(0x%llx)", CPU.GetId(), CPU.GPR[3]); - Memory.Write32(CPU.GPR[3], CPU.GetStackAddr()); - Memory.Write32(CPU.GPR[3]+4, CPU.GetStackSize()); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadRename(PPUThread& CPU) -{ - ConLog.Write("PPU[%d] thread rename(%s)", CPU.GPR[3], Memory.ReadString(CPU.GPR[4])); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadRecoverPageFault(PPUThread& CPU) -{ - ConLog.Warning("TODO: PPU[%d] thread recover page fault!", CPU.GPR[3]); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadGetPageFaultContext(PPUThread& CPU) -{ - ConLog.Warning("TODO: PPU[%d] thread get page fault context!", CPU.GPR[3]); - return CELL_OK; -} - -int SysCalls::lv2PPUThreadGetId(PPUThread& CPU) -{ - //ConLog.Write("PPU[%d] thread get id(0x%llx)", CPU.GetId(), CPU.GPR[3]); - Memory.Write64(CPU.GPR[3], CPU.GetId()); - return CELL_OK; -} - -int sys_spu_thread_once(u64 once_ctrl_addr, u64 init_addr) -{ - return 0; -} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp index 677cd60635..ca1761ed7b 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Pad.cpp @@ -2,7 +2,7 @@ #include "Emu/Io/Pad.h" #include "Emu/SysCalls/SysCalls.h" -SysCallBase sc_pad("cellPad"); +extern Module sys_io; enum CELL_PAD_ERROR_CODE { @@ -37,7 +37,7 @@ struct CellPadInfo2 int cellPadInit(u32 max_connect) { - sc_pad.Log("cellPadInit(max_connect=%d)", max_connect); + sys_io.Log("cellPadInit(max_connect=%d)", max_connect); if(Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_ALREADY_INITIALIZED; Emu.GetPadManager().Init(max_connect); return CELL_OK; @@ -45,7 +45,7 @@ int cellPadInit(u32 max_connect) int cellPadEnd() { - sc_pad.Log("cellPadEnd()"); + sys_io.Log("cellPadEnd()"); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; Emu.GetPadManager().Close(); return CELL_OK; @@ -53,7 +53,7 @@ int cellPadEnd() int cellPadClearBuf(u32 port_no) { - sc_pad.Log("cellPadClearBuf(port_no=%d)", port_no); + sys_io.Log("cellPadClearBuf(port_no=%d)", port_no); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= Emu.GetPadManager().GetPads().GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; @@ -120,7 +120,7 @@ int cellPadGetData(u32 port_no, u32 data_addr) int cellPadGetDataExtra(u32 port_no, u32 device_type_addr, u32 data_addr) { - sc_pad.Log("cellPadGetDataExtra(port_no=%d, device_type_addr=0x%x, device_type_addr=0x%x)", port_no, device_type_addr, data_addr); + sys_io.Log("cellPadGetDataExtra(port_no=%d, device_type_addr=0x%x, device_type_addr=0x%x)", port_no, device_type_addr, data_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= Emu.GetPadManager().GetPads().GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; return CELL_OK; @@ -128,7 +128,7 @@ int cellPadGetDataExtra(u32 port_no, u32 device_type_addr, u32 data_addr) int cellPadSetActDirect(u32 port_no, u32 param_addr) { - sc_pad.Log("cellPadSetActDirect(port_no=%d, param_addr=0x%x)", port_no, param_addr); + sys_io.Log("cellPadSetActDirect(port_no=%d, param_addr=0x%x)", port_no, param_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; if(port_no >= Emu.GetPadManager().GetPads().GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; return CELL_OK; @@ -136,7 +136,7 @@ int cellPadSetActDirect(u32 port_no, u32 param_addr) int cellPadGetInfo2(u32 info_addr) { - sc_pad.Log("cellPadGetInfo2(info_addr=0x%x)", info_addr); + sys_io.Log("cellPadGetInfo2(info_addr=0x%x)", info_addr); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; CellPadInfo2 info; @@ -165,7 +165,7 @@ int cellPadGetInfo2(u32 info_addr) int cellPadSetPortSetting(u32 port_no, u32 port_setting) { - sc_pad.Log("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); + sys_io.Log("cellPadSetPortSetting(port_no=%d, port_setting=0x%x)", port_no, port_setting); if(!Emu.GetPadManager().IsInited()) return CELL_PAD_ERROR_UNINITIALIZED; Array& pads = Emu.GetPadManager().GetPads(); if(port_no >= pads.GetCount()) return CELL_PAD_ERROR_INVALID_PARAMETER; diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp index 04ecd0f15e..8f0a127121 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Process.cpp @@ -8,26 +8,27 @@ int sys_process_getpid() return 1; } +int sys_process_exit(int errorcode) +{ + ConLog.Warning("sys_process_exit(%d)", errorcode); + Emu.Pause(); + return CELL_OK; +} + int sys_game_process_exitspawn( u32 path_addr, u32 argv_addr, u32 envp_addr, u32 data, u32 data_size, int prio, u64 flags ) { sc_p.Log("sys_game_process_exitspawn: "); sc_p.Log("path: %s", Memory.ReadString(path_addr)); - sc_p.Log("argv: %x", Memory.Read32(argv_addr)); - sc_p.Log("envp: %x", Memory.Read32(envp_addr)); - sc_p.Log("data: %x", data); - sc_p.Log("data_size: %x", data_size); + sc_p.Log("argv: 0x%x", Memory.Read32(argv_addr)); + sc_p.Log("envp: 0x%x", Memory.Read32(envp_addr)); + sc_p.Log("data: 0x%x", data); + sc_p.Log("data_size: 0x%x", data_size); sc_p.Log("prio: %d", prio); sc_p.Log("flags: %d", flags); return CELL_OK; } -int SysCalls::lv2ProcessGetPid(PPUThread& CPU) -{ - ConLog.Warning("lv2ProcessGetPid"); - Memory.Write32(CPU.GPR[4], CPU.GetId()); - return CELL_OK; -} int SysCalls::lv2ProcessWaitForChild(PPUThread& CPU) { ConLog.Warning("lv2ProcessWaitForChild"); @@ -69,12 +70,14 @@ int SysCalls::lv2ProcessKill(PPUThread& CPU) CPU.Close(); return CELL_OK; } +/* int SysCalls::lv2ProcessExit(PPUThread& CPU) { ConLog.Warning("lv2ProcessExit(%lld)", CPU.GPR[3]); Emu.Pause(); return CELL_OK; } +*/ int SysCalls::lv2ProcessWaitForChild2(PPUThread& CPU) { ConLog.Warning("lv2ProcessWaitForChild2[r3: 0x%llx, r4: 0x%llx, r5: 0x%llx, r6: 0x%llx, r7: 0x%llx, r8: 0x%llx]", diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Resc.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Resc.cpp index 2b2c572c99..499e93885d 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Resc.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Resc.cpp @@ -15,8 +15,16 @@ struct CellRescSrc int cellRescSetSrc(const int idx, const u32 src_addr) { sc_resc.Warning("cellRescSetSrc(idx=0x%x, src_addr=0x%x)", idx, src_addr); - const CellRescSrc& src = *(CellRescSrc*)Memory.GetMemFromAddr(src_addr); - sc_resc.Warning(" *** format=%d", src.format); + if(!Memory.IsGoodAddr(src_addr, sizeof(CellRescSrc))) return CELL_EFAULT; + + CellRescSrc src = (CellRescSrc&)Memory[src_addr]; + re(src.format, src.format); + re(src.pitch, src.pitch); + re(src.width, src.width); + re(src.height, src.height); + re(src.offset, src.offset); + + sc_resc.Warning(" *** format=0x%x", src.format); sc_resc.Warning(" *** pitch=%d", src.pitch); sc_resc.Warning(" *** width=%d", src.width); sc_resc.Warning(" *** height=%d", src.height); diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp index 060c0ba2f4..7e3ba1b5d5 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SPU_Thread.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" +#include "Loader/ELF.h" SysCallBase sc_spu("sys_spu"); @@ -11,6 +12,34 @@ struct sys_spu_thread_group_attribute union{u32 ct;} option; }; +struct sys_spu_image +{ + u32 type; + u32 entry_point; + u32 segs_addr; + int nsegs; +}; + +u32 LoadImage(vfsStream& stream) +{ + ELFLoader l(stream); + l.LoadInfo(); + l.LoadData(Memory.MainMem.Alloc(stream.GetSize())); + + return l.GetEntry(); +} + + int sys_spu_image_open(u32 img_addr, u32 path_addr) + { + const wxString& path = Memory.ReadString(path_addr); + sc_spu.Warning("sys_spu_image_open(img_addr=0x%x, path_addr=0x%x [%s])", img_addr, path_addr, path); + + vfsLocalFile stream(path); + LoadImage(stream); + + return CELL_OK; + } + //170 int sys_spu_thread_group_create(u64 id_addr, u32 num, int prio, u64 attr_addr) { @@ -45,11 +74,11 @@ int sys_spu_thread_create(u64 thread_id_addr, u64 entry_addr, u64 arg, //160 int sys_raw_spu_create(u32 id_addr, u32 attr_addr) { - sc_spu.Log("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id_addr, attr_addr); + sc_spu.Warning("sys_raw_spu_create(id_addr=0x%x, attr_addr=0x%x)", id_addr, attr_addr); - PPCThread& new_thread = Emu.GetCPU().AddThread(false); - Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); - Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(false, new_thread.GetId())); + //PPCThread& new_thread = Emu.GetCPU().AddThread(false); + //Emu.GetIdManager().GetNewID("sys_raw_spu", new u32(attr_addr)); + //Memory.Write32(id_addr, Emu.GetCPU().GetThreadNumById(false, new_thread.GetId())); return CELL_OK; } @@ -57,7 +86,7 @@ int sys_raw_spu_create(u32 id_addr, u32 attr_addr) //169 int sys_spu_initialize(u32 max_usable_spu, u32 max_raw_spu) { - sc_spu.Log("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu); + sc_spu.Warning("sys_spu_initialize(max_usable_spu=%d, max_raw_spu=%d)", max_usable_spu, max_raw_spu); if(!Memory.InitSpuRawMem(max_raw_spu)) { diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp new file mode 100644 index 0000000000..8b11792c2a --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_Semaphore.cpp @@ -0,0 +1,96 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" + +SysCallBase sys_sem("sys_semaphore"); + +struct semaphore_attr +{ + u32 protocol; + u32 pshared; + u64 ipc_key; + int flags; + u32 pad; + char name[8]; +}; + +struct semaphore +{ + wxSemaphore sem; + semaphore_attr attr; + + semaphore(int initial_count, int max_count, semaphore_attr attr) + : sem(initial_count, max_count) + , attr(attr) + { + } +}; + +int sys_semaphore_create(u32 sem_addr, u32 attr_addr, int initial_count, int max_count) +{ + sys_sem.Log("sys_semaphore_create(sem_addr=0x%x, attr_addr=0x%x, initial_count=%d, max_count=%d)", + sem_addr, attr_addr, initial_count, max_count); + + if(!Memory.IsGoodAddr(sem_addr) || !Memory.IsGoodAddr(attr_addr)) return CELL_EFAULT; + + semaphore_attr attr = (semaphore_attr&)Memory[attr_addr]; + attr.protocol = re(attr.protocol); + attr.pshared = re(attr.pshared); + attr.ipc_key = re(attr.ipc_key); + attr.flags = re(attr.flags); + + sys_sem.Log("*** protocol = %d", attr.protocol); + sys_sem.Log("*** pshared = %d", attr.pshared); + sys_sem.Log("*** ipc_key = 0x%llx", attr.ipc_key); + sys_sem.Log("*** flags = 0x%x", attr.flags); + sys_sem.Log("*** name = %s", attr.name); + + Memory.Write32(sem_addr, sys_sem.GetNewId(new semaphore(initial_count, max_count, attr))); + + return CELL_OK; +} + +int sys_semaphore_destroy(u32 sem) +{ + sys_sem.Log("sys_semaphore_destroy(sem=0x%x)", sem); + + if(!sys_sem.CheckId(sem)) return CELL_ESRCH; + + Emu.GetIdManager().RemoveID(sem); + return CELL_OK; +} + +int sys_semaphore_wait(u32 sem, u64 timeout) +{ + sys_sem.Log("sys_semaphore_wait(sem=0x%x, timeout=0x%llx)", sem, timeout); + + semaphore* sem_data = nullptr; + if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; + + sem_data->sem.WaitTimeout(timeout ? timeout : INFINITE); + + return CELL_OK; +} + +int sys_semaphore_trywait(u32 sem) +{ + sys_sem.Log("sys_semaphore_trywait(sem=0x%x)", sem); + + semaphore* sem_data = nullptr; + if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; + + if(sem_data->sem.TryWait()) return 1; + + return CELL_OK; +} + +int sys_semaphore_post(u32 sem, int count) +{ + sys_sem.Log("sys_semaphore_post(sem=0x%x, count=%d)", sem, count); + + semaphore* sem_data = nullptr; + if(!sys_sem.CheckId(sem, sem_data)) return CELL_ESRCH; + + while(count--) sem_data->sem.Post(); + + return CELL_OK; +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp index c8f64fe83f..b7d672f286 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil.cpp @@ -48,53 +48,157 @@ int cellVideoOutGetResolution(u32 resolutionId, u32 resolution_addr) sc_v.Log("cellVideoOutGetResolution(resolutionId=%d, resolution_addr=0x%x)", resolutionId, resolution_addr); - CellVideoOutResolution res = {0, 0}; - - switch(resolutionId) + if(!Memory.IsGoodAddr(resolution_addr, sizeof(CellVideoOutResolution))) { - case CELL_VIDEO_OUT_RESOLUTION_1080: - res.width = re16(1920); - res.height = re16(1080); - break; + return CELL_EFAULT; + } + + u32 num = ResolutionIdToNum(resolutionId); - case CELL_VIDEO_OUT_RESOLUTION_720: - res.width = re16(1280); - res.height = re16(720); - break; - - case CELL_VIDEO_OUT_RESOLUTION_480: - res.width = re16(720); - res.height = re16(480); - break; - - case CELL_VIDEO_OUT_RESOLUTION_576: - res.width = re16(720); - res.height = re16(576); - break; - - case CELL_VIDEO_OUT_RESOLUTION_1600x1080: - res.width = re16(1600); - res.height = re16(1080); - break; - - case CELL_VIDEO_OUT_RESOLUTION_1440x1080: - res.width = re16(1440); - res.height = re16(1080); - break; - - case CELL_VIDEO_OUT_RESOLUTION_1280x1080: - res.width = re16(1280); - res.height = re16(1080); - break; - - case CELL_VIDEO_OUT_RESOLUTION_960x1080: - res.width = re16(960); - res.height = re16(1080); - break; - - default: return CELL_EINVAL; + if(!num) + { + return CELL_EINVAL; } + CellVideoOutResolution res; + re(res.width, ResolutionTable[num].width); + re(res.height, ResolutionTable[num].height); + Memory.WriteData(resolution_addr, res); + + return CELL_VIDEO_OUT_SUCCEEDED; +} + +int cellVideoOutConfigure(u32 videoOut, u32 config_addr, u32 option_addr, u32 waitForEvent) +{ + sc_v.Warning("cellVideoOutConfigure(videoOut=%d, config_addr=0x%x, option_addr=0x%x, waitForEvent=0x%x)", + videoOut, config_addr, option_addr, waitForEvent); + + if(!Memory.IsGoodAddr(config_addr, sizeof(CellVideoOutConfiguration))) + { + return CELL_EFAULT; + } + + CellVideoOutConfiguration& config = (CellVideoOutConfiguration&)Memory[config_addr]; + + switch(videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: + if(config.resolutionId) + { + Emu.GetGSManager().GetInfo().mode.resolutionId = config.resolutionId; + } + + Emu.GetGSManager().GetInfo().mode.format = config.format; + + if(config.aspect) + { + Emu.GetGSManager().GetInfo().mode.aspect = config.aspect; + } + + if(config.pitch) + { + Emu.GetGSManager().GetInfo().mode.pitch = re(config.pitch); + } + + return CELL_VIDEO_OUT_SUCCEEDED; + + case CELL_VIDEO_OUT_SECONDARY: + return CELL_VIDEO_OUT_SUCCEEDED; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +int cellVideoOutGetConfiguration(u32 videoOut, u32 config_addr, u32 option_addr) +{ + sc_v.Warning("cellVideoOutGetConfiguration(videoOut=%d, config_addr=0x%x, option_addr=0x%x)", + videoOut, config_addr, option_addr); + + if(!Memory.IsGoodAddr(config_addr, sizeof(CellVideoOutConfiguration))) return CELL_EFAULT; + + CellVideoOutConfiguration config; + memset(&config, 0, sizeof(CellVideoOutConfiguration)); + + switch(videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: + config.resolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; + config.format = Emu.GetGSManager().GetInfo().mode.format; + config.aspect = Emu.GetGSManager().GetInfo().mode.aspect; + config.pitch = re(Emu.GetGSManager().GetInfo().mode.pitch); + + Memory.WriteData(config_addr, config); + + return CELL_VIDEO_OUT_SUCCEEDED; + + case CELL_VIDEO_OUT_SECONDARY: + Memory.WriteData(config_addr, config); + + return CELL_VIDEO_OUT_SUCCEEDED; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +int cellVideoOutGetNumberOfDevice(u32 videoOut) +{ + sc_v.Warning("cellVideoOutGetNumberOfDevice(videoOut=%d)", videoOut); + + switch(videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: return 1; + case CELL_VIDEO_OUT_SECONDARY: return 0; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +int cellVideoOutGetResolutionAvailability(u32 videoOut, u32 resolutionId, u32 aspect, u32 option) +{ + sc_v.Warning("cellVideoOutGetResolutionAvailability(videoOut=%d, resolutionId=0x%x, option_addr=0x%x, aspect=0x%x, option=0x%x)", + videoOut, resolutionId, aspect, option); + + if(!ResolutionIdToNum(resolutionId)) + { + return CELL_EINVAL; + } + + switch(videoOut) + { + case CELL_VIDEO_OUT_PRIMARY: return 1; + case CELL_VIDEO_OUT_SECONDARY: return 0; + } + + return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; +} + +SysCallBase sc_sysutil("cellSysutil"); + +int cellSysutilCheckCallback() +{ + //sc_sysutil.Warning("cellSysutilCheckCallback()"); + Emu.GetCallbackManager().m_exit_callback.Check(); + + return CELL_OK; +} + +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(); + + return CELL_OK; +} + +int cellSysutilUnregisterCallback(int slot) +{ + sc_sysutil.Warning("cellSysutilUnregisterCallback(slot=%d)", slot); + Emu.GetCallbackManager().m_exit_callback.Unregister(slot); + + wxGetApp().m_MainFrame->UpdateUI(); + return CELL_OK; } \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_SysUtil_MsgDialog.cpp b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil_MsgDialog.cpp new file mode 100644 index 0000000000..9ffc858806 --- /dev/null +++ b/rpcs3/Emu/SysCalls/lv2/SC_SysUtil_MsgDialog.cpp @@ -0,0 +1,76 @@ +#include "stdafx.h" +#include "Emu/SysCalls/SysCalls.h" + +SysCallBase sc_md("cellMsgDialog"); + +enum +{ + CELL_MSGDIALOG_BUTTON_NONE = -1, + CELL_MSGDIALOG_BUTTON_INVALID = 0, + CELL_MSGDIALOG_BUTTON_OK = 1, + CELL_MSGDIALOG_BUTTON_YES = 1, + CELL_MSGDIALOG_BUTTON_NO = 2, + CELL_MSGDIALOG_BUTTON_ESCAPE = 3, +}; + +enum CellMsgDialogType +{ + CELL_MSGDIALOG_DIALOG_TYPE_ERROR = 0x00000000, + CELL_MSGDIALOG_DIALOG_TYPE_NORMAL = 0x00000001, + + CELL_MSGDIALOG_BUTTON_TYPE_NONE = 0x00000000, + CELL_MSGDIALOG_BUTTON_TYPE_YESNO = 0x00000010, + + CELL_MSGDIALOG_DEFAULT_CURSOR_YES = 0x00000000, + CELL_MSGDIALOG_DEFAULT_CURSOR_NO = 0x00000100, +}; + +int cellMsgDialogOpen2(u32 type, u32 msgString_addr, u32 callback_addr, u32 userData, u32 extParam) +{ + long style = 0; + + if(type & CELL_MSGDIALOG_DIALOG_TYPE_NORMAL) + { + style |= wxICON_EXCLAMATION; + } + else + { + style |= wxICON_ERROR; + } + + if(type & CELL_MSGDIALOG_BUTTON_TYPE_YESNO) + { + style |= wxYES_NO; + } + else + { + style |= wxOK; + } + + int res = wxMessageBox(Memory.ReadString(msgString_addr), wxGetApp().GetAppName(), style); + + u64 status; + + switch(res) + { + case wxOK: status = CELL_MSGDIALOG_BUTTON_OK; break; + case wxYES: status = CELL_MSGDIALOG_BUTTON_YES; break; + case wxNO: status = CELL_MSGDIALOG_BUTTON_NO; break; + + default: + if(res) + { + status = CELL_MSGDIALOG_BUTTON_INVALID; + break; + } + + status = CELL_MSGDIALOG_BUTTON_NONE; + break; + } + + Callback2 callback(0, callback_addr, userData); + callback.Handle(status); + callback.Branch(); + + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp b/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp index 9fb5f6aa46..52f6ec1573 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_TTY.cpp @@ -1,28 +1,18 @@ #include "stdafx.h" #include "Emu/SysCalls/SysCalls.h" -int SysCalls::lv2TtyRead(PPUThread& CPU) +int sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr) { - const u32 ch = CPU.GPR[3]; - const u64 buf_addr = CPU.GPR[4]; - const u32 len = CPU.GPR[5]; - const u64 preadlen_addr = CPU.GPR[6]; - ConLog.Warning("lv2TtyRead: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); + ConLog.Warning("sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); Memory.Write32NN(preadlen_addr, len); return CELL_OK; } -int SysCalls::lv2TtyWrite(PPUThread& CPU) +int sys_tty_write(u32 ch, u64 buf_addr, u32 len, u64 pwritelen_addr) { - const u32 ch = CPU.GPR[3]; - const u64 buf_addr = CPU.GPR[4]; - const u32 len = CPU.GPR[5]; - const u64 pwritelen_addr = CPU.GPR[6]; - //for(uint i=0; i<32; ++i) ConLog.Write("r%d = 0x%llx", i, CPU.GPR[i]); - //ConLog.Warning("lv2TtyWrite: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); if(ch < 0 || ch > 15 || len <= 0) return CELL_EINVAL; - if(!Memory.IsGoodAddr(buf_addr)) return CELL_EINVAL; + if(!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT; Emu.GetDbgCon().Write(ch, Memory.ReadString(buf_addr, len)); @@ -31,4 +21,4 @@ int SysCalls::lv2TtyWrite(PPUThread& CPU) Memory.Write32(pwritelen_addr, len); return CELL_OK; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp index b74c863920..503e177dd3 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Time.cpp @@ -8,11 +8,11 @@ static const u64 timebase_frequency = 79800000; int sys_time_get_current_time(u32 sec_addr, u32 nsec_addr) { sys_time.Log("sys_time_get_current_time(sec_addr=0x%x, nsec_addr=0x%x)", sec_addr, nsec_addr); - __timeb64 cur_time; - _ftime64_s(&cur_time); - Memory.Write64(sec_addr, cur_time.time); - Memory.Write64(nsec_addr, (u64)cur_time.millitm * 1000000); + u64 time = sys_time_get_system_time(); + + Memory.Write64(sec_addr, time / 1000000); + Memory.Write64(nsec_addr, time % 1000000); return CELL_OK; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 66ed66a645..7466f5540b 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -6,10 +6,11 @@ #include "Emu/Cell/PPCThreadManager.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" +#include "Gui/CompilerELF.h" -#include "Emu/SysCalls/SysCalls.h" +using namespace PPU_opcodes; -SysCalls SysCallsManager; +//SysCalls SysCallsManager; Emulator::Emulator() : m_status(Stopped) @@ -55,7 +56,7 @@ void Emulator::CheckStatus() } if(IsAllPaused) { - ConLog.Warning("all paused!"); + //ConLog.Warning("all paused!"); Pause(); return; } @@ -69,41 +70,41 @@ void Emulator::CheckStatus() } if(IsAllStoped) { - ConLog.Warning("all stoped!"); + //ConLog.Warning("all stoped!"); Pause(); //Stop(); } } -void Emulator::Run() +void Emulator::Load() { - if(IsRunned()) Stop(); - if(IsPaused()) - { - Resume(); - return; - } - - //ConLog.Write("run..."); - m_status = Runned; - + if(!wxFileExists(m_path)) return; + ConLog.Write("loading '%s'...", m_path); Memory.Init(); - GetInfo().Reset(); - //SetTLSData(0, 0, 0); - //SetMallocPageSize(0x100000); - - Loader l(m_path); - if(!l.Load()) + Memory.Write64(Memory.PRXMem.Alloc(8), 0xDEADBEEFABADCAFE); + + bool is_error; + vfsLocalFile f(m_path); + Loader l(f); + + try { - Memory.Close(); - Stop(); - return; + is_error = !l.Load() || l.GetMachine() == MACHINE_Unknown; } - - if(l.GetMachine() == MACHINE_Unknown) + catch(const wxString& e) + { + ConLog.Error(e); + is_error = true; + } + catch(...) + { + ConLog.Error("Unhandled loader error."); + is_error = true; + } + + if(is_error) { - ConLog.Error("Unknown machine type"); Memory.Close(); Stop(); return; @@ -111,38 +112,76 @@ void Emulator::Run() PPCThread& thread = GetCPU().AddThread(l.GetMachine() == MACHINE_PPC64); - Memory.MainMem.Alloc(0x10000000, 0x10010000); - Memory.PRXMem.Write64(Memory.PRXMem.GetStartAddr(), 0xDEADBEEFABADCAFE); - - thread.SetPc(l.GetEntry()); + thread.SetEntry(l.GetEntry()); thread.SetArg(thread.GetId()); Memory.StackMem.Alloc(0x1000); thread.InitStack(); thread.AddArgv(m_path); //thread.AddArgv("-emu"); - m_rsx_callback = Memory.MainMem.Alloc(0x10) + 4; + m_rsx_callback = Memory.MainMem.Alloc(4 * 4) + 4; 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); + + 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); + thread.Run(); + wxGetApp().m_MainFrame->UpdateUI(); + wxCriticalSectionLocker lock(m_cs_status); + m_status = Ready; +} + +void Emulator::Run() +{ + if(!IsReady()) + { + Load(); + if(!IsReady()) return; + } + + if(IsRunned()) Stop(); + if(IsPaused()) + { + Resume(); + return; + } + + wxCriticalSectionLocker lock(m_cs_status); + //ConLog.Write("run..."); + m_status = Runned; + + m_vfs.Mount("/", vfsDevice::GetRoot(m_path), new vfsLocalFile()); + m_vfs.Mount("/dev_hdd0/", wxGetCwd() + "\\dev_hdd0\\", new vfsLocalFile()); + 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()); + //if(m_memory_viewer && m_memory_viewer->exit) safe_delete(m_memory_viewer); //m_memory_viewer->SetPC(loader.GetEntry()); //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(); GetGSManager().Init(); + GetCallbackManager().Init(); - if(Ini.CPUDecoderMode.GetValue() != 1) - { - GetCPU().Start(); - GetCPU().Exec(); - } + GetCPU().Exec(); } void Emulator::Pause() @@ -150,7 +189,9 @@ void Emulator::Pause() if(!IsRunned()) return; //ConLog.Write("pause..."); + wxCriticalSectionLocker lock(m_cs_status); m_status = Paused; + wxGetApp().SendDbgCommand(DID_PAUSE_EMU); wxGetApp().m_MainFrame->UpdateUI(); } @@ -159,7 +200,9 @@ void Emulator::Resume() if(!IsPaused()) return; //ConLog.Write("resume..."); + wxCriticalSectionLocker lock(m_cs_status); m_status = Runned; + wxGetApp().SendDbgCommand(DID_RESUME_EMU); wxGetApp().m_MainFrame->UpdateUI(); CheckStatus(); @@ -170,16 +213,22 @@ void Emulator::Stop() { if(IsStopped()) return; //ConLog.Write("shutdown..."); + { + wxCriticalSectionLocker lock(m_cs_status); + m_status = Stopped; + } m_rsx_callback = 0; - m_status = Stopped; + wxGetApp().SendDbgCommand(DID_STOP_EMU); wxGetApp().m_MainFrame->UpdateUI(); GetGSManager().Close(); GetCPU().Close(); - SysCallsManager.Close(); + //SysCallsManager.Close(); GetIdManager().Clear(); GetPadManager().Close(); + GetCallbackManager().Clear(); + UnloadModules(); CurGameInfo.Reset(); Memory.Close(); @@ -187,7 +236,7 @@ void Emulator::Stop() if(m_dbg_console) { GetDbgCon().Close(); - m_dbg_console = NULL; + GetDbgCon().Clear(); } //if(m_memory_viewer && m_memory_viewer->IsShown()) m_memory_viewer->Hide(); } diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index d3603ee12e..7834238004 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -3,9 +3,11 @@ #include "Gui/MemoryViewer.h" #include "Emu/Cell/PPCThreadManager.h" #include "Emu/Io/Pad.h" -#include "Emu/DbgConsole.h" #include "Emu/GS/GSManager.h" +#include "Emu/FS/VFS.h" +#include "Emu/DbgConsole.h" #include "Loader/Loader.h" +#include "SysCalls/Callback.h" struct EmuInfo { @@ -52,10 +54,12 @@ class Emulator Interpreter, }; + mutable wxCriticalSection m_cs_status; Status m_status; uint m_mode; u32 m_rsx_callback; + u32 m_ppu_thr_exit; MemoryViewerPanel* m_memory_viewer; //ArrayF m_cpu_threads; @@ -64,6 +68,8 @@ class Emulator IdManager m_id_manager; DbgConsole* m_dbg_console; GSManager m_gs_manager; + CallbackManager m_callback_manager; + VFS m_vfs; EmuInfo m_info; @@ -74,14 +80,16 @@ public: Emulator(); void Init(); - virtual void SetSelf(const wxString& path); - virtual void SetElf(const wxString& path); + void SetSelf(const wxString& path); + void SetElf(const wxString& path); - PPCThreadManager& GetCPU() { return m_thread_manager; } - PadManager& GetPadManager() { return m_pad_manager; } - IdManager& GetIdManager() { return m_id_manager; } - DbgConsole& GetDbgCon() { return *m_dbg_console; } - GSManager& GetGSManager() { return m_gs_manager; } + PPCThreadManager& GetCPU() { return m_thread_manager; } + PadManager& GetPadManager() { return m_pad_manager; } + IdManager& GetIdManager() { return m_id_manager; } + DbgConsole& GetDbgCon() { return *m_dbg_console; } + GSManager& GetGSManager() { return m_gs_manager; } + CallbackManager& GetCallbackManager() { return m_callback_manager; } + VFS& GetVFS() { return m_vfs; } void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) { @@ -97,17 +105,20 @@ public: u32 GetMallocPageSize() { return m_info.GetProcParam().malloc_pagesize; } u32 GetRSXCallback() const { return m_rsx_callback; } + u32 GetPPUThreadExit() const { return m_ppu_thr_exit; } void CheckStatus(); - virtual void Run(); - virtual void Pause(); - virtual void Resume(); - virtual void Stop(); + void Load(); + void Run(); + void Pause(); + void Resume(); + void Stop(); - virtual bool IsRunned() const { return m_status == Runned; } - virtual bool IsPaused() const { return m_status == Paused; } - virtual bool IsStopped() const { return m_status == Stopped; } + __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; } + __forceinline bool IsReady() const { wxCriticalSectionLocker lock(m_cs_status); return m_status == Ready; } }; extern Emulator Emu; \ No newline at end of file diff --git a/rpcs3/Gui/CompilerELF.cpp b/rpcs3/Gui/CompilerELF.cpp index 44ca0226f8..45ec23c010 100644 --- a/rpcs3/Gui/CompilerELF.cpp +++ b/rpcs3/Gui/CompilerELF.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "CompilerELF.h" +using namespace PPU_opcodes; void Write8(wxFile& f, const u8 data) { @@ -33,44 +34,6 @@ wxFont GetFont(int size) return wxFont(size, wxMODERN, wxNORMAL, wxNORMAL); } -u32 SetField(u32 src, u32 from, u32 to) -{ - return (src & ((1 << ((to - from) + 1)) - 1)) << (31 - to); -} - -u32 SetField(s32 src, u32 p) -{ - return (src & 0x1) << (31 - p); -} - -u32 ToOpcode(u32 i) { return SetField(i, 0, 5); } -u32 ToRS(u32 i) { return SetField(i, 6, 10); } -u32 ToRD(u32 i) { return SetField(i, 6, 10); } -u32 ToRA(u32 i) { return SetField(i, 11, 15); } -u32 ToRB(u32 i) { return SetField(i, 16, 20); } -u32 ToLL(u32 i) { return i & 0x03fffffc; } -u32 ToAA(u32 i) { return SetField(i, 30); } -u32 ToLK(u32 i) { return SetField(i, 31); } -u32 ToIMM16(s32 i) { return SetField(i, 16, 31); } -u32 ToD(s32 i) { return SetField(i, 16, 31); } -u32 ToDS(s32 i) -{ - if(i < 0) return ToD(i + 1); - return ToD(i); -} -u32 ToSYS(u32 i) { return SetField(i, 6, 31); } -u32 ToBF(u32 i) { return SetField(i, 6, 10); } -u32 ToBO(u32 i) { return SetField(i, 6, 10); } -u32 ToBI(u32 i) { return SetField(i, 11, 15); } -u32 ToBD(u32 i) { return i & 0xfffc; } -u32 ToMB(u32 i) { return SetField(i, 21, 25); } -u32 ToME(u32 i) { return SetField(i, 26, 30); } -u32 ToSH(u32 i) { return SetField(i, 16, 20); } -u32 ToRC(u32 i) { return SetField(i, 31); } -u32 ToOE(u32 i) { return SetField(i, 21); } -u32 ToL(u32 i) { return SetField(i, 10); } -u32 ToCRFD(u32 i) { return SetField(i, 6, 8); } - struct InstrField { u32 (*To)(u32 i); @@ -90,6 +53,8 @@ enum MASKS 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, @@ -126,92 +91,119 @@ static const struct Instruction { MASKS mask; wxString name; - u32 op_num; - u32 op_g; + 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}, + {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_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_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}, + {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}, + {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, - //G_1f = 0x1f, - {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}, + {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, @@ -225,8 +217,8 @@ static const struct Instruction //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}; + {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 @@ -271,6 +263,8 @@ Instruction GetInstruction(const wxString& str) u32 CompileInstruction(Instruction instr, Array& 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) | @@ -279,7 +273,9 @@ u32 CompileInstruction(Instruction instr, Array& arr) if(instr.smask & SMASK_BO) code |= ToBO(instr.bo); if(instr.smask & SMASK_BI) code |= ToBI(instr.bi); - code |= ToOpcode(instr.op_num); + 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) { @@ -299,10 +295,18 @@ u32 CompileInstruction(Instruction instr, Array& arr) 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); @@ -417,78 +421,46 @@ CompilerELF::CompilerELF(wxWindow* parent) asm_list->SetFont(wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); hex_list->SetFont(wxFont(-1, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); - wxGetApp().Connect(wxEVT_SCROLLWIN_TOP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_SCROLLWIN_LINEUP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_SCROLLWIN_THUMBRELEASE,wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_TOP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_BOTTOM, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_LINEUP, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_LINEDOWN, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_THUMBTRACK, wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_SCROLLWIN_THUMBRELEASE,wxScrollWinEventHandler(CompilerELF::OnScroll), (wxObject*)0, this); - wxGetApp().Connect(asm_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); - wxGetApp().Connect(hex_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); + m_app_connector.Connect(asm_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); + m_app_connector.Connect(hex_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(CompilerELF::MouseWheel), (wxObject*)0, this); - wxGetApp().Connect(asm_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); - wxGetApp().Connect(hex_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); + m_app_connector.Connect(asm_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); + m_app_connector.Connect(hex_list->GetId(), wxEVT_KEY_DOWN, wxKeyEventHandler(CompilerELF::OnKeyDown), (wxObject*)0, this); asm_list->WriteText( - "[sysPrxForUser, sys_initialize_tls, 0x744680a2]\n" - "[sysPrxForUser, sys_process_exit, 0xe6f2c1e7]\n" - "[sys_fs, cellFsOpen, 0x718bf5f8]\n" - "[sys_fs, cellFsClose, 0x2cb51f0d]\n" - "[sys_fs, cellFsRead, 0x4d5ff8e2]\n" - "[sys_fs, cellFsWrite, 0xecdcf2ab]\n" - "[sys_fs, cellFsLseek, 0xa397d042]\n" - "[sys_fs, cellFsMkdir, 0xba901fe6]\n" - "\n" - ".int [flags, 577] #LV2_O_WRONLY | LV2_O_CREAT | LV2_O_TRUNC\n" - ".string [path, \"dev_hdd0/game/TEST12345/USRDIR/test.txt\"]\n" - ".string [str, \"Hello World!\"]\n" + ".int [sys_tty_write, 0x193]\n" + ".int [sys_process_exit, 0x003]\n" + ".string [str, \"Hello World!\\n\"]\n" ".strlen [str_len, str]\n" - ".buf [fd, 8]\n" - "\n" - ".srr [fd_hi, fd, 16]\n" - ".and [fd_lo, fd, 0xffff]\n" - "\n" - ".srr [path_hi, path, 16]\n" - ".and [path_lo, path, 0xffff]\n" + ".buf [ret, 8]\n" "\n" ".srr [str_hi, str, 16]\n" ".and [str_lo, str, 0xffff]\n" "\n" - "\tbl \tsys_initialize_tls\n" + ".srr [ret_hi, str, 16]\n" + ".and [ret_lo, str, 0xffff]\n" "\n" - "\tli \tr3, path_lo\n" - "\toris \tr3, r3, path_hi\n" - "\tli \tr4, flags\n" - "\tli \tr5, fd_lo\n" - "\toris \tr5, r5, fd_hi\n" - "\tli \tr6, 0\n" - "\tli \tr7, 0\n" - "\tbl \tcellFsOpen\n" - "\tcmpwi \tcr7, r3, 0\n" - "\tblt- \tcr7, exit_err\n" - "\n" - "\tli \tr3, fd_lo\n" - "\toris \tr3, r3, fd_hi\n" - "\tlwz \tr3, r3, 0\n" - "\tli \tr4, str_lo\n" - "\toris \tr4, r4, str_hi\n" - "\tli \tr5, str_len\n" - "\tli \tr6, 0\n" - "\tbl \tcellFsWrite\n" - "\tcmpwi \tcr7, r3, 0\n" - "\tblt- \tcr7, exit_err\n" - "\n" - "\tli \tr3, fd_lo\n" - "\toris \tr3, r3, fd_hi\n" - "\tlwz \tr3, r3, 0\n" - "\tbl \tcellFsClose\n" - "\tcmpwi \tcr7, r3, 0\n" - "\tblt- \tcr7, exit_err\n" + " li r3, 0\n" + " li r4, str_lo\n" + " oris r4, r4, str_hi\n" + " li r5, str_len\n" + " li r6, ret_lo\n" + " oris r6, r6, ret_hi\n" + " li r11, sys_tty_write\n" + " sc\n" + " cmpwi cr7, r3, 0\n" + " bne- cr7, exit_err\n" "\n" "exit_ok:\n" - "\tli \tr3, 0\n" - "\tb \texit\n" + " li r3, 0\n" + " b exit\n" "\n" "exit_err:\n" ".string [str, \"error.\\n\"]\n" @@ -497,21 +469,21 @@ CompilerELF::CompilerELF(wxWindow* parent) ".strlen [str_len, str]\n" ".int [written_len_lo, fd_lo]\n" ".int [written_len_hi, fd_hi]\n" - "\tli \tr3, 1\n" - "\tli \tr4, str_lo\n" - "\toris \tr4, r4, str_hi\n" - "\tli \tr5, str_len\n" - "\tli \tr6, written_len_lo\n" - "\toris \tr6, r6, written_len_hi\n" - "\tli \tr11, 403\n" - "\tsc\n" - "\tli \tr3, 1\n" - "\tb \texit\n" + " li r3, 1\n" + " li r4, str_lo\n" + " oris r4, r4, str_hi\n" + " li r5, str_len\n" + " li r6, written_len_lo\n" + " oris r6, r6, written_len_hi\n" + " li r11, sys_tty_write\n" + " sc\n" + " li r3, 1\n" "\n" "exit:\n" - "\tbl \tsys_process_exit\n" - "\tli \tr3, 1\n" - "\tb \texit\n" + " li r11, sys_process_exit\n" + " sc\n" + " li r3, 1\n" + " b exit\n" ); ::SendMessage((HWND)hex_list->GetHWND(), WM_VSCROLL, SB_BOTTOM, 0); @@ -685,6 +657,8 @@ void CompilerELF::OnUpdate(wxCommandEvent& event) void CompilerELF::OnScroll(wxScrollWinEvent& event) { + if(!m_aui_mgr.GetManagedWindow()) return; + const int id = event.GetEventObject() ? ((wxScrollBar*)event.GetEventObject())->GetId() : -1; wxTextCtrl* src = NULL; @@ -960,13 +934,12 @@ struct CompileProgram return false; } - bool GetArg(wxString& result, bool func = false) + int GetArg(wxString& result, bool func = false) { s64 from = -1; - for(;;) + for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) { - const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); @@ -976,7 +949,7 @@ struct CompileProgram if(from == -1) { - if(endln || commit || end) return false; + if(endln || commit || end) return 0; if(!skip) from = p - 1; continue; } @@ -984,7 +957,7 @@ struct CompileProgram const bool text = m_asm[from] == '"'; const bool end_text = cur_char == '"'; - if((text ? end_text : skip || commit || end) || endln) + if((text ? end_text : (skip || commit || end)) || endln) { if(text && p > 2 && m_asm[p - 2] == '\\' && (p <= 3 || m_asm[p - 3] != '\\')) { @@ -997,14 +970,13 @@ struct CompileProgram m_error = true; } - const s64 to = (endln || text ? p : p - 1) - from; - bool ret = true; + const s64 to = ((endln || text) ? p : p - 1) - from; + int ret = 1; if(skip || text) { - for(;;) + for(char cur_char = NextChar(); !m_error; cur_char = NextChar()) { - const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); const bool commit = IsCommit(cur_char); const bool endln = IsEndLn(cur_char); @@ -1015,20 +987,20 @@ struct CompileProgram if(commit) { - ret = false; EndLn(); + ret = -1; break; } if(endln) { - ret = false; p--; break; } WriteError(wxString::Format("Bad symbol '%c'", cur_char)); m_error = true; + break; } } @@ -1059,11 +1031,19 @@ struct CompileProgram return ret; } } + + return 0; } bool CheckEnd(bool show_err = true) { - for(;;) + if(m_error) + { + NextLn(); + return false; + } + + while(true) { const char cur_char = NextChar(); const bool skip = IsSkip(cur_char); @@ -1266,14 +1246,15 @@ struct CompileProgram m_cur_arg = 0; wxString str; - while(GetArg(str)) + while(int r = GetArg(str)) { - Arg arg(str); - DetectArgInfo(arg); - m_args.AddCpy(arg); + Arg* arg = new Arg(str); + DetectArgInfo(*arg); + m_args.Add(arg); + if(r == -1) break; } - m_end_args = true; + m_end_args = m_args.GetCount() > 0; } u32 GetBranchValue(const wxString& branch) @@ -1444,7 +1425,7 @@ struct CompileProgram { if(create) { - m_branches.Add(new Branch(name, -1, addr)); + m_branches.Move(new Branch(name, -1, addr)); return; } @@ -1500,7 +1481,7 @@ struct CompileProgram case ARG_ERR: { - m_branches.Add(new Branch(wxEmptyString, -1, 0)); + m_branches.Move(new Branch(wxEmptyString, -1, 0)); dst_branch = &m_branches[m_branches.GetCount() - 1]; } break; @@ -1579,7 +1560,7 @@ struct CompileProgram if(!founded) { const u32 addr = s_opd.sh_addr + s_opd.sh_size; - m_sp_string.Add(new SpData(src1, addr)); + m_sp_string.Move(new SpData(src1, addr)); s_opd.sh_size += src1.Len() + 1; *dst_branch = Branch(dst, -1, addr); } @@ -1879,7 +1860,7 @@ struct CompileProgram if(!CheckEnd()) continue; - m_branches.Add(new Branch(name, a_id.value, 0)); + m_branches.Move(new Branch(name, a_id.value, 0)); const u32 import = m_branches.GetCount() - 1; bool founded = false; @@ -1891,7 +1872,7 @@ struct CompileProgram break; } - if(!founded) modules.Add(new Module(module, import)); + if(!founded) modules.Move(new Module(module, import)); } u32 imports_count = 0; @@ -2117,7 +2098,7 @@ struct CompileProgram if(m_error) break; - m_branches.Add(new Branch(name, m_branch_pos)); + m_branches.Move(new Branch(name, m_branch_pos)); CheckEnd(); continue; @@ -2136,7 +2117,7 @@ struct CompileProgram break; } - if(!has_entry) m_branches.Add(new Branch("entry", 0)); + if(!has_entry) m_branches.Move(new Branch("entry", 0)); if(m_analyze) m_error = false; FirstChar(); @@ -2202,7 +2183,7 @@ struct CompileProgram break; case ARG_REG_R: - m_args.InsertCpy(0, Arg("cr0", 0, ARG_REG_CR)); + m_args.Move(0, new Arg("cr0", 0, ARG_REG_CR)); break; } } @@ -2219,13 +2200,13 @@ struct CompileProgram case MASK_BI_BD: if(!SetNextArgType(ARG_REG_CR, false)) { - m_args.InsertCpy(0, Arg("cr0", 0, ARG_REG_CR)); + 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.AddCpy(Arg("2", 2, ARG_IMM)); + if(!SetNextArgType(ARG_IMM, false)) m_args.Move(new Arg("2", 2, ARG_IMM)); break; case MASK_LL: @@ -2248,6 +2229,18 @@ struct CompileProgram 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); @@ -2527,7 +2520,7 @@ struct CompileProgram WritePhdr(f, p_loos_2); sections_names.Clear(); - free(opd_data); + delete[] opd_data; for(u32 i=0; i #include "Ini.h" +#include +#include LogWriter ConLog; LogFrame* ConLogFrame; -wxMutex mtx_wait; + +wxCriticalSection g_cs_conlog; static const uint max_item_count = 500; static const uint buffer_size = 1024 * 64; -wxSemaphore m_conlog_sem; - struct LogPacket { wxString m_prefix; @@ -24,6 +25,7 @@ struct LogPacket , m_text(text) , m_colour(colour) { + } LogPacket() @@ -37,7 +39,7 @@ struct _LogBuffer : public MTPacketBuffer { } - void Push(const LogPacket& data) + void _push(const LogPacket& data) { const u32 sprefix = data.m_prefix.Len(); const u32 stext = data.m_text.Len(); @@ -69,7 +71,7 @@ struct _LogBuffer : public MTPacketBuffer CheckBusy(); } - LogPacket Pop() + LogPacket _pop() { LogPacket ret; @@ -107,14 +109,26 @@ LogWriter::LogWriter() void LogWriter::WriteToLog(wxString prefix, wxString value, wxString colour/*, wxColour bgcolour*/) { + if(ThreadBase* thr = GetCurrentNamedThread()) + { + prefix = (prefix.IsEmpty() ? "" : prefix + " : ") + thr->GetThreadName(); + } + if(m_logfile.IsOpened()) m_logfile.Write((prefix.IsEmpty() ? wxEmptyString : "[" + prefix + "]: ") + value + "\n"); if(!ConLogFrame) return; - wxMutexLocker locker(mtx_wait); + wxCriticalSectionLocker lock(g_cs_conlog); - while(LogBuffer.IsBusy()) Sleep(1); + if(wxThread::IsMain()) + { + while(LogBuffer.IsBusy()) wxYieldIfNeeded(); + } + else + { + while(LogBuffer.IsBusy()) Sleep(1); + } //if(LogBuffer.put == LogBuffer.get) LogBuffer.Flush(); @@ -179,29 +193,23 @@ void LogWriter::SkipLn() WriteToLog(wxEmptyString, wxEmptyString, "Black"); } -BEGIN_EVENT_TABLE(LogFrame, FrameBase) +BEGIN_EVENT_TABLE(LogFrame, wxPanel) EVT_CLOSE(LogFrame::OnQuit) END_EVENT_TABLE() -LogFrame::LogFrame() - : FrameBase(NULL, wxID_ANY, "Log Console", wxEmptyString, wxSize(600, 450), wxDefaultPosition) +LogFrame::LogFrame(wxWindow* parent) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(600, 500)) , ThreadBase(false, "LogThread") , m_log(*new wxListView(this)) { - wxBoxSizer& s_panel( *new wxBoxSizer(wxHORIZONTAL) ); - - s_panel.Add(&m_log, wxSizerFlags().Expand()); - m_log.InsertColumn(0, wxEmptyString); m_log.InsertColumn(1, "Log"); m_log.SetBackgroundColour(wxColour("Black")); - m_log.SetColumnWidth(0, 18); - - SetSizerAndFit( &s_panel ); - - Connect( wxEVT_SIZE, wxSizeEventHandler(LogFrame::OnResize) ); - Connect( m_log.GetId(), wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, wxListEventHandler( LogFrame::OnColBeginDrag )); + wxBoxSizer& s_main = *new wxBoxSizer(wxVERTICAL); + s_main.Add(&m_log, 1, wxEXPAND); + SetSizer(&s_main); + Layout(); Show(); ThreadBase::Start(); @@ -215,7 +223,7 @@ bool LogFrame::Close(bool force) { Stop(); ConLogFrame = NULL; - return FrameBase::Close(force); + return wxWindowBase::Close(force); } void LogFrame::Task() @@ -227,12 +235,17 @@ void LogFrame::Task() Sleep(1); continue; } + else + { + wxThread::Yield(); + } const LogPacket item = LogBuffer.Pop(); while(m_log.GetItemCount() > max_item_count) { m_log.DeleteItem(0); + wxThread::Yield(); } const int cur_item = m_log.GetItemCount(); @@ -240,6 +253,8 @@ void LogFrame::Task() m_log.InsertItem(cur_item, item.m_prefix); m_log.SetItem(cur_item, 1, item.m_text); m_log.SetItemTextColour(cur_item, item.m_colour); + m_log.SetColumnWidth(0, -1); + m_log.SetColumnWidth(1, -1); ::SendMessage((HWND)m_log.GetHWND(), WM_VSCROLL, SB_BOTTOM, 0); } @@ -247,21 +262,6 @@ void LogFrame::Task() LogBuffer.Flush(); } -void LogFrame::OnColBeginDrag(wxListEvent& event) -{ - event.Veto(); -} - -void LogFrame::OnResize(wxSizeEvent& event) -{ - const wxSize size( GetClientSize() ); - - m_log.SetSize( size ); - m_log.SetColumnWidth(1, size.GetWidth() - 4 - m_log.GetColumnWidth(0)); - - event.Skip(); -} - void LogFrame::OnQuit(wxCloseEvent& event) { Stop(); diff --git a/rpcs3/Gui/ConLog.h b/rpcs3/Gui/ConLog.h index 8a6b0276fd..6d724ec485 100644 --- a/rpcs3/Gui/ConLog.h +++ b/rpcs3/Gui/ConLog.h @@ -23,20 +23,18 @@ public: }; class LogFrame - : public FrameBase + : public wxPanel , public ThreadBase { wxListView& m_log; public: - LogFrame(); + LogFrame(wxWindow* parent); ~LogFrame(); bool Close(bool force = false); private: - virtual void OnColBeginDrag(wxListEvent& event); - virtual void OnResize(wxSizeEvent& event); virtual void Task(); void OnQuit(wxCloseEvent& event); diff --git a/rpcs3/Gui/Debugger.cpp b/rpcs3/Gui/Debugger.cpp new file mode 100644 index 0000000000..31bb005d06 --- /dev/null +++ b/rpcs3/Gui/Debugger.cpp @@ -0,0 +1,148 @@ +#include "stdafx.h" +#include + +#include "Debugger.h" +#include "Emu/Memory/Memory.h" +#include "InterpreterDisAsm.h" + +class DbgEmuPanel : public wxPanel +{ + AppConnector m_app_connector; + + wxButton* m_btn_run; + wxButton* m_btn_stop; + wxButton* m_btn_restart; + +public: + DbgEmuPanel(wxWindow* parent) : wxPanel(parent) + { + m_btn_run = new wxButton(this, wxID_ANY, "Run"); + m_btn_stop = new wxButton(this, wxID_ANY, "Stop"); + m_btn_restart = new wxButton(this, wxID_ANY, "Restart"); + + wxBoxSizer& s_b_main = *new wxBoxSizer(wxHORIZONTAL); + + s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5)); + s_b_main.Add(m_btn_stop, wxSizerFlags().Border(wxALL, 5)); + s_b_main.Add(new wxStaticLine(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_VERTICAL), 0, wxEXPAND); + s_b_main.Add(m_btn_restart, wxSizerFlags().Border(wxALL, 5)); + + SetSizer(&s_b_main); + Layout(); + + UpdateUI(); + Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DbgEmuPanel::OnRun)); + Connect(m_btn_stop->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DbgEmuPanel::OnStop)); + Connect(m_btn_restart->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DbgEmuPanel::OnRestart)); + + m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(DbgEmuPanel::HandleCommand), (wxObject*)0, this); + } + + void UpdateUI() + { + m_btn_run->Enable(!Emu.IsStopped()); + m_btn_stop->Enable(!Emu.IsStopped()); + m_btn_restart->Enable(!Emu.m_path.IsEmpty()); + } + + void OnRun(wxCommandEvent& event) + { + if(Emu.IsRunned()) + { + Emu.Pause(); + } + else if(Emu.IsPaused()) + { + Emu.Resume(); + } + else + { + Emu.Run(); + } + } + + void OnStop(wxCommandEvent& event) + { + Emu.Stop(); + } + + void OnRestart(wxCommandEvent& event) + { + Emu.Stop(); + Emu.Load(); + } + + void HandleCommand(wxCommandEvent& event) + { + switch(event.GetId()) + { + case DID_STOP_EMU: + m_btn_run->SetLabel("Run"); + break; + + case DID_PAUSE_EMU: + m_btn_run->SetLabel("Resume"); + break; + + case DID_START_EMU: + case DID_RESUME_EMU: + m_btn_run->SetLabel("Pause"); + break; + } + + UpdateUI(); + event.Skip(); + } +}; + +DebuggerPanel::DebuggerPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(400, 600), wxTAB_TRAVERSAL) +{ + m_aui_mgr.SetManagedWindow(this); + + m_nb = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, + wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | + wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS | + wxAUI_NB_WINDOWLIST_BUTTON | wxAUI_NB_TAB_MOVE | wxNO_BORDER); + + m_aui_mgr.AddPane(new DbgEmuPanel(this), wxAuiPaneInfo().Top()); + m_aui_mgr.AddPane(m_nb, wxAuiPaneInfo().Center().CaptionVisible(false).CloseButton().MaximizeButton()); + m_aui_mgr.Update(); + + m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(DebuggerPanel::HandleCommand), (wxObject*)0, this); +} + +DebuggerPanel::~DebuggerPanel() +{ + m_aui_mgr.UnInit(); +} + +void DebuggerPanel::UpdateUI() +{ +} + +void DebuggerPanel::HandleCommand(wxCommandEvent& event) +{ + PPCThread* thr = (PPCThread*)event.GetClientData(); + + switch(event.GetId()) + { + case DID_CREATE_THREAD: + m_nb->AddPage(new InterpreterDisAsmFrame(m_nb, thr), thr->GetFName()); + break; + + case DID_REMOVE_THREAD: + for(uint i=0; iGetPageCount(); ++i) + { + InterpreterDisAsmFrame* page = (InterpreterDisAsmFrame*)m_nb->GetPage(i); + + if(page->CPU.GetId() == thr->GetId()) + { + m_nb->DeletePage(i); + break; + } + } + break; + } + + event.Skip(); +} \ No newline at end of file diff --git a/rpcs3/Gui/Debugger.h b/rpcs3/Gui/Debugger.h new file mode 100644 index 0000000000..e127642937 --- /dev/null +++ b/rpcs3/Gui/Debugger.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include "wx/aui/aui.h" + +class DebuggerPanel : public wxPanel +{ + wxAuiManager m_aui_mgr; + wxAuiNotebook* m_nb; + AppConnector m_app_connector; + +public: + DebuggerPanel(wxWindow* parent); + ~DebuggerPanel(); + + void UpdateUI(); + void HandleCommand(wxCommandEvent& event); +}; \ No newline at end of file diff --git a/rpcs3/Gui/DisAsmFrame.cpp b/rpcs3/Gui/DisAsmFrame.cpp index defba175e8..808ec657f6 100644 --- a/rpcs3/Gui/DisAsmFrame.cpp +++ b/rpcs3/Gui/DisAsmFrame.cpp @@ -54,7 +54,7 @@ DisAsmFrame::DisAsmFrame(PPCThread& cpu) Connect( wxEVT_SIZE, wxSizeEventHandler(DisAsmFrame::OnResize) ); - wxGetApp().Connect(m_disasm_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(DisAsmFrame::MouseWheel), (wxObject*)0, this); + m_app_connector.Connect(m_disasm_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(DisAsmFrame::MouseWheel), (wxObject*)0, this); Connect(b_prev.GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisAsmFrame::Prev)); Connect(b_next.GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(DisAsmFrame::Next)); @@ -211,7 +211,7 @@ struct WaitDumperThread : public ThreadBase ~WaitDumperThread() { - free((bool*)done); + delete (bool*)done; done = NULL; } @@ -272,11 +272,11 @@ struct WaitDumperThread : public ThreadBase for(uint sh=0; shLoadInfo()) { delete l_elf64; @@ -323,7 +323,7 @@ void DisAsmFrame::Dump(wxCommandEvent& WXUNUSED(event)) case CLASS_ELF32: ElfType64 = false; - l_elf32 = new ELF32Loader(Emu.m_path); + l_elf32 = new ELF32Loader(f_elf); if(!l_elf32->LoadInfo()) { delete l_elf32; diff --git a/rpcs3/Gui/DisAsmFrame.h b/rpcs3/Gui/DisAsmFrame.h index 82290e2427..a863b4af13 100644 --- a/rpcs3/Gui/DisAsmFrame.h +++ b/rpcs3/Gui/DisAsmFrame.h @@ -5,6 +5,7 @@ class DisAsmFrame : public wxFrame static const uint LINES_OPCODES = 40; u32 count; + AppConnector m_app_connector; wxListView* m_disasm_list; PPCThread& CPU; diff --git a/rpcs3/Gui/FrameBase.h b/rpcs3/Gui/FrameBase.h index 582c14086a..e6abb14287 100644 --- a/rpcs3/Gui/FrameBase.h +++ b/rpcs3/Gui/FrameBase.h @@ -5,6 +5,7 @@ class FrameBase : public wxFrame protected: IniEntry m_ini; WindowInfo m_default_info; + bool m_is_skip_resize; FrameBase( wxWindow* parent, @@ -13,9 +14,11 @@ protected: const wxString& ininame = wxEmptyString, wxSize defsize = wxDefaultSize, wxPoint defposition = wxDefaultPosition, - long style = wxDEFAULT_FRAME_STYLE) + long style = wxDEFAULT_FRAME_STYLE, + bool is_skip_resize = false) : wxFrame(parent, id, framename, defposition, defsize, style) , m_default_info(defsize, defposition) + , m_is_skip_resize(is_skip_resize) { m_ini.Init(ininame.IsEmpty() ? framename : ininame, "GuiSettings"); LoadInfo(); @@ -51,7 +54,7 @@ protected: void OnResize(wxSizeEvent& event) { m_ini.SetValue(WindowInfo(GetSize(), m_ini.GetValue().position)); - //event.Skip(); + if(m_is_skip_resize) event.Skip(); } void OnClose(wxCloseEvent& event) diff --git a/rpcs3/Gui/GameViewer.cpp b/rpcs3/Gui/GameViewer.cpp index 04d4caf4e1..c559a41820 100644 --- a/rpcs3/Gui/GameViewer.cpp +++ b/rpcs3/Gui/GameViewer.cpp @@ -3,21 +3,14 @@ #include "Loader/PSF.h" static const wxString m_class_name = "GameViewer"; -GameViewer::GameViewer(wxWindow* parent) : wxPanel(parent) +GameViewer::GameViewer(wxWindow* parent) : wxListView(parent) { - wxBoxSizer& s_panel( *new wxBoxSizer(wxVERTICAL) ); - - m_game_list = new wxListView(this); - s_panel.Add(m_game_list); - - SetSizerAndFit( &s_panel ); - LoadSettings(); - m_columns.Show(m_game_list); + m_columns.Show(this); m_path = wxGetCwd(); //TODO - Connect(m_game_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(GameViewer::DClick)); + Connect(GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(GameViewer::DClick)); Refresh(); } @@ -25,13 +18,11 @@ GameViewer::GameViewer(wxWindow* parent) : wxPanel(parent) GameViewer::~GameViewer() { SaveSettings(); - m_game_list->Destroy(); } void GameViewer::DoResize(wxSize size) { SetSize(size); - m_game_list->SetSize(size); } void GameViewer::LoadGames() @@ -63,7 +54,8 @@ void GameViewer::LoadPSF() { const wxString& path = m_games[i] + "\\" + "PARAM.SFO"; if(!wxFileExists(path)) continue; - PSFLoader psf(path); + vfsLocalFile f(path); + PSFLoader psf(f); if(!psf.Load(false)) continue; psf.m_info.root = m_games[i]; m_game_data.Add(new GameInfo(psf.m_info)); @@ -74,7 +66,7 @@ void GameViewer::LoadPSF() void GameViewer::ShowData() { - m_columns.ShowData(m_game_list); + m_columns.ShowData(this); } void GameViewer::Refresh() @@ -86,7 +78,7 @@ void GameViewer::Refresh() void GameViewer::SaveSettings() { - m_columns.LoadSave(false, m_class_name, m_game_list); + m_columns.LoadSave(false, m_class_name, this); } void GameViewer::LoadSettings() @@ -96,10 +88,10 @@ void GameViewer::LoadSettings() void GameViewer::DClick(wxListEvent& event) { - long i = m_game_list->GetFirstSelected(); + long i = GetFirstSelected(); if(i < 0) return; - const wxString& path = m_game_data[i].root + "\\" + "USRDIR" + "\\" + "BOOT.BIN"; + const wxString& path = m_path + "\\" + m_game_data[i].root + "\\" + "USRDIR" + "\\" + "BOOT.BIN"; if(!wxFileExists(path)) { ConLog.Error("Boot error: elf not found! [%s]", path); diff --git a/rpcs3/Gui/GameViewer.h b/rpcs3/Gui/GameViewer.h index eb9d957a0d..17dfa9f776 100644 --- a/rpcs3/Gui/GameViewer.h +++ b/rpcs3/Gui/GameViewer.h @@ -214,9 +214,8 @@ public: } }; -class GameViewer : public wxPanel +class GameViewer : public wxListView { - wxListView* m_game_list; wxString m_path; wxArrayString m_games; ArrayF m_game_data; diff --git a/rpcs3/Gui/InterpreterDisAsm.cpp b/rpcs3/Gui/InterpreterDisAsm.cpp index 242c9c6e10..b8e18e8e98 100644 --- a/rpcs3/Gui/InterpreterDisAsm.cpp +++ b/rpcs3/Gui/InterpreterDisAsm.cpp @@ -10,13 +10,11 @@ u32 FixPc(const u32 pc) return pc - ((show_lines/2)*4); } -InterpreterDisAsmFrame::InterpreterDisAsmFrame(const wxString& title, PPCThread* cpu) - : FrameBase(NULL, wxID_ANY, title, "InterpreterDisAsmFrame", wxSize(500, 700)) +InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu) + : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxSize(500, 700), wxTAB_TRAVERSAL) , ThreadBase(false, "DisAsmFrame Thread") - , m_main_panel(*new wxPanel(this)) , CPU(*cpu) , PC(0) - , m_exec(false) { if(CPU.IsSPU()) { @@ -34,14 +32,14 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(const wxString& title, PPCThread* wxBoxSizer& s_p_main = *new wxBoxSizer(wxVERTICAL); wxBoxSizer& s_b_main = *new wxBoxSizer(wxHORIZONTAL); - m_list = new wxListView(&m_main_panel); + m_list = new wxListView(this); - wxButton& b_go_to_addr = *new wxButton(&m_main_panel, wxID_ANY, "Go To Address"); - wxButton& b_go_to_pc = *new wxButton(&m_main_panel, wxID_ANY, "Go To PC"); + wxButton& b_go_to_addr = *new wxButton(this, wxID_ANY, "Go To Address"); + wxButton& b_go_to_pc = *new wxButton(this, wxID_ANY, "Go To PC"); - m_btn_step = new wxButton(&m_main_panel, wxID_ANY, "Step"); - m_btn_run = new wxButton(&m_main_panel, wxID_ANY, "Run"); - m_btn_pause = new wxButton(&m_main_panel, wxID_ANY, "Pause"); + m_btn_step = new wxButton(this, wxID_ANY, "Step"); + m_btn_run = new wxButton(this, wxID_ANY, "Run"); + m_btn_pause = new wxButton(this, wxID_ANY, "Pause"); s_b_main.Add(&b_go_to_addr, wxSizerFlags().Border(wxALL, 5)); s_b_main.Add(&b_go_to_pc, wxSizerFlags().Border(wxALL, 5)); @@ -49,7 +47,7 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(const wxString& title, PPCThread* s_b_main.Add(m_btn_run, wxSizerFlags().Border(wxALL, 5)); s_b_main.Add(m_btn_pause, wxSizerFlags().Border(wxALL, 5)); - m_regs = new wxTextCtrl(&m_main_panel, wxID_ANY, wxEmptyString, + m_regs = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_DONTWRAP|wxNO_BORDER|wxTE_RICH2); m_regs->SetMinSize(wxSize(495, 100)); m_regs->SetEditable(false); @@ -58,25 +56,14 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(const wxString& title, PPCThread* m_regs->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL)); wxBoxSizer& s_w_list = *new wxBoxSizer(wxHORIZONTAL); - s_w_list.Add(m_list); - s_w_list.AddSpacer(5); - s_w_list.Add(m_regs); + s_w_list.Add(m_list, 2, wxEXPAND | wxLEFT | wxDOWN, 5); + s_w_list.Add(m_regs, 1, wxEXPAND | wxRIGHT | wxDOWN, 5); - s_p_main.AddSpacer(5); - s_p_main.Add(&s_b_main); - s_p_main.AddSpacer(5); - s_p_main.Add(&s_w_list); - s_p_main.AddSpacer(5); + s_p_main.Add(&s_b_main, 0, wxEXPAND | wxLEFT | wxRIGHT, 5); + s_p_main.Add(&s_w_list, 1, wxEXPAND | wxDOWN, 5); - wxBoxSizer& s_p_main_h = *new wxBoxSizer(wxVERTICAL); - s_p_main_h.AddSpacer(5); - s_p_main_h.Add(&s_p_main); - s_p_main_h.AddSpacer(5); - m_main_panel.SetSizerAndFit(&s_p_main_h); - - wxBoxSizer& s_main = *new wxBoxSizer(wxVERTICAL); - s_main.Add(&m_main_panel); - SetSizerAndFit(&s_main); + SetSizer(&s_p_main); + Layout(); m_list->InsertColumn(0, "ASM"); @@ -92,14 +79,12 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(const wxString& title, PPCThread* Connect(m_btn_run->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoRun)); Connect(m_btn_pause->GetId(), wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(InterpreterDisAsmFrame::DoPause)); Connect(m_list->GetId(), wxEVT_COMMAND_LIST_ITEM_ACTIVATED, wxListEventHandler(InterpreterDisAsmFrame::DClick)); - Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); - wxGetApp().Connect(m_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(InterpreterDisAsmFrame::MouseWheel), (wxObject*)0, this); - wxGetApp().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InterpreterDisAsmFrame::OnKeyDown), (wxObject*)0, this); + //Connect(wxEVT_SIZE, wxSizeEventHandler(InterpreterDisAsmFrame::OnResize)); + m_app_connector.Connect(m_list->GetId(), wxEVT_MOUSEWHEEL, wxMouseEventHandler(InterpreterDisAsmFrame::MouseWheel), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(InterpreterDisAsmFrame::OnKeyDown), (wxObject*)0, this); - m_btn_pause->Disable(); - //ShowPc(Loader.entry); + m_app_connector.Connect(wxEVT_DBG_COMMAND, wxCommandEventHandler(InterpreterDisAsmFrame::HandleCommand), (wxObject*)0, this); WriteRegs(); - ThreadBase::Start(); Load(BreakPointsDBName); } @@ -171,7 +156,7 @@ void InterpreterDisAsmFrame::Load(const wxString& path) void InterpreterDisAsmFrame::OnKeyDown(wxKeyEvent& event) { - if(wxGetActiveWindow() != this) + if(wxGetActiveWindow() != wxGetTopLevelParent(this)) { event.Skip(); return; @@ -231,7 +216,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr) wxColour colour; - if(PC == CPU.PC) + if((!CPU.IsRunned() || !Emu.IsRunned()) && PC == CPU.PC) { colour = wxColour("Green"); } @@ -252,7 +237,6 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr) m_list->SetItemBackgroundColour( i, colour ); } - while(remove_markedPC.GetCount()) { u32 mpc = remove_markedPC[0]; @@ -271,6 +255,7 @@ void InterpreterDisAsmFrame::ShowAddr(const u64 addr) markedPC.RemoveAt(mpc); } + m_list->SetColumnWidth(0, -1); m_list->Thaw(); } @@ -282,6 +267,41 @@ void InterpreterDisAsmFrame::WriteRegs() m_regs->Thaw(); } +void InterpreterDisAsmFrame::HandleCommand(wxCommandEvent& event) +{ + PPCThread* thr = (PPCThread*)event.GetClientData(); + event.Skip(); + + if(!thr || thr->GetId() != CPU.GetId()) return; + + switch(event.GetId()) + { + 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; + + 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(); + + DoUpdate(); + break; + + case DID_STOP_EMU: + case DID_PAUSE_EMU: + DoUpdate(); + break; + } +} + void InterpreterDisAsmFrame::OnUpdate(wxCommandEvent& event) { //WriteRegs(); @@ -324,29 +344,21 @@ void InterpreterDisAsmFrame::Show_PC(wxCommandEvent& WXUNUSED(event)) extern bool dump_enable; void InterpreterDisAsmFrame::DoRun(wxCommandEvent& WXUNUSED(event)) { - m_exec = true; - /* - bool dump_status = dump_enable; - if(Emu.IsPaused()) Emu.Run(); - while(Emu.IsRunned()) - { - CPU.Exec(); - if(IsBreakPoint(CPU.PC) || dump_status != dump_enable) break; - } + if(CPU.IsPaused()) CPU.Resume(); + if(Emu.IsPaused()) Emu.Resume(); - DoUpdate(); - */ + CPU.Exec(); + //ThreadBase::Start(); } void InterpreterDisAsmFrame::DoPause(wxCommandEvent& WXUNUSED(event)) { - Emu.Pause(); + CPU.Pause(); } void InterpreterDisAsmFrame::DoStep(wxCommandEvent& WXUNUSED(event)) { - CPU.Exec(); - DoUpdate(); + ThreadBase::Start(); } void InterpreterDisAsmFrame::DClick(wxListEvent& event) @@ -356,7 +368,7 @@ void InterpreterDisAsmFrame::DClick(wxListEvent& event) const u64 start_pc = PC - show_lines*4; const u64 pc = start_pc + i*4; - //ConLog.Write("pc=0x%x", pc); + //ConLog.Write("pc=0x%llx", pc); if(!Memory.IsGoodAddr(pc, 4)) return; @@ -371,37 +383,12 @@ void InterpreterDisAsmFrame::DClick(wxListEvent& event) ShowAddr(start_pc); } - -void InterpreterDisAsmFrame::OnResize(wxSizeEvent& event) -{ - const wxSize& size( GetClientSize() ); - - wxTextCtrl& regs = *m_regs; - wxListView& list = *m_list; - - const int list_size = size.GetWidth() * 0.75; - const int regs_size = size.GetWidth() * 0.25 - 5; - list.SetMinSize(wxSize(list_size, size.GetHeight()-55)); - regs.SetMinSize(wxSize(regs_size, size.GetHeight()-55)); - m_main_panel.SetSize( size ); - m_main_panel.GetSizer()->RecalcSizes(); - - list.SetColumnWidth(0, list_size-8); - - event.Skip(); -} void InterpreterDisAsmFrame::MouseWheel(wxMouseEvent& event) { const int value = (event.m_wheelRotation / event.m_wheelDelta); - if(event.ControlDown()) - { - ShowAddr( PC - (show_lines * (value + 1)) * 4); - } - else - { - ShowAddr( PC - (show_lines + value) * 4 ); - } + + ShowAddr( PC - (event.ControlDown() ? show_lines * (value + 1) : show_lines + value) * 4); event.Skip(); } @@ -440,31 +427,30 @@ bool InterpreterDisAsmFrame::RemoveBreakPoint(u64 pc) void InterpreterDisAsmFrame::Task() { - while(!TestDestroy()) + wxGetApp().SendDbgCommand(DID_RESUME_THREAD, &CPU); + + bool dump_status = dump_enable; + + //CPU.InitTls(); + + try { - Sleep(1); - - if(!m_exec) continue; - - m_btn_step->Disable(); - m_btn_run->Disable(); - m_btn_pause->Enable(); - - bool dump_status = dump_enable; - if(Emu.IsPaused()) Emu.Resume(); - - while(Emu.IsRunned() && !TestDestroy()) + do { - CPU.Exec(); - if(IsBreakPoint(CPU.PC) || dump_status != dump_enable) break; + CPU.ExecOnce(); } - - DoUpdate(); - - m_btn_step->Enable(); - m_btn_run->Enable(); - m_btn_pause->Disable(); - - m_exec = false; + while(CPU.IsRunned() && Emu.IsRunned() && !TestDestroy() && !IsBreakPoint(CPU.PC) && dump_status == dump_enable); } + catch(const wxString& e) + { + ConLog.Error(e); + } + catch(...) + { + ConLog.Error("Unhandled exception."); + } + + //CPU.FreeTls(); + + wxGetApp().SendDbgCommand(DID_PAUSE_THREAD, &CPU); } \ No newline at end of file diff --git a/rpcs3/Gui/InterpreterDisAsm.h b/rpcs3/Gui/InterpreterDisAsm.h index bae01e49eb..2d2fc2f420 100644 --- a/rpcs3/Gui/InterpreterDisAsm.h +++ b/rpcs3/Gui/InterpreterDisAsm.h @@ -6,12 +6,10 @@ #include "Emu/Cell/SPUDisAsm.h" class InterpreterDisAsmFrame - : public FrameBase + : public wxPanel , public ThreadBase { wxListView* m_list; - wxPanel& m_main_panel; - PPCThread& CPU; DisAsm* disasm; Decoder* decoder; u64 PC; @@ -22,20 +20,24 @@ class InterpreterDisAsmFrame wxButton* m_btn_step; wxButton* m_btn_run; wxButton* m_btn_pause; - volatile bool m_exec; + AppConnector m_app_connector; public: - InterpreterDisAsmFrame(const wxString& title, PPCThread* cpu); + PPCThread& CPU; + +public: + InterpreterDisAsmFrame(wxWindow* parent, PPCThread* cpu); ~InterpreterDisAsmFrame(); void Save(const wxString& path); void Load(const wxString& path); - virtual void OnKeyDown(wxKeyEvent& event); + void OnKeyDown(wxKeyEvent& event); void DoUpdate(); void ShowAddr(const u64 addr); void WriteRegs(); + void HandleCommand(wxCommandEvent& event); void OnUpdate(wxCommandEvent& event); void Show_Val(wxCommandEvent& event); void Show_PC(wxCommandEvent& event); @@ -44,7 +46,6 @@ public: void DoStep(wxCommandEvent& event); void DClick(wxListEvent& event); - void OnResize(wxSizeEvent& event); void MouseWheel(wxMouseEvent& event); bool IsBreakPoint(u64 pc); void AddBreakPoint(u64 pc); diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 14d38d741e..8c264de5c4 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -5,6 +5,8 @@ #include "Emu/System.h" #include "Ini.h" #include "svnrev.h" +#include "Emu/GS/sysutil_video.h" +#include BEGIN_EVENT_TABLE(MainFrame, FrameBase) EVT_CLOSE(MainFrame::OnQuit) @@ -17,10 +19,21 @@ enum IDs id_boot_game, id_sys_pause, id_sys_stop, + id_sys_send_exit, id_config_emu, + id_update_dbg, }; -MainFrame::MainFrame() : FrameBase(NULL, wxID_ANY, "", "MainFrame", wxSize(280, 180)) +wxString GetPaneName() +{ + static int pane_num = 0; + + return wxString::Format("Pane_%d", pane_num++); +} + +MainFrame::MainFrame() + : FrameBase(NULL, wxID_ANY, "", "MainFrame", wxSize(280, 180)) + , m_aui_mgr(this) { SetLabel(wxString::Format(_PRGNAME_ " " _PRGVER_ " r%d" SVN_MOD " (" SVN_DATE ")", SVN_REV)); wxMenuBar& menubar(*new wxMenuBar()); @@ -39,40 +52,55 @@ MainFrame::MainFrame() : FrameBase(NULL, wxID_ANY, "", "MainFrame", wxSize(280, //menu_boot.Append(id_boot_self, "Boot Self"); menu_sys.Append(id_sys_pause, "Pause"); - menu_sys.Append(id_sys_stop, "Stop"); + menu_sys.Append(id_sys_stop, "Stop\tCtrl + S"); + menu_sys.AppendSeparator(); + menu_sys.Append(id_sys_send_exit, "Send exit cmd"); menu_conf.Append(id_config_emu, "Settings"); SetMenuBar(&menubar); - wxBoxSizer& s_panel( *new wxBoxSizer(wxHORIZONTAL) ); - m_game_viewer = new GameViewer(this); - s_panel.Add( m_game_viewer, wxSizerFlags().Expand() ); - - SetSizerAndFit( &s_panel ); - - Connect(wxEVT_SIZE, wxSizeEventHandler(MainFrame::OnResize)); - + AddPane(m_game_viewer, "Game List", wxAUI_DOCK_BOTTOM); + Connect( id_boot_game, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootGame) ); Connect( id_boot_elf, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootElf) ); Connect( id_boot_self, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::BootSelf) ); Connect( id_sys_pause, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Pause) ); Connect( id_sys_stop, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Stop) ); + Connect( id_sys_send_exit, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::SendExit) ); + Connect( id_update_dbg, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::UpdateUI) ); Connect( id_config_emu, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainFrame::Config) ); - wxGetApp().Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); + m_app_connector.Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(MainFrame::OnKeyDown), (wxObject*)0, this); UpdateUI(); - - (new CompilerELF(NULL))->Show(); } -void MainFrame::OnResize(wxSizeEvent& event) +MainFrame::~MainFrame() { - m_game_viewer->DoResize(GetClientSize()); - event.Skip(); + m_aui_mgr.UnInit(); +} + +void MainFrame::AddPane(wxWindow* wind, const wxString& caption, int flags) +{ + m_aui_mgr.AddPane(wind, wxAuiPaneInfo().Name(GetPaneName()).Caption(caption).Direction(flags).CloseButton(false).MaximizeButton()); +} + +void MainFrame::DoSettings(bool load) +{ + IniEntry ini; + ini.Init("Settings", "MainFrameAui"); + + if(load) + { + m_aui_mgr.LoadPerspective(ini.LoadValue(m_aui_mgr.SavePerspective())); + } + else + { + ini.SaveValue(m_aui_mgr.SavePerspective()); + } } void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) @@ -85,7 +113,7 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) stoped = true; } - wxDirDialog ctrl( this, L"Select game folder", wxEmptyString); + wxDirDialog ctrl(this, L"Select game folder", wxEmptyString); if(ctrl.ShowModal() == wxID_CANCEL) { @@ -141,7 +169,7 @@ void MainFrame::BootGame(wxCommandEvent& WXUNUSED(event)) return; } - Emu.Run(); + Emu.Load(); ConLog.Write("Game: boot done."); return; @@ -174,7 +202,7 @@ void MainFrame::BootElf(wxCommandEvent& WXUNUSED(event)) Emu.Stop(); Emu.SetElf(ctrl.GetPath()); - Emu.Run(); + Emu.Load(); ConLog.Write("Elf: boot done."); } @@ -203,14 +231,18 @@ void MainFrame::BootSelf(wxCommandEvent& WXUNUSED(event)) Emu.Stop(); Emu.SetSelf(ctrl.GetPath()); - Emu.Run(); + Emu.Load(); ConLog.Write("SELF: boot done."); } void MainFrame::Pause(wxCommandEvent& WXUNUSED(event)) { - if(Emu.IsPaused()) + if(Emu.IsReady()) + { + Emu.Run(); + } + else if(Emu.IsPaused()) { Emu.Resume(); } @@ -225,6 +257,11 @@ void MainFrame::Stop(wxCommandEvent& WXUNUSED(event)) Emu.Stop(); } +void MainFrame::SendExit(wxCommandEvent& event) +{ + Emu.GetCallbackManager().m_exit_callback.Handle(0x0101, 0); +} + void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) { //TODO @@ -237,27 +274,41 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) paused = true; } - wxDialog* diag = new wxDialog(this, wxID_ANY, "Settings", wxDefaultPosition); + wxDialog diag(this, wxID_ANY, "Settings", wxDefaultPosition); wxBoxSizer* s_panel(new wxBoxSizer(wxVERTICAL)); - wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, diag, _("CPU") ) ); - wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, diag, _("Decoder") ) ); + wxStaticBoxSizer* s_round_cpu( new wxStaticBoxSizer( wxVERTICAL, &diag, _("CPU") ) ); + wxStaticBoxSizer* s_round_cpu_decoder( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Decoder") ) ); - wxStaticBoxSizer* s_round_gs( new wxStaticBoxSizer( wxHORIZONTAL, diag, _("GS") ) ); - wxStaticBoxSizer* s_round_gs_render( new wxStaticBoxSizer( wxVERTICAL, diag, _("Render") ) ); + wxStaticBoxSizer* s_round_gs( new wxStaticBoxSizer( wxVERTICAL, &diag, _("GS") ) ); + wxStaticBoxSizer* s_round_gs_render( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Render") ) ); + wxStaticBoxSizer* s_round_gs_res( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default resolution") ) ); + wxStaticBoxSizer* s_round_gs_aspect( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Default aspect ratio") ) ); - wxStaticBoxSizer* s_round_pad( new wxStaticBoxSizer( wxHORIZONTAL, diag, _("Pad") ) ); - wxStaticBoxSizer* s_round_pad_handler( new wxStaticBoxSizer( wxVERTICAL, diag, _("Handler") ) ); + wxStaticBoxSizer* s_round_pad( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Pad") ) ); + wxStaticBoxSizer* s_round_pad_handler( new wxStaticBoxSizer( wxVERTICAL, &diag, _("Handler") ) ); - wxComboBox* cbox_cpu_decoder = new wxComboBox(diag, wxID_ANY); - wxComboBox* cbox_gs_render = new wxComboBox(diag, wxID_ANY); - wxComboBox* cbox_pad_handler = new wxComboBox(diag, wxID_ANY); + wxComboBox* cbox_cpu_decoder = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_render = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_resolution = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_gs_aspect = new wxComboBox(&diag, wxID_ANY); + wxComboBox* cbox_pad_handler = new wxComboBox(&diag, wxID_ANY); + + wxCheckBox* chbox_gs_vsync = new wxCheckBox(&diag, wxID_ANY, "VSync"); //cbox_cpu_decoder->Append("DisAsm"); cbox_cpu_decoder->Append("Interpreter & DisAsm"); cbox_cpu_decoder->Append("Interpreter"); + for(int i=1; iAppend(wxString::Format("%dx%d", ResolutionTable[i].width, ResolutionTable[i].height)); + } + + cbox_gs_aspect->Append("4:3"); + cbox_gs_aspect->Append("16:9"); + cbox_gs_render->Append("Null"); cbox_gs_render->Append("OpenGL"); //cbox_gs_render->Append("Software"); @@ -266,50 +317,65 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_pad_handler->Append("Windows"); //cbox_pad_handler->Append("DirectInput"); + chbox_gs_vsync->SetValue(Ini.GSVSyncEnable.GetValue()); + cbox_cpu_decoder->SetSelection(Ini.CPUDecoderMode.GetValue() ? Ini.CPUDecoderMode.GetValue() - 1 : 0); cbox_gs_render->SetSelection(Ini.GSRenderMode.GetValue()); + cbox_gs_resolution->SetSelection(ResolutionIdToNum(Ini.GSResolution.GetValue()) - 1); + cbox_gs_aspect->SetSelection(Ini.GSAspectRatio.GetValue() - 1); cbox_pad_handler->SetSelection(Ini.PadHandlerMode.GetValue()); - s_round_cpu_decoder->Add(cbox_cpu_decoder); - s_round_cpu->Add(s_round_cpu_decoder); + s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_cpu->Add(s_round_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); - s_round_gs_render->Add(cbox_gs_render); - s_round_gs->Add(s_round_gs_render); + s_round_gs_render->Add(cbox_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs_res->Add(cbox_gs_resolution, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs_aspect->Add(cbox_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_render, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_res, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(s_round_gs_aspect, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_gs->Add(chbox_gs_vsync, wxSizerFlags().Border(wxALL, 5)); - s_round_pad_handler->Add(cbox_pad_handler); - s_round_pad->Add(s_round_pad_handler); + s_round_pad_handler->Add(cbox_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); + s_round_pad->Add(s_round_pad_handler, wxSizerFlags().Border(wxALL, 5).Expand()); wxBoxSizer* s_b_panel(new wxBoxSizer(wxHORIZONTAL)); - s_b_panel->Add(new wxButton(diag, wxID_OK)); - s_b_panel->AddSpacer(5); - s_b_panel->Add(new wxButton(diag, wxID_CANCEL)); + s_b_panel->Add(new wxButton(&diag, wxID_OK), wxSizerFlags().Border(wxALL, 5).Center()); + s_b_panel->Add(new wxButton(&diag, wxID_CANCEL), wxSizerFlags().Border(wxALL, 5).Center()); - s_panel->Add(s_round_cpu); - s_panel->AddSpacer(5); - s_panel->Add(s_round_gs); - s_panel->AddSpacer(5); - s_panel->Add(s_round_pad); - s_panel->AddSpacer(8); - s_panel->Add(s_b_panel, wxRIGHT); + //wxBoxSizer* s_conf_panel(new wxBoxSizer(wxHORIZONTAL)); - diag->SetSizerAndFit( s_panel ); + s_panel->Add(s_round_cpu, wxSizerFlags().Border(wxALL, 5).Expand()); + s_panel->Add(s_round_gs, wxSizerFlags().Border(wxALL, 5).Expand()); + s_panel->Add(s_round_pad, wxSizerFlags().Border(wxALL, 5).Expand()); + s_panel->Add(s_b_panel, wxSizerFlags().Border(wxALL, 8).Expand()); + + diag.SetSizerAndFit( s_panel ); - if(diag->ShowModal() == wxID_OK) + if(diag.ShowModal() == wxID_OK) { Ini.CPUDecoderMode.SetValue(cbox_cpu_decoder->GetSelection() + 1); Ini.GSRenderMode.SetValue(cbox_gs_render->GetSelection()); + Ini.GSResolution.SetValue(ResolutionNumToId(cbox_gs_resolution->GetSelection() + 1)); + Ini.GSAspectRatio.SetValue(cbox_gs_aspect->GetSelection() + 1); + Ini.GSVSyncEnable.SetValue(chbox_gs_vsync->GetValue()); Ini.PadHandlerMode.SetValue(cbox_pad_handler->GetSelection()); + Ini.Save(); } - delete diag; - if(paused) Emu.Resume(); } +void MainFrame::UpdateUI(wxCommandEvent& WXUNUSED(event)) +{ + wxGetApp().m_debugger_frame->UpdateUI(); +} + void MainFrame::OnQuit(wxCloseEvent& event) { + DoSettings(false); TheApp->Exit(); } @@ -356,13 +422,14 @@ void MakeSaveState(wxFile& f) void MainFrame::OnKeyDown(wxKeyEvent& event) { - if(wxGetActiveWindow() == this && event.ControlDown()) + if(wxGetActiveWindow() /*== this*/ && event.ControlDown()) { switch(event.GetKeyCode()) { - case 'C': case 'c': if(Emu.IsPaused()) Emu.Resume(); return; + case 'C': case 'c': if(Emu.IsPaused()) Emu.Resume(); else if(Emu.IsReady()) Emu.Run(); return; + case 'P': case 'p': if(Emu.IsRunned()) Emu.Pause(); return; case 'S': case 's': if(!Emu.IsStopped()) Emu.Stop(); return; - case 'R': case 'r': if(Emu.m_path.Len()) {Emu.Stop(); Emu.Run();} return; + case 'R': case 'r': if(!Emu.m_path.IsEmpty()) {Emu.Stop(); Emu.Run();} return; } } @@ -374,17 +441,16 @@ 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 ); - if(Emu.IsRunned()) - { - pause.SetText("Pause"); - pause.Enable(); - stop.Enable(); - } - else - { - pause.SetText("Resume"); - pause.Enable(Emu.IsPaused()); - stop.Enable(Emu.IsPaused()); - } + 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 1461618d61..acd7072708 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -1,27 +1,35 @@ #pragma once #include "GameViewer.h" +#include "wx/aui/aui.h" class MainFrame : public FrameBase { GameViewer* m_game_viewer; + wxAuiManager m_aui_mgr; + AppConnector m_app_connector; public: MainFrame(); + ~MainFrame(); + + void AddPane(wxWindow* wind, const wxString& caption, int flags); + void DoSettings(bool load); private: - virtual void OnQuit(wxCloseEvent& event); - virtual void OnResize(wxSizeEvent& event); + void OnQuit(wxCloseEvent& event); - virtual void BootGame(wxCommandEvent& event); - virtual void BootElf(wxCommandEvent& event); - virtual void BootSelf(wxCommandEvent& event); - virtual void Pause(wxCommandEvent& event); - virtual void Stop(wxCommandEvent& event); - virtual void Config(wxCommandEvent& event); - virtual void OnKeyDown(wxKeyEvent& event); + void BootGame(wxCommandEvent& event); + void BootElf(wxCommandEvent& event); + void BootSelf(wxCommandEvent& event); + void Pause(wxCommandEvent& event); + void Stop(wxCommandEvent& event); + void SendExit(wxCommandEvent& event); + void Config(wxCommandEvent& event); + void UpdateUI(wxCommandEvent& event); + void OnKeyDown(wxKeyEvent& event); public: - virtual void UpdateUI(); + void UpdateUI(); private: DECLARE_EVENT_TABLE() diff --git a/rpcs3/Gui/Plugins.h b/rpcs3/Gui/Plugins.h new file mode 100644 index 0000000000..0cffa91ad2 --- /dev/null +++ b/rpcs3/Gui/Plugins.h @@ -0,0 +1,362 @@ +#pragma once + +#define LOAD_SYMBOL(x) if(m_dll.HasSymbol(#x)) x = (_##x)m_dll.GetSymbol(#x) +struct Ps3EmuPlugin +{ + enum PS3EMULIB_TYPE + { + LIB_PAD = (1 << 0), + LIB_KB = (1 << 1), + LIB_MOUSE = (1 << 2), + LIB_FS = (1 << 3), + }; + + typedef u32 (*_Ps3EmuLibGetType)(); + typedef u32 (*_Ps3EmuLibGetVersion)(); + typedef const char* (*_Ps3EmuLibGetName)(); + typedef const char* (*_Ps3EmuLibGetFullName)(); + typedef void (*_Ps3EmuLibSetSettingsPath)(const char* path); + typedef void (*_Ps3EmuLibSetLogPath)(const char* path); + typedef const char* (*_Ps3EmuLibGetSettingsName)(); + typedef const char* (*_Ps3EmuLibGetLogName)(); + typedef void (*_Ps3EmuLibConfigure)(PS3EMULIB_TYPE type); + typedef void (*_Ps3EmuLibAbout)(); + typedef u32 (*_Ps3EmuLibTest)(PS3EMULIB_TYPE type); + + _Ps3EmuLibGetType Ps3EmuLibGetType; + _Ps3EmuLibGetVersion Ps3EmuLibGetVersion; + _Ps3EmuLibGetName Ps3EmuLibGetName; + _Ps3EmuLibGetFullName Ps3EmuLibGetFullName; + _Ps3EmuLibSetSettingsPath Ps3EmuLibSetSettingsPath; + _Ps3EmuLibSetLogPath Ps3EmuLibSetLogPath; + _Ps3EmuLibGetSettingsName Ps3EmuLibGetSettingsName; + _Ps3EmuLibGetLogName Ps3EmuLibGetLogName; + _Ps3EmuLibConfigure Ps3EmuLibConfigure; + _Ps3EmuLibAbout Ps3EmuLibAbout; + _Ps3EmuLibTest Ps3EmuLibTest; + + wxDynamicLibrary m_dll; + + Ps3EmuPlugin() + { + Reset(); + } + + Ps3EmuPlugin(const wxString& path) + { + Load(path); + } + + virtual ~Ps3EmuPlugin() throw() + { + Unload(); + } + + wxString FormatVersion() + { + if(!Ps3EmuLibGetVersion) return wxEmptyString; + + const u32 v = Ps3EmuLibGetVersion(); + + const u8 v0 = v >> 24; + const u8 v1 = v >> 16; + const u8 v2 = v >> 8; + const u8 v3 = v; + + if(!v2 && !v3) return wxString::Format("%d.%d", v0, v1); + if(!v3) return wxString::Format("%d.%d.%d", v0, v1, v2); + + return wxString::Format("%d.%d.%d.%d", v0, v1, v2, v3); + } + + void Load(const wxString& path) + { + if(m_dll.Load(path)) + { + Init(); + } + else + { + Reset(); + } + } + + void Unload() + { + Reset(); + + if(m_dll.IsLoaded()) m_dll.Unload(); + } + + virtual bool Test() + { + return + m_dll.IsLoaded() && + Ps3EmuLibGetType && + Ps3EmuLibGetVersion && + Ps3EmuLibGetName && + Ps3EmuLibGetFullName && + Ps3EmuLibSetSettingsPath && + Ps3EmuLibSetLogPath && + Ps3EmuLibGetSettingsName && + Ps3EmuLibGetLogName && + Ps3EmuLibConfigure && + Ps3EmuLibAbout && + Ps3EmuLibTest; + } + +protected: + virtual void Init() + { + LOAD_SYMBOL(Ps3EmuLibGetType); + LOAD_SYMBOL(Ps3EmuLibGetVersion); + LOAD_SYMBOL(Ps3EmuLibGetName); + LOAD_SYMBOL(Ps3EmuLibGetFullName); + LOAD_SYMBOL(Ps3EmuLibSetSettingsPath); + LOAD_SYMBOL(Ps3EmuLibSetLogPath); + LOAD_SYMBOL(Ps3EmuLibGetSettingsName); + LOAD_SYMBOL(Ps3EmuLibGetLogName); + LOAD_SYMBOL(Ps3EmuLibConfigure); + LOAD_SYMBOL(Ps3EmuLibAbout); + LOAD_SYMBOL(Ps3EmuLibTest); + } + + virtual void Reset() + { + Ps3EmuLibGetType = nullptr; + Ps3EmuLibGetVersion = nullptr; + Ps3EmuLibGetName = nullptr; + Ps3EmuLibGetFullName = nullptr; + Ps3EmuLibSetSettingsPath = nullptr; + Ps3EmuLibSetLogPath = nullptr; + Ps3EmuLibGetSettingsName = nullptr; + Ps3EmuLibGetLogName = nullptr; + Ps3EmuLibConfigure = nullptr; + Ps3EmuLibAbout = nullptr; + Ps3EmuLibTest = nullptr; + } +}; + +struct Ps3EmuPluginPAD : public Ps3EmuPlugin +{ + typedef int (*_PadInit)(u32 max_connect); + typedef int (*_PadEnd)(); + typedef int (*_PadClearBuf)(u32 port_no); + typedef int (*_PadGetData)(u32 port_no, void* data); + typedef int (*_PadGetDataExtra)(u32 port_no, u32* device_type, void* data); + typedef int (*_PadSetActDirect)(u32 port_no, void* param); + typedef int (*_PadGetInfo)(void* info); + typedef int (*_PadGetInfo2)(void* info); + typedef int (*_PadSetPortSetting)(u32 port_no, u32 port_setting); + typedef int (*_PadLddRegisterController)(); + typedef int (*_PadLddUnregisterController)(int handle); + typedef int (*_PadLddDataInsert)(int handle, void* data); + typedef int (*_PadLddGetPortNo)(int handle); + typedef int (*_PadPeriphGetInfo)(void* info); + typedef int (*_PadPeriphGetData)(u32 port_no, void* data); + typedef int (*_PadInfoPressMode)(u32 port_no); + typedef int (*_PadSetPressMode)(u32 port_no, u8 mode); + typedef int (*_PadInfoSensorMode)(u32 port_no); + typedef int (*_PadSetSensorMode)(u32 port_no, u8 mode); + typedef int (*_PadGetRawData)(u32 port_no, void* data); + typedef int (*_PadDbgLddRegisterController)(u32 device_capability); + typedef int (*_PadDbgLddSetDataInsertMode)(int handle, u8 mode); + typedef int (*_PadDbgPeriphRegisterDevice)(u16 vid, u16 pid, u32 pclass_type, u32 pclass_profile, void* mapping); + typedef int (*_PadDbgGetData)(u32 port_no, void* data); + + _PadInit PadInit; + _PadEnd PadEnd; + _PadClearBuf PadClearBuf; + _PadGetData PadGetData; + _PadGetDataExtra PadGetDataExtra; + _PadSetActDirect PadSetActDirect; + _PadGetInfo PadGetInfo; + _PadGetInfo2 PadGetInfo2; + _PadSetPortSetting PadSetPortSetting; + _PadLddRegisterController PadLddRegisterController; + _PadLddUnregisterController PadLddUnregisterController; + _PadLddDataInsert PadLddDataInsert; + _PadLddGetPortNo PadLddGetPortNo; + _PadPeriphGetInfo PadPeriphGetInfo; + _PadPeriphGetData PadPeriphGetData; + _PadInfoPressMode PadInfoPressMode; + _PadSetPressMode PadSetPressMode; + _PadInfoSensorMode PadInfoSensorMode; + _PadSetSensorMode PadSetSensorMode; + _PadGetRawData PadGetRawData; + _PadDbgLddRegisterController PadDbgLddRegisterController; + _PadDbgLddSetDataInsertMode PadDbgLddSetDataInsertMode; + _PadDbgPeriphRegisterDevice PadDbgPeriphRegisterDevice; + _PadDbgGetData PadDbgGetData; + + Ps3EmuPluginPAD() + { + Reset(); + } + + Ps3EmuPluginPAD(const wxString& path) + { + Load(path); + } + + virtual bool Test() + { + return Ps3EmuPlugin::Test() && + PadInit && + PadEnd && + PadClearBuf && + PadGetData && + PadGetDataExtra && + PadSetActDirect && + PadGetInfo && + PadGetInfo2 && + PadSetPortSetting && + PadLddRegisterController && + PadLddUnregisterController && + PadLddDataInsert && + PadLddGetPortNo && + PadPeriphGetInfo && + PadPeriphGetData && + PadInfoPressMode && + PadSetPressMode && + PadInfoSensorMode && + PadSetSensorMode && + PadGetRawData && + PadDbgLddRegisterController && + PadDbgLddSetDataInsertMode && + PadDbgPeriphRegisterDevice && + PadDbgGetData; + } + +protected: + virtual void Init() + { + LOAD_SYMBOL(PadInit); + LOAD_SYMBOL(PadEnd); + LOAD_SYMBOL(PadClearBuf); + LOAD_SYMBOL(PadGetData); + LOAD_SYMBOL(PadGetDataExtra); + LOAD_SYMBOL(PadSetActDirect); + LOAD_SYMBOL(PadGetInfo); + LOAD_SYMBOL(PadGetInfo2); + LOAD_SYMBOL(PadSetPortSetting); + LOAD_SYMBOL(PadLddRegisterController); + LOAD_SYMBOL(PadLddUnregisterController); + LOAD_SYMBOL(PadLddDataInsert); + LOAD_SYMBOL(PadLddGetPortNo); + LOAD_SYMBOL(PadPeriphGetInfo); + LOAD_SYMBOL(PadPeriphGetData); + LOAD_SYMBOL(PadInfoPressMode); + LOAD_SYMBOL(PadSetPressMode); + LOAD_SYMBOL(PadInfoSensorMode); + LOAD_SYMBOL(PadSetSensorMode); + LOAD_SYMBOL(PadGetRawData); + LOAD_SYMBOL(PadDbgLddRegisterController); + LOAD_SYMBOL(PadDbgLddSetDataInsertMode); + LOAD_SYMBOL(PadDbgPeriphRegisterDevice); + LOAD_SYMBOL(PadDbgGetData); + + Ps3EmuPlugin::Init(); + } + + virtual void Reset() + { + PadInit = nullptr; + PadEnd = nullptr; + PadClearBuf = nullptr; + PadGetData = nullptr; + PadGetDataExtra = nullptr; + PadSetActDirect = nullptr; + PadGetInfo = nullptr; + PadGetInfo2 = nullptr; + PadSetPortSetting = nullptr; + PadLddRegisterController = nullptr; + PadLddUnregisterController = nullptr; + PadLddDataInsert = nullptr; + PadLddGetPortNo = nullptr; + PadPeriphGetInfo = nullptr; + PadPeriphGetData = nullptr; + PadInfoPressMode = nullptr; + PadSetPressMode = nullptr; + PadInfoSensorMode = nullptr; + PadSetSensorMode = nullptr; + PadGetRawData = nullptr; + PadDbgLddRegisterController = nullptr; + PadDbgLddSetDataInsertMode = nullptr; + PadDbgPeriphRegisterDevice = nullptr; + PadDbgGetData = nullptr; + + Ps3EmuPlugin::Reset(); + } +}; + +struct PluginsManager +{ + struct PluginInfo + { + wxString path; + wxString name; + u32 type; + }; + + Array m_plugins; + ArrayF m_pad_plugins; + + void Load(const wxString& path) + { + if(!wxDirExists(path)) return; + + m_plugins.ClearD(); + wxDir dir(path); + + wxArrayString res; + wxDir::GetAllFiles(path, &res, "*.dll", wxDIR_FILES); + + for(u32 i=0; iAdd(new wxStaticText(parent, wxID_ANY, name), wxSizerFlags().Border(wxRIGHT, 5).Center().Left()); + s_panel->Add(cb = new wxComboBox(parent, wxID_ANY), wxSizerFlags().Center().Right()); + + return s_panel; + } + + void Dialog() + { + wxDialog dial(nullptr, wxID_ANY, "Select plugins...", wxDefaultPosition); + + wxBoxSizer& s_panel(*new wxBoxSizer(wxVERTICAL)); + + wxComboBox* cbox_pad_plugins; + s_panel.Add(GetNewComboBox(&dial, "Pad", cbox_pad_plugins), wxSizerFlags().Border(wxALL, 5).Expand()); + + for(u32 i=0; iAppend(m_plugins[i].name + " (" + wxFileName(m_plugins[i].path).GetName() + ")"); + } + } + + if(cbox_pad_plugins->GetCount()) cbox_pad_plugins->Select(0); + + dial.SetSizerAndFit(&s_panel); + dial.ShowModal(); + } +}; diff --git a/rpcs3/Ini.h b/rpcs3/Ini.h index da9e777323..829db83c46 100644 --- a/rpcs3/Ini.h +++ b/rpcs3/Ini.h @@ -55,7 +55,7 @@ template struct IniEntry : public Ini m_Config->SetPath(path); } - void SetValue(const T value) + void SetValue(const T& value) { m_value = value; } @@ -65,17 +65,22 @@ template struct IniEntry : public Ini return m_value; } - T LoadValue(const T defvalue) + T LoadValue(const T& defvalue) { return Ini::Load(m_key, defvalue); } + void SaveValue(const T& value) + { + Ini::Save(m_key, value); + } + void Save() { Ini::Save(m_key, m_value); } - T Load(const T defvalue) + T Load(const T& defvalue) { return (m_value = Ini::Load(m_key, defvalue)); } @@ -89,20 +94,36 @@ private: public: IniEntry CPUDecoderMode; IniEntry GSRenderMode; + IniEntry GSResolution; + IniEntry GSAspectRatio; + IniEntry GSVSyncEnable; IniEntry PadHandlerMode; public: Inis() : DefPath("EmuSettings") { - CPUDecoderMode.Init("DecoderMode", DefPath + "\\" + "CPU"); - GSRenderMode.Init("RenderMode", DefPath + "\\" + "GS"); - PadHandlerMode.Init("HandlerMode", DefPath + "\\" + "Pad"); + wxString path; + + path = DefPath + "\\" + "CPU"; + CPUDecoderMode.Init("DecoderMode", path); + + path = DefPath + "\\" + "GS"; + GSRenderMode.Init("RenderMode", path); + GSResolution.Init("Resolution", path); + GSAspectRatio.Init("AspectRatio", path); + GSVSyncEnable.Init("VSyncEnable", path); + + path = DefPath + "\\" + "Pad"; + PadHandlerMode.Init("HandlerMode", path); } void Load() { CPUDecoderMode.Load(2); GSRenderMode.Load(0); + GSResolution.Load(4); + GSAspectRatio.Load(1); + GSVSyncEnable.Load(false); PadHandlerMode.Load(0); } @@ -110,6 +131,9 @@ public: { CPUDecoderMode.Save(); GSRenderMode.Save(); + GSResolution.Save(); + GSAspectRatio.Save(); + GSVSyncEnable.Save(); PadHandlerMode.Save(); } }; diff --git a/rpcs3/Loader/ELF.cpp b/rpcs3/Loader/ELF.cpp index 3d5d1678f2..d967e4583e 100644 --- a/rpcs3/Loader/ELF.cpp +++ b/rpcs3/Loader/ELF.cpp @@ -2,17 +2,10 @@ #include "Loader.h" #include "ELF.h" -ELFLoader::ELFLoader(wxFile& f) +ELFLoader::ELFLoader(vfsStream& f) : elf_f(f) , LoaderBase() - , loader(NULL) -{ -} - -ELFLoader::ELFLoader(const wxString& path) - : elf_f(*new wxFile(path)) - , LoaderBase() - , loader(NULL) + , loader(nullptr) { } @@ -32,19 +25,21 @@ bool ELFLoader::LoadInfo() if(!loader || !loader->LoadInfo()) return false; + entry = loader->GetEntry(); + machine = loader->GetMachine(); + return true; } -bool ELFLoader::LoadData() +bool ELFLoader::LoadData(u64 offset) { - if(!loader || !loader->LoadData()) return false; - entry = loader->GetEntry(); - machine = loader->GetMachine(); + if(!loader || !loader->LoadData(offset)) return false; return true; } bool ELFLoader::Close() { - safe_delete(loader); + delete loader; + loader = nullptr; return elf_f.Close(); } diff --git a/rpcs3/Loader/ELF.h b/rpcs3/Loader/ELF.h index d68fa0de95..90d89e31f4 100644 --- a/rpcs3/Loader/ELF.h +++ b/rpcs3/Loader/ELF.h @@ -1,6 +1,7 @@ #pragma once #include "ELF64.h" #include "ELF32.h" +#include "Emu/FS/vfsStream.h" enum ElfClass { @@ -18,7 +19,7 @@ struct Elf_Ehdr { } - virtual void Load(wxFile& f) + virtual void Load(vfsStream& f) { e_magic = Read32(f); e_class = Read8(f); @@ -40,17 +41,16 @@ struct Elf_Ehdr class ELFLoader : public LoaderBase { - wxFile& elf_f; + vfsStream& elf_f; LoaderBase* loader; public: Elf_Ehdr ehdr; - ELFLoader(wxFile& f); - ELFLoader(const wxString& path); + ELFLoader(vfsStream& f); ~ELFLoader() {Close();} virtual bool LoadInfo(); - virtual bool LoadData(); + virtual bool LoadData(u64 offset = 0); virtual bool Close(); }; \ No newline at end of file diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 3d45ff9602..514ed3df17 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -1,18 +1,12 @@ #include "stdafx.h" #include "ELF32.h" -ELF32Loader::ELF32Loader(wxFile& f) +ELF32Loader::ELF32Loader(vfsStream& f) : elf32_f(f) , LoaderBase() { } -ELF32Loader::ELF32Loader(const wxString& path) - : elf32_f(*new wxFile(path)) - , LoaderBase() -{ -} - bool ELF32Loader::LoadInfo() { if(!elf32_f.IsOpened()) return false; @@ -24,13 +18,13 @@ bool ELF32Loader::LoadInfo() return true; } -bool ELF32Loader::LoadData() +bool ELF32Loader::LoadData(u64 offset) { if(!elf32_f.IsOpened()) return false; - if(!LoadEhdrData()) return false; - if(!LoadPhdrData()) return false; - if(!LoadShdrData()) return false; + if(!LoadEhdrData(offset)) return false; + if(!LoadPhdrData(offset)) return false; + if(!LoadShdrData(offset)) return false; return true; } @@ -81,9 +75,9 @@ bool ELF32Loader::LoadPhdrInfo() elf32_f.Seek(ehdr.e_phoff); for(uint i=0; iLoad(elf32_f); + phdr_arr.Move(phdr); } return true; @@ -94,9 +88,9 @@ bool ELF32Loader::LoadShdrInfo() elf32_f.Seek(ehdr.e_shoff); for(u32 i=0; iLoad(elf32_f); + shdr_arr.Move(shdr); } if(ehdr.e_shstrndx >= shdr_arr.GetCount()) @@ -123,7 +117,7 @@ bool ELF32Loader::LoadShdrInfo() return true; } -bool ELF32Loader::LoadEhdrData() +bool ELF32Loader::LoadEhdrData(u64 offset) { #ifdef LOADER_DEBUG ConLog.SkipLn(); @@ -133,7 +127,7 @@ bool ELF32Loader::LoadEhdrData() return true; } -bool ELF32Loader::LoadPhdrData() +bool ELF32Loader::LoadPhdrData(u64 offset) { for(u32 i=0; i shdr_arr; Array phdr_arr; - ELF32Loader(wxFile& f); - ELF32Loader(const wxString& path); + ELF32Loader(vfsStream& f); ~ELF32Loader() {Close();} virtual bool LoadInfo(); - virtual bool LoadData(); + virtual bool LoadData(u64 offset); virtual bool Close(); private: bool LoadEhdrInfo(); bool LoadPhdrInfo(); bool LoadShdrInfo(); - bool LoadEhdrData(); - bool LoadPhdrData(); - bool LoadShdrData(); + + bool LoadEhdrData(u64 offset); + bool LoadPhdrData(u64 offset); + bool LoadShdrData(u64 offset); }; \ No newline at end of file diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index a5463f445c..817d115026 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -1,18 +1,14 @@ #include "stdafx.h" #include "ELF64.h" +#include "Gui/CompilerELF.h" +using namespace PPU_opcodes; -ELF64Loader::ELF64Loader(wxFile& f) +ELF64Loader::ELF64Loader(vfsStream& f) : elf64_f(f) , LoaderBase() { } -ELF64Loader::ELF64Loader(const wxString& path) - : elf64_f(*new wxFile(path)) - , LoaderBase() -{ -} - bool ELF64Loader::LoadInfo() { if(!elf64_f.IsOpened()) return false; @@ -24,13 +20,13 @@ bool ELF64Loader::LoadInfo() return true; } -bool ELF64Loader::LoadData() +bool ELF64Loader::LoadData(u64 offset) { if(!elf64_f.IsOpened()) return false; - if(!LoadEhdrData()) return false; - if(!LoadPhdrData()) return false; - if(!LoadShdrData()) return false; + if(!LoadEhdrData(offset)) return false; + if(!LoadPhdrData(offset)) return false; + if(!LoadShdrData(offset)) return false; return true; } @@ -40,9 +36,9 @@ bool ELF64Loader::Close() return elf64_f.Close(); } -bool ELF64Loader::LoadEhdrInfo() +bool ELF64Loader::LoadEhdrInfo(s64 offset) { - elf64_f.Seek(0); + elf64_f.Seek(offset < 0 ? 0 : offset); ehdr.Load(elf64_f); if(!ehdr.CheckMagic()) return false; @@ -82,7 +78,7 @@ bool ELF64Loader::LoadEhdrInfo() return true; } -bool ELF64Loader::LoadPhdrInfo() +bool ELF64Loader::LoadPhdrInfo(s64 offset) { phdr_arr.Clear(); @@ -92,18 +88,19 @@ bool ELF64Loader::LoadPhdrInfo() return false; } - elf64_f.Seek(ehdr.e_phoff); + elf64_f.Seek(offset < 0 ? ehdr.e_phoff : offset); + for(u32 i=0; iLoad(elf64_f); + phdr_arr.Move(phdr); } return true; } -bool ELF64Loader::LoadShdrInfo() +bool ELF64Loader::LoadShdrInfo(s64 offset) { shdr_arr.Clear(); shdr_name_arr.Clear(); @@ -113,12 +110,12 @@ bool ELF64Loader::LoadShdrInfo() return false; } - elf64_f.Seek(ehdr.e_shoff); + elf64_f.Seek(offset < 0 ? ehdr.e_shoff : offset); for(u32 i=0; iLoad(elf64_f); + shdr_arr.Move(shdr); } if(ehdr.e_shstrndx >= shdr_arr.GetCount()) @@ -129,7 +126,7 @@ bool ELF64Loader::LoadShdrInfo() for(u32 i=0; iSetLoaded(); + } + else + { + ConLog.Warning("Unknown module '%s'", module_name); + } + #ifdef LOADER_DEBUG ConLog.SkipLn(); ConLog.Write("*** size: 0x%x", stub.s_size); @@ -281,21 +294,41 @@ bool ELF64Loader::LoadPhdrData() ConLog.Write("*** unk0: 0x%x", stub.s_unk0); ConLog.Write("*** unk1: 0x%x", stub.s_unk1); ConLog.Write("*** imports: %d", stub.s_imports); - ConLog.Write("*** module name: %s [0x%x]", Memory.ReadString(stub.s_modulename), stub.s_modulename); + ConLog.Write("*** module name: %s [0x%x]", module_name, stub.s_modulename); ConLog.Write("*** nid: 0x%x", stub.s_nid); ConLog.Write("*** text: 0x%x", stub.s_text); #endif + static const u32 section = 4 * 3; + u64 tbl = Memory.MainMem.Alloc(stub.s_imports * 4 * 2); + u64 dst = Memory.MainMem.Alloc(stub.s_imports * section); for(u32 i=0; iLoad(nid)) + { + ConLog.Warning("Unknown function 0x%08x in '%s' module", nid, module_name); + } + } #ifdef LOADER_DEBUG ConLog.Write("import %d:", i+1); - ConLog.Write("*** nid: 0x%x", nid); - ConLog.Write("*** text: 0x%x", text); + ConLog.Write("*** nid: 0x%x (0x%x)", nid, stub.s_nid + i*4); + ConLog.Write("*** text: 0x%x (0x%x)", text, stub.s_text + i*4); #endif - Memory.MemFlags.Add(text, stub.s_text + i*4, nid); + Memory.Write32(stub.s_text + i*4, tbl + i*8); + + mem32_t out_tbl(tbl + i*8); + out_tbl += dst + i*section; + 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); } } #ifdef LOADER_DEBUG @@ -313,7 +346,7 @@ bool ELF64Loader::LoadPhdrData() return true; } -bool ELF64Loader::LoadShdrData() +bool ELF64Loader::LoadShdrData(u64 offset) { u64 max_addr = 0; @@ -341,12 +374,12 @@ bool ELF64Loader::LoadShdrData() const u64 addr = shdr.sh_addr; const u64 size = shdr.sh_size; - if(size == 0 || !Memory.IsGoodAddr(addr, size)) continue; + if(size == 0 || !Memory.IsGoodAddr(offset + addr, size)) continue; switch(shdr.sh_type) { case SHT_NOBITS: - memset(&Memory[addr], 0, size); + memset(&Memory[offset + addr], 0, size); break; case SHT_PROGBITS: diff --git a/rpcs3/Loader/ELF64.h b/rpcs3/Loader/ELF64.h index 73dcbe8749..0f3d0bcb95 100644 --- a/rpcs3/Loader/ELF64.h +++ b/rpcs3/Loader/ELF64.h @@ -23,7 +23,7 @@ struct Elf64_Ehdr u16 e_shnum; u16 e_shstrndx; - void Load(wxFile& f) + void Load(vfsStream& f) { e_magic = Read32(f); e_class = Read8(f); @@ -88,7 +88,7 @@ struct Elf64_Shdr u64 sh_addralign; u64 sh_entsize; - void Load(wxFile& f) + void Load(vfsStream& f) { sh_name = Read32(f); sh_type = Read32(f); @@ -130,7 +130,7 @@ struct Elf64_Phdr u64 p_memsz; u64 p_align; - void Load(wxFile& f) + void Load(vfsStream& f) { p_type = Read32(f); p_flags = Read32(f); @@ -159,7 +159,7 @@ struct Elf64_Phdr class ELF64Loader : public LoaderBase { - wxFile& elf64_f; + vfsStream& elf64_f; public: Elf64_Ehdr ehdr; @@ -167,19 +167,21 @@ public: Array shdr_arr; Array phdr_arr; - ELF64Loader(wxFile& f); - ELF64Loader(const wxString& path); + ELF64Loader(vfsStream& f); ~ELF64Loader() {Close();} virtual bool LoadInfo(); - virtual bool LoadData(); + virtual bool LoadData(u64 offset = 0); virtual bool Close(); + bool LoadEhdrInfo(s64 offset=-1); + bool LoadPhdrInfo(s64 offset=-1); + bool LoadShdrInfo(s64 offset=-1); + private: - bool LoadEhdrInfo(); - bool LoadPhdrInfo(); - bool LoadShdrInfo(); - bool LoadEhdrData(); - bool LoadPhdrData(); - bool LoadShdrData(); + bool LoadEhdrData(u64 offset); + bool LoadPhdrData(u64 offset); + bool LoadShdrData(u64 offset); + + //bool LoadImports(); }; \ No newline at end of file diff --git a/rpcs3/Loader/Loader.cpp b/rpcs3/Loader/Loader.cpp index 81160c10ad..929216a9ca 100644 --- a/rpcs3/Loader/Loader.cpp +++ b/rpcs3/Loader/Loader.cpp @@ -3,37 +3,7 @@ #include "ELF.h" #include "SELF.h" #include "PSF.h" - -u8 Read8(wxFile& f) -{ - u8 ret; - f.Read(&ret, sizeof(u8)); - return ret; -} - -u16 Read16(wxFile& f) -{ - const u8 c0 = Read8(f); - const u8 c1 = Read8(f); - - return ((u16)c0 << 8) | (u16)c1; -} - -u32 Read32(wxFile& f) -{ - const u16 c0 = Read16(f); - const u16 c1 = Read16(f); - - return ((u32)c0 << 16) | (u32)c1; -} - -u64 Read64(wxFile& f) -{ - const u32 c0 = Read32(f); - const u32 c1 = Read32(f); - - return ((u64)c0 << 32) | (u64)c1; -} +#include "Emu/FS/vfsLocalFile.h" const wxString Ehdr_DataToString(const u8 data) { @@ -121,64 +91,61 @@ const wxString Phdr_TypeToString(const u32 type) return wxString::Format("Unknown (%x)", type); } -Loader::Loader() : f(NULL) +Loader::Loader() : m_stream(nullptr) { } -Loader::Loader(const wxString& path) : f(new wxFile(path)) +Loader::Loader(vfsFileBase& stream) : m_stream(&stream) { } -void Loader::Open(const wxString& path) +void Loader::Open(vfsFileBase& stream) { - m_path = path; - f = new wxFile(path); -} - -void Loader::Open(wxFile& _f, const wxString& path) -{ - m_path = path; - f = &_f; + m_stream = &stream; } LoaderBase* Loader::SearchLoader() { - if(!f) return NULL; + if(!m_stream) return nullptr; - LoaderBase* l = NULL; + LoaderBase* l; - if((l=new ELFLoader(*f))->LoadInfo()) return l; - safe_delete(l); - if((l=new SELFLoader(*f))->LoadInfo()) return l; - safe_delete(l); - return NULL; + if((l=new ELFLoader(*m_stream))->LoadInfo()) return l; + delete l; + + if((l=new SELFLoader(*m_stream))->LoadInfo()) return l; + delete l; + + return nullptr; } bool Loader::Load() { - LoaderBase* l = SearchLoader(); + static const u64 spu_offset = 0x10000; + + ScopedPtr l = SearchLoader(); + if(!l) { ConLog.Error("Unknown file type"); return false; } - if(!l->LoadData()) + if(!l->LoadData(l->GetMachine() == MACHINE_SPU ? spu_offset : 0)) { ConLog.Error("Broken file"); - safe_delete(l); return false; } machine = l->GetMachine(); - entry = l->GetEntry(); - safe_delete(l); + entry = l->GetMachine() == MACHINE_SPU ? l->GetEntry() + spu_offset : l->GetEntry(); - const wxString& root = wxFileName(wxFileName(m_path).GetPath()).GetPath(); + const wxString& root = wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath(); const wxString& psf_path = root + "\\" + "PARAM.SFO"; if(wxFileExists(psf_path)) { - PSFLoader psf_l(psf_path); + vfsLocalFile f(psf_path); + PSFLoader psf_l(f); if(psf_l.Load()) { CurGameInfo = psf_l.m_info; @@ -188,13 +155,4 @@ bool Loader::Load() } return true; -} - -Loader::~Loader() -{ - if(f) - { - f->Close(); - f = NULL; - } } \ No newline at end of file diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index 7f2c04d41f..034c53dc29 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/FS/vfsFileBase.h" #ifdef _DEBUG #define LOADER_DEBUG @@ -13,7 +14,7 @@ enum Elf_Machine enum ShdrType { - SHT_NULL, + SHT_NULL, SHT_PROGBITS, SHT_SYMTAB, SHT_STRTAB, @@ -35,10 +36,27 @@ enum ShdrFlag SHF_MASKPROC = 0xf0000000, }; -u8 Read8 (wxFile& f); -u16 Read16(wxFile& f); -u32 Read32(wxFile& f); -u64 Read64(wxFile& f); +__forceinline static u8 Read8(vfsStream& f) +{ + u8 ret; + f.Read(&ret, sizeof(u8)); + return ret; +} + +__forceinline static u16 Read16(vfsStream& f) +{ + return ((u16)Read8(f) << 8) | (u16)Read8(f); +} + +__forceinline static u32 Read32(vfsStream& f) +{ + return (Read16(f) << 16) | Read16(f); +} + +__forceinline static u64 Read64(vfsStream& f) +{ + return ((u64)Read32(f) << 32) | (u64)Read32(f); +} const wxString Ehdr_DataToString(const u8 data); const wxString Ehdr_TypeToString(const u16 type); @@ -111,24 +129,22 @@ protected: } public: - virtual bool LoadInfo(){return false;}; - virtual bool LoadData(){return false;}; - virtual bool Close(){return false;}; + virtual bool LoadInfo() { return false; } + virtual bool LoadData(u64 offset = 0) { return false; } Elf_Machine GetMachine() { return machine; } u32 GetEntry() { return entry; } }; class Loader : public LoaderBase { - wxFile* f; - wxString m_path; + vfsFileBase* m_stream; public: Loader(); - Loader(const wxString& path); + Loader(vfsFileBase& stream); + void Open(const wxString& path); - void Open(wxFile& f, const wxString& path); - ~Loader(); + void Open(vfsFileBase& stream); bool Load(); diff --git a/rpcs3/Loader/PSF.cpp b/rpcs3/Loader/PSF.cpp index 177d4bbe1c..7e7c1a2ac9 100644 --- a/rpcs3/Loader/PSF.cpp +++ b/rpcs3/Loader/PSF.cpp @@ -1,11 +1,7 @@ #include "stdafx.h" #include "PSF.h" -PSFLoader::PSFLoader(wxFile& f) : psf_f(f) -{ -} - -PSFLoader::PSFLoader(const wxString& path) : psf_f(*new wxFile(path)) +PSFLoader::PSFLoader(vfsStream& f) : psf_f(f) { } @@ -80,7 +76,7 @@ bool PSFLoader::LoadKeyTable() struct PsfHelper { - static wxString ReadString(wxFile& f, const u32 size) + static wxString ReadString(vfsStream& f, const u32 size) { wxString ret = wxEmptyString; @@ -92,7 +88,7 @@ struct PsfHelper return ret; } - static wxString ReadString(wxFile& f) + static wxString ReadString(vfsStream& f) { wxString ret = wxEmptyString; @@ -106,14 +102,14 @@ struct PsfHelper return ret; } - static char ReadChar(wxFile& f) + static char ReadChar(vfsStream& f) { char c; f.Read(&c, 1); return c; } - static char ReadCharNN(wxFile& f) + static char ReadCharNN(vfsStream& f) { char c; while(!f.Eof()) @@ -125,7 +121,7 @@ struct PsfHelper return c; } - static void GoToNN(wxFile& f) + static void GoToNN(vfsStream& f) { while(!f.Eof()) { diff --git a/rpcs3/Loader/PSF.h b/rpcs3/Loader/PSF.h index 6359fbdf1d..c665734408 100644 --- a/rpcs3/Loader/PSF.h +++ b/rpcs3/Loader/PSF.h @@ -23,12 +23,11 @@ struct PsfDefTbl class PSFLoader { - wxFile& psf_f; + vfsStream& psf_f; bool m_show_log; public: - PSFLoader(wxFile& f); - PSFLoader(const wxString& path); + PSFLoader(vfsStream& f); wxArrayString m_table; GameInfo m_info; diff --git a/rpcs3/Loader/SELF.cpp b/rpcs3/Loader/SELF.cpp index 2064f787fd..842d74263a 100644 --- a/rpcs3/Loader/SELF.cpp +++ b/rpcs3/Loader/SELF.cpp @@ -1,18 +1,13 @@ #include "stdafx.h" #include "SELF.h" +#include "ELF64.h" -SELFLoader::SELFLoader(wxFile& f) +SELFLoader::SELFLoader(vfsStream& f) : self_f(f) , LoaderBase() { } -SELFLoader::SELFLoader(const wxString& path) - : self_f(*new wxFile(path)) - , LoaderBase() -{ -} - bool SELFLoader::LoadInfo() { if(!self_f.IsOpened()) return false; @@ -24,12 +19,26 @@ bool SELFLoader::LoadInfo() return true; } -bool SELFLoader::LoadData() +bool SELFLoader::LoadData(u64 offset) { if(!self_f.IsOpened()) return false; sce_hdr.Show(); self_hdr.Show(); + + ELF64Loader l(self_f); + if( !l.LoadEhdrInfo(self_hdr.se_elfoff) || + !l.LoadPhdrInfo(self_hdr.se_phdroff) || + !l.LoadShdrInfo(self_hdr.se_shdroff) || + !l.LoadData(offset) ) + { + ConLog.Error("Broken SELF file."); + + return false; + } + + return true; + ConLog.Error("Boot SELF not supported yet!"); return false; } \ No newline at end of file diff --git a/rpcs3/Loader/SELF.h b/rpcs3/Loader/SELF.h index c68e45861f..63ac82f90f 100644 --- a/rpcs3/Loader/SELF.h +++ b/rpcs3/Loader/SELF.h @@ -11,7 +11,7 @@ struct SceHeader u64 se_hsize; u64 se_esize; - void Load(wxFile& f) + void Load(vfsStream& f) { se_magic = Read32(f); se_hver = Read32(f); @@ -50,7 +50,7 @@ struct SelfHeader u64 se_controlsize; u64 pad; - void Load(wxFile& f) + void Load(vfsStream& f) { se_htype = Read64(f); se_appinfooff = Read64(f); @@ -80,16 +80,14 @@ struct SelfHeader class SELFLoader : public LoaderBase { - wxFile& self_f; + vfsStream& self_f; SceHeader sce_hdr; SelfHeader self_hdr; public: - SELFLoader(wxFile& f); - SELFLoader(const wxString& path); - ~SELFLoader() {Close();} + SELFLoader(vfsStream& f); virtual bool LoadInfo(); - virtual bool LoadData(); + virtual bool LoadData(u64 offset = 0); }; \ No newline at end of file diff --git a/rpcs3/rpcs3.cpp b/rpcs3/rpcs3.cpp index f285cfb2e9..f716e8b532 100644 --- a/rpcs3/rpcs3.cpp +++ b/rpcs3/rpcs3.cpp @@ -3,6 +3,9 @@ #include "Ini.h" #include "Emu/System.h" #include +#include "Gui/CompilerELF.h" + +const wxEventType wxEVT_DBG_COMMAND = wxNewEventType(); IMPLEMENT_APP(Rpcs3App) Rpcs3App* TheApp; @@ -15,13 +18,20 @@ bool Rpcs3App::OnInit() Ini.Load(); - ConLogFrame = new LogFrame(); - ConLogFrame->Show(); - m_MainFrame = new MainFrame(); + SetTopWindow(m_MainFrame); Emu.Init(); + + (new CompilerELF(m_MainFrame))->Show(); + m_debugger_frame = new DebuggerPanel(m_MainFrame); + ConLogFrame = new LogFrame(m_MainFrame); + + m_MainFrame->AddPane(ConLogFrame, "Log", wxAUI_DOCK_BOTTOM); + m_MainFrame->AddPane(m_debugger_frame, "Debugger", wxAUI_DOCK_RIGHT); + //ConLogFrame->Show(); m_MainFrame->Show(); + m_MainFrame->DoSettings(true); return true; } @@ -35,6 +45,13 @@ void Rpcs3App::Exit() wxApp::Exit(); } +void Rpcs3App::SendDbgCommand(DbgCommand id, PPCThread* thr) +{ + wxCommandEvent event(wxEVT_DBG_COMMAND, id); + event.SetClientData(thr); + AddPendingEvent(event); +} + /* CPUThread& GetCPU(const u8 core) { diff --git a/rpcs3/rpcs3.h b/rpcs3/rpcs3.h index a62ec80c0c..c44142c5ff 100644 --- a/rpcs3/rpcs3.h +++ b/rpcs3/rpcs3.h @@ -1,22 +1,52 @@ #pragma once #include "Gui/MainFrame.h" +#include "Gui/Debugger.h" template T min(const T a, const T b) { return a < b ? a : b; } template T max(const T a, const T b) { return a > b ? a : b; } -#define re(val) MemoryBase::Reverse(val) +//#define re(val) MemoryBase::Reverse(val) #define re64(val) MemoryBase::Reverse64(val) #define re32(val) MemoryBase::Reverse32(val) #define re16(val) MemoryBase::Reverse16(val) +template T re(const T val) { return MemoryBase::Reverse(val); } +template void re(T1& dst, const T2 val) { dst = MemoryBase::Reverse(val); } + + +extern const wxEventType wxEVT_DBG_COMMAND; + +enum DbgCommand +{ + DID_FIRST_COMMAND = 0x500, + + DID_START_EMU, + DID_STOP_EMU, + DID_PAUSE_EMU, + DID_RESUME_EMU, + DID_CREATE_THREAD, + DID_REMOVE_THREAD, + DID_RENAME_THREAD, + DID_START_THREAD, + DID_STOP_THREAD, + DID_PAUSE_THREAD, + DID_RESUME_THREAD, + DID_EXEC_THREAD, + + DID_LAST_COMMAND, +}; + class Rpcs3App : public wxApp { public: MainFrame* m_MainFrame; + DebuggerPanel* m_debugger_frame; virtual bool OnInit(); virtual void Exit(); + + void SendDbgCommand(DbgCommand id, PPCThread* thr=nullptr); }; DECLARE_APP(Rpcs3App) diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index a7afadc24c..7611efb926 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -186,11 +186,18 @@ + + + + + + + @@ -203,23 +210,34 @@ + + + + + + + + + + + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 5c81bf7fd5..b4d5f92feb 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -38,6 +38,12 @@ {9bd88f78-8528-48f3-b9e0-78e06476b04d} + + {fd7cea02-e77f-41b1-8b61-f78e7d280e04} + + + {dfd581c4-aed0-4229-bb30-7ee5816049e1} + @@ -187,6 +193,60 @@ Utilities + + Emu\SysCalls + + + Emu\SysCalls\lv2 + + + Emu\SysCalls + + + Emu\FS + + + Emu\FS + + + Emu\FS + + + Emu\FS + + + Emu\FS + + + Emu\SysCalls\lv2 + + + Emu\FS + + + Emu\SysCalls\lv2 + + + Emu\SysCalls\lv2 + + + Emu\SysCalls\Modules + + + Emu\SysCalls\Modules + + + Emu\SysCalls\Modules + + + Emu\SysCalls\Modules + + + Gui + + + rpcs3 + diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index b3b249bfe5..35052a2feb 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -17,17 +17,17 @@ #include -#define uint unsigned int +typedef unsigned int uint; -#define u8 unsigned __int8 -#define u16 unsigned __int16 -#define u32 unsigned __int32 -#define u64 unsigned __int64 +typedef unsigned __int8 u8; +typedef unsigned __int16 u16; +typedef unsigned __int32 u32; +typedef unsigned __int64 u64; -#define s8 signed __int8 -#define s16 signed __int16 -#define s32 signed __int32 -#define s64 signed __int64 +typedef signed __int8 s8; +typedef signed __int16 s16; +typedef signed __int32 s32; +typedef signed __int64 s64; union u128 { @@ -174,13 +174,14 @@ static void safe_realloc(T* ptr, uint new_size) ptr = (T*)((ptr == NULL) ? malloc(new_size * sizeof(T)) : realloc(ptr, new_size * sizeof(T))); } -#define safe_delete(x) {free(x);(x)=NULL;} +#define safe_delete(x) {free(x);(x)=nullptr;} enum Status { Runned, Paused, Stopped, + Ready, }; #include "Utilities/Thread.h" @@ -188,11 +189,19 @@ enum Status #include "Utilities/Timer.h" #include "Utilities/IdManager.h" +#include "AppConnector.h" + #include "Ini.h" #include "Gui/FrameBase.h" #include "Gui/ConLog.h" #include "Emu/System.h" #include "Emu/Memory/Memory.h" +#include "Emu/Cell/PPUThread.h" + +#include "Emu/FS/vfsFileBase.h" +#include "Emu/FS/vfsLocalFile.h" +#include "Emu/FS/vfsStream.h" +#include "Emu/FS/vfsStreamMemory.h" #include "rpcs3.h" #define _PRGNAME_ "RPCS3"