From 598d929abaa47281322b14eb840cd11c959e9692 Mon Sep 17 00:00:00 2001 From: DHrpcs3 Date: Wed, 19 Nov 2014 16:16:30 +0200 Subject: [PATCH] Implemented LLE Modules Manager (draft) Improved loader core. Implemented *_thread wrappers. Minor fixes. Temporary disabled ELF Compiler & DisAsm frame. --- Utilities/BEType.h | 114 +- rpcs3/Crypto/unself.cpp | 95 ++ rpcs3/Crypto/unself.h | 289 ++++- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 13 + rpcs3/Emu/ARMv7/ARMv7Thread.h | 45 + rpcs3/Emu/CPU/CPUDecoder.h | 2 +- rpcs3/Emu/CPU/CPUThread.h | 39 + rpcs3/Emu/Cell/PPCDecoder.cpp | 2 +- rpcs3/Emu/Cell/PPUInstrTable.h | 1210 +++++++++--------- rpcs3/Emu/Cell/PPUInterpreter.h | 38 +- rpcs3/Emu/Cell/PPUProgramCompiler.cpp | 71 +- rpcs3/Emu/Cell/PPUProgramCompiler.h | 3 +- rpcs3/Emu/Cell/PPUThread.cpp | 26 +- rpcs3/Emu/Cell/PPUThread.h | 56 +- rpcs3/Emu/Cell/SPUThread.cpp | 14 +- rpcs3/Emu/Cell/SPUThread.h | 46 + rpcs3/Emu/Memory/Memory.cpp | 47 +- rpcs3/Emu/Memory/Memory.h | 11 +- rpcs3/Emu/Memory/vm.cpp | 136 +- rpcs3/Emu/Memory/vm.h | 88 +- rpcs3/Emu/Memory/vm_ptr.h | 152 ++- rpcs3/Emu/SysCalls/ModuleManager.h | 18 + rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp | 7 +- rpcs3/Emu/SysCalls/Modules/cellPamf.cpp | 72 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 9 +- rpcs3/Emu/SysCalls/Modules/sys_net.cpp | 2 +- rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 10 +- rpcs3/Emu/SysCalls/lv2/sys_prx.cpp | 4 +- rpcs3/Emu/SysCalls/lv2/sys_prx.h | 65 +- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 18 +- rpcs3/Emu/SysCalls/lv2/sys_spu.h | 4 + rpcs3/Emu/System.cpp | 151 +-- rpcs3/Emu/System.h | 24 +- rpcs3/Gui/CompilerELF.cpp | 2 +- rpcs3/Gui/DisAsmFrame.cpp | 2 + rpcs3/Gui/DisAsmFrame.h | 6 +- rpcs3/Gui/LLEModulesManager.cpp | 65 + rpcs3/Gui/LLEModulesManager.h | 13 + rpcs3/Gui/MainFrame.cpp | 10 + rpcs3/Gui/MainFrame.h | 1 + rpcs3/Loader/ELF.cpp | 63 - rpcs3/Loader/ELF.h | 53 - rpcs3/Loader/ELF32.cpp | 678 ++-------- rpcs3/Loader/ELF32.h | 260 ++-- rpcs3/Loader/ELF64.cpp | 956 +++++++------- rpcs3/Loader/ELF64.h | 217 ++-- rpcs3/Loader/Loader.cpp | 130 +- rpcs3/Loader/Loader.h | 124 +- rpcs3/Loader/SELF.cpp | 99 -- rpcs3/Loader/SELF.h | 53 - rpcs3/Loader/TROPUSR.cpp | 2 +- rpcs3/emucore.vcxproj | 4 - rpcs3/emucore.vcxproj.filters | 12 - rpcs3/rpcs3.vcxproj | 2 + rpcs3/rpcs3.vcxproj.filters | 6 + rpcs3/stdafx.h | 5 +- 57 files changed, 2844 insertions(+), 2804 deletions(-) create mode 100644 rpcs3/Gui/LLEModulesManager.cpp create mode 100644 rpcs3/Gui/LLEModulesManager.h delete mode 100644 rpcs3/Loader/ELF.cpp delete mode 100644 rpcs3/Loader/ELF.h delete mode 100644 rpcs3/Loader/SELF.cpp delete mode 100644 rpcs3/Loader/SELF.h diff --git a/Utilities/BEType.h b/Utilities/BEType.h index 1bbc0a8114..cfe3dc5b0f 100644 --- a/Utilities/BEType.h +++ b/Utilities/BEType.h @@ -451,7 +451,13 @@ template class be_t { static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type"); - T m_data; + +public: + typedef typename std::remove_cv::type type; + static const bool is_le_machine = true; + +private: + type m_data; template struct _convert @@ -482,55 +488,77 @@ class be_t return (be_t&)res; } }; + public: - typedef T type; - const T& ToBE() const { return m_data; } - T ToLE() const + type ToLE() const { return se_t::func(m_data); } - void FromBE(const T& value) + void FromBE(const type& value) { m_data = value; } - void FromLE(const T& value) + void FromLE(const type& value) { m_data = se_t::func(value); } - static be_t make(const T value) + static be_t MakeFromLE(const type value) { - T data = se_t::func(value); + type data = se_t::func(value); return (be_t&)data; } - //template - operator const T() const + static be_t MakeFromBE(const type value) { - return ToLE(); + return (be_t&)value; + } + + //make be_t from current machine byte ordering + static be_t make(const type value) + { + return is_le_machine ? MakeFromLE(value) : MakeFromBE(value); + } + + //get value in current machine byte ordering + __forceinline type value() const + { + return is_le_machine ? ToLE() : ToBE(); + } + + be_t() = default; + be_t(const be_t& value) = default; + + be_t(type value) + { + m_data = se_t::func(value); } be_t& operator = (const be_t& value) = default; - be_t& operator = (T value) + be_t& operator = (type value) { - m_data = se_t::func(value); + m_data = se_t::func(value); return *this; } + operator type() const + { + return value(); + } + template operator const be_t() const { - return be_t::make(ToLE()); - //return _convert sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data); + return _convert sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data); } template be_t& operator += (T1 right) { return *this = T(*this) + right; } @@ -577,62 +605,6 @@ public: be_t& operator-- () { *this -= 1; return *this; } }; -template -class be_t -{ - static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type"); - const T m_data; - -public: - typedef const T type; - - const T& ToBE() const - { - return m_data; - } - - const T ToLE() const - { - return se_t::func(m_data); - } - - static be_t make(const T value) - { - const T data = se_t::func(value); - return (be_t&)data; - } - - //template - operator const T() const - { - return ToLE(); - } - - template - operator const be_t() const - { - return be_t::make(ToLE()); - } - - template be_t operator & (const be_t& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; } - template be_t operator | (const be_t& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; } - template be_t operator ^ (const be_t& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; } - - template bool operator == (T1 right) const { return (T1)ToLE() == right; } - template bool operator != (T1 right) const { return !(*this == right); } - template bool operator > (T1 right) const { return (T1)ToLE() > right; } - template bool operator < (T1 right) const { return (T1)ToLE() < right; } - template bool operator >= (T1 right) const { return (T1)ToLE() >= right; } - template bool operator <= (T1 right) const { return (T1)ToLE() <= right; } - - template bool operator == (const be_t& right) const { return ToBE() == right.ToBE(); } - template bool operator != (const be_t& right) const { return !(*this == right); } - template bool operator > (const be_t& right) const { return (T1)ToLE() > right.ToLE(); } - template bool operator < (const be_t& right) const { return (T1)ToLE() < right.ToLE(); } - template bool operator >= (const be_t& right) const { return (T1)ToLE() >= right.ToLE(); } - template bool operator <= (const be_t& right) const { return (T1)ToLE() <= right.ToLE(); } -}; - template struct is_be_t : public std::integral_constant {}; diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 67ef26a4b1..28b464c100 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -10,6 +10,101 @@ #include #include + +void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr) +{ +Write32(f, ehdr.e_magic); +Write8(f, ehdr.e_class); +Write8(f, ehdr.e_data); +Write8(f, ehdr.e_curver); +Write8(f, ehdr.e_os_abi); +Write64(f, ehdr.e_abi_ver); +Write16(f, ehdr.e_type); +Write16(f, ehdr.e_machine); +Write32(f, ehdr.e_version); +Write64(f, ehdr.e_entry); +Write64(f, ehdr.e_phoff); +Write64(f, ehdr.e_shoff); +Write32(f, ehdr.e_flags); +Write16(f, ehdr.e_ehsize); +Write16(f, ehdr.e_phentsize); +Write16(f, ehdr.e_phnum); +Write16(f, ehdr.e_shentsize); +Write16(f, ehdr.e_shnum); +Write16(f, ehdr.e_shstrndx); +} +void WritePhdr(rFile& f, Elf64_Phdr& phdr) +{ +Write32(f, phdr.p_type); +Write32(f, phdr.p_flags); +Write64(f, phdr.p_offset); +Write64(f, phdr.p_vaddr); +Write64(f, phdr.p_paddr); +Write64(f, phdr.p_filesz); +Write64(f, phdr.p_memsz); +Write64(f, phdr.p_align); +} +void WriteShdr(rFile& f, Elf64_Shdr& shdr) +{ +Write32(f, shdr.sh_name); +Write32(f, shdr.sh_type); +Write64(f, shdr.sh_flags); +Write64(f, shdr.sh_addr); +Write64(f, shdr.sh_offset); +Write64(f, shdr.sh_size); +Write32(f, shdr.sh_link); +Write32(f, shdr.sh_info); +Write64(f, shdr.sh_addralign); +Write64(f, shdr.sh_entsize); +} +void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr) +{ + Write32(f, ehdr.e_magic); + Write8(f, ehdr.e_class); + Write8(f, ehdr.e_data); + Write8(f, ehdr.e_curver); + Write8(f, ehdr.e_os_abi); + Write64(f, ehdr.e_abi_ver); + Write16(f, ehdr.e_type); + Write16(f, ehdr.e_machine); + Write32(f, ehdr.e_version); + Write32(f, ehdr.e_entry); + Write32(f, ehdr.e_phoff); + Write32(f, ehdr.e_shoff); + Write32(f, ehdr.e_flags); + Write16(f, ehdr.e_ehsize); + Write16(f, ehdr.e_phentsize); + Write16(f, ehdr.e_phnum); + Write16(f, ehdr.e_shentsize); + Write16(f, ehdr.e_shnum); + Write16(f, ehdr.e_shstrndx); +} +void WritePhdr(rFile& f, Elf32_Phdr& phdr) +{ + Write32(f, phdr.p_type); + Write32(f, phdr.p_offset); + Write32(f, phdr.p_vaddr); + Write32(f, phdr.p_paddr); + Write32(f, phdr.p_filesz); + Write32(f, phdr.p_memsz); + Write32(f, phdr.p_flags); + Write32(f, phdr.p_align); +} +void WriteShdr(rFile& f, Elf32_Shdr& shdr) +{ + Write32(f, shdr.sh_name); + Write32(f, shdr.sh_type); + Write32(f, shdr.sh_flags); + Write32(f, shdr.sh_addr); + Write32(f, shdr.sh_offset); + Write32(f, shdr.sh_size); + Write32(f, shdr.sh_link); + Write32(f, shdr.sh_info); + Write32(f, shdr.sh_addralign); + Write32(f, shdr.sh_entsize); +} + + void AppInfo::Load(vfsStream& f) { authid = Read64(f); diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index 53b34bee30..787fc00c7b 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -1,6 +1,5 @@ #pragma once -#include "Loader/SELF.h" #include "Loader/ELF64.h" #include "Loader/ELF32.h" #include "key_vault.h" @@ -142,7 +141,8 @@ struct MetadataSectionHeader void Show(); }; -struct SectionHash { +struct SectionHash +{ u8 sha1[20]; u8 padding[12]; u8 hmac_key[64]; @@ -183,6 +183,291 @@ struct SelfSection void Load(vfsStream& f); }; +struct Elf32_Ehdr +{ + u32 e_magic; + u8 e_class; + u8 e_data; + u8 e_curver; + u8 e_os_abi; + u64 e_abi_ver; + u16 e_type; + u16 e_machine; + u32 e_version; + u32 e_entry; + u32 e_phoff; + u32 e_shoff; + u32 e_flags; + u16 e_ehsize; + u16 e_phentsize; + u16 e_phnum; + u16 e_shentsize; + u16 e_shnum; + u16 e_shstrndx; + void Show() {} + bool IsLittleEndian() const + { + return e_data == 1; + } + + void Load(vfsStream& f) + { + e_magic = Read32(f); + e_class = Read8(f); + e_data = Read8(f); + e_curver = Read8(f); + e_os_abi = Read8(f); + + if (IsLittleEndian()) + { + e_abi_ver = Read64LE(f); + e_type = Read16LE(f); + e_machine = Read16LE(f); + e_version = Read32LE(f); + e_entry = Read32LE(f); + e_phoff = Read32LE(f); + e_shoff = Read32LE(f); + e_flags = Read32LE(f); + e_ehsize = Read16LE(f); + e_phentsize = Read16LE(f); + e_phnum = Read16LE(f); + e_shentsize = Read16LE(f); + e_shnum = Read16LE(f); + e_shstrndx = Read16LE(f); + } + else + { + e_abi_ver = Read64(f); + e_type = Read16(f); + e_machine = Read16(f); + e_version = Read32(f); + e_entry = Read32(f); + e_phoff = Read32(f); + e_shoff = Read32(f); + e_flags = Read32(f); + e_ehsize = Read16(f); + e_phentsize = Read16(f); + e_phnum = Read16(f); + e_shentsize = Read16(f); + e_shnum = Read16(f); + e_shstrndx = Read16(f); + } + } + bool CheckMagic() const { return e_magic == 0x7F454C46; } + u32 GetEntry() const { return e_entry; } +}; + +struct Elf32_Shdr +{ + u32 sh_name; + u32 sh_type; + u32 sh_flags; + u32 sh_addr; + u32 sh_offset; + u32 sh_size; + u32 sh_link; + u32 sh_info; + u32 sh_addralign; + u32 sh_entsize; + void Load(vfsStream& f) + { + sh_name = Read32(f); + sh_type = Read32(f); + sh_flags = Read32(f); + sh_addr = Read32(f); + sh_offset = Read32(f); + sh_size = Read32(f); + sh_link = Read32(f); + sh_info = Read32(f); + sh_addralign = Read32(f); + sh_entsize = Read32(f); + } + void LoadLE(vfsStream& f) + { + f.Read(this, sizeof(*this)); + } + void Show() {} +}; +struct Elf32_Phdr +{ + u32 p_type; + u32 p_offset; + u32 p_vaddr; + u32 p_paddr; + u32 p_filesz; + u32 p_memsz; + u32 p_flags; + u32 p_align; + void Load(vfsStream& f) + { + p_type = Read32(f); + p_offset = Read32(f); + p_vaddr = Read32(f); + p_paddr = Read32(f); + p_filesz = Read32(f); + p_memsz = Read32(f); + p_flags = Read32(f); + p_align = Read32(f); + } + void LoadLE(vfsStream& f) + { + f.Read(this, sizeof(*this)); + } + void Show() {} +}; + +struct Elf64_Ehdr +{ + u32 e_magic; + u8 e_class; + u8 e_data; + u8 e_curver; + u8 e_os_abi; + u64 e_abi_ver; + u16 e_type; + u16 e_machine; + u32 e_version; + u64 e_entry; + u64 e_phoff; + u64 e_shoff; + u32 e_flags; + u16 e_ehsize; + u16 e_phentsize; + u16 e_phnum; + u16 e_shentsize; + u16 e_shnum; + u16 e_shstrndx; + void Load(vfsStream& f) + { + e_magic = Read32(f); + e_class = Read8(f); + e_data = Read8(f); + e_curver = Read8(f); + e_os_abi = Read8(f); + e_abi_ver = Read64(f); + e_type = Read16(f); + e_machine = Read16(f); + e_version = Read32(f); + e_entry = Read64(f); + e_phoff = Read64(f); + e_shoff = Read64(f); + e_flags = Read32(f); + e_ehsize = Read16(f); + e_phentsize = Read16(f); + e_phnum = Read16(f); + e_shentsize = Read16(f); + e_shnum = Read16(f); + e_shstrndx = Read16(f); + } + void Show() {} + bool CheckMagic() const { return e_magic == 0x7F454C46; } + u64 GetEntry() const { return e_entry; } +}; + +struct Elf64_Shdr +{ + u32 sh_name; + u32 sh_type; + u64 sh_flags; + u64 sh_addr; + u64 sh_offset; + u64 sh_size; + u32 sh_link; + u32 sh_info; + u64 sh_addralign; + u64 sh_entsize; + void Load(vfsStream& f) + { + sh_name = Read32(f); + sh_type = Read32(f); + sh_flags = Read64(f); + sh_addr = Read64(f); + sh_offset = Read64(f); + sh_size = Read64(f); + sh_link = Read32(f); + sh_info = Read32(f); + sh_addralign = Read64(f); + sh_entsize = Read64(f); + } + void Show(){} +}; + +struct Elf64_Phdr +{ + u32 p_type; + u32 p_flags; + u64 p_offset; + u64 p_vaddr; + u64 p_paddr; + u64 p_filesz; + u64 p_memsz; + u64 p_align; + void Load(vfsStream& f) + { + p_type = Read32(f); + p_flags = Read32(f); + p_offset = Read64(f); + p_vaddr = Read64(f); + p_paddr = Read64(f); + p_filesz = Read64(f); + p_memsz = Read64(f); + p_align = Read64(f); + } + void Show(){} +}; + +struct SceHeader +{ + u32 se_magic; + u32 se_hver; + u16 se_flags; + u16 se_type; + u32 se_meta; + u64 se_hsize; + u64 se_esize; + void Load(vfsStream& f) + { + se_magic = Read32(f); + se_hver = Read32(f); + se_flags = Read16(f); + se_type = Read16(f); + se_meta = Read32(f); + se_hsize = Read64(f); + se_esize = Read64(f); + } + void Show(){} + bool CheckMagic() const { return se_magic == 0x53434500; } +}; + +struct SelfHeader +{ + u64 se_htype; + u64 se_appinfooff; + u64 se_elfoff; + u64 se_phdroff; + u64 se_shdroff; + u64 se_secinfoff; + u64 se_sceveroff; + u64 se_controloff; + u64 se_controlsize; + u64 pad; + void Load(vfsStream& f) + { + se_htype = Read64(f); + se_appinfooff = Read64(f); + se_elfoff = Read64(f); + se_phdroff = Read64(f); + se_shdroff = Read64(f); + se_secinfoff = Read64(f); + se_sceveroff = Read64(f); + se_controloff = Read64(f); + se_controlsize = Read64(f); + pad = Read64(f); + } + void Show(){} +}; + + class SELFDecrypter { // Main SELF file stream. diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 732c2ad7fa..8c57c78485 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -3,6 +3,7 @@ #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" +#include "Emu/CPU/CPUThreadManager.h" #include "ARMv7Thread.h" #include "ARMv7Decoder.h" @@ -100,3 +101,15 @@ void ARMv7Thread::DoStop() void ARMv7Thread::DoCode() { } + +arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +{ + thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); + + thread->SetName(name); + thread->SetEntry(entry); + thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize); + thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); + + argc = 0; +} \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index d80d5c9669..c657042e10 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -138,3 +138,48 @@ protected: virtual void DoCode(); }; +class arm7_thread : cpu_thread +{ + static const u32 stack_align = 0x10; + vm::ptr argv; + u32 argc; + vm::ptr envp; + +public: + arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + + cpu_thread& args(std::initializer_list values) override + { + if (!values.size()) + return *this; + + assert(argc == 0); + + envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main)); + *envp = 0; + argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main)); + + for (auto &arg : values) + { + u32 arg_size = align(u32(arg.size() + 1), stack_align); + u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main); + + std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); + + argv[argc++] = arg_addr; + } + + return *this; + } + + cpu_thread& run() override + { + thread->Run(); + + static_cast(thread)->GPR[3] = argc; + static_cast(thread)->GPR[4] = argv.addr(); + static_cast(thread)->GPR[5] = envp.addr(); + + return *this; + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/CPU/CPUDecoder.h b/rpcs3/Emu/CPU/CPUDecoder.h index d1faeea13d..beb0027055 100644 --- a/rpcs3/Emu/CPU/CPUDecoder.h +++ b/rpcs3/Emu/CPU/CPUDecoder.h @@ -340,7 +340,7 @@ public: , m_args_count(source.m_args_count) , m_args(source.m_args_count ? new CodeFieldBase*[source.m_args_count] : nullptr) { - for(int i = 0; i < source.m_args_count; ++i) + for(uint i = 0; i < source.m_args_count; ++i) m_args[i] = source.m_args[i]; } diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 35d48dd990..d5b2a94eb1 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -256,3 +256,42 @@ protected: }; CPUThread* GetCurrentCPUThread(); + +class cpu_thread +{ +protected: + CPUThread* thread; + +public: + u32 get_entry() const + { + return thread->entry; + } + + virtual cpu_thread& args(std::initializer_list values) = 0; + + virtual cpu_thread& run() = 0; + + u64 join() + { + if (!joinable()) + throw "thread must be joinable for join"; + + thread->SetJoinable(false); + + while (thread->IsRunning()) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + return thread->GetExitStatus(); + } + + bool joinable() const + { + return thread->IsJoinable(); + } + + u32 get_id() const + { + thread->GetId(); + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPCDecoder.cpp b/rpcs3/Emu/Cell/PPCDecoder.cpp index 52e28b9e91..de2b55fdf9 100644 --- a/rpcs3/Emu/Cell/PPCDecoder.cpp +++ b/rpcs3/Emu/Cell/PPCDecoder.cpp @@ -8,4 +8,4 @@ u8 PPCDecoder::DecodeMemory(const u32 address) Decode(instr); return sizeof(u32); -} +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUInstrTable.h b/rpcs3/Emu/Cell/PPUInstrTable.h index 77f742d467..250311321e 100644 --- a/rpcs3/Emu/Cell/PPUInstrTable.h +++ b/rpcs3/Emu/Cell/PPUInstrTable.h @@ -5,628 +5,656 @@ namespace PPU_instr { - //This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask - static DoubleCodeField<21, 25, 26, 26, 5> mb; + namespace fields + { + //This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask + static DoubleCodeField<21, 25, 26, 26, 5> mb; - //This field is used in rotate instructions to specify the last 1 bit of a 64-bit mask - static DoubleCodeField<21, 25, 26, 26, 5> me; + //This field is used in rotate instructions to specify the last 1 bit of a 64-bit mask + static DoubleCodeField<21, 25, 26, 26, 5> me; - //This field is used to specify a shift amount - static DoubleCodeField<16, 20, 30, 30, 5> sh; + //This field is used to specify a shift amount + static DoubleCodeField<16, 20, 30, 30, 5> sh; - //This field is used to specify a special-purpose register for the mtspr and mfspr instructions - static CodeField<11, 20> SPR; + //This field is used to specify a special-purpose register for the mtspr and mfspr instructions + static CodeField<11, 20> SPR; - // - static CodeField<6, 10> VS(FIELD_R_VPR); + // + static CodeField<6, 10> VS(FIELD_R_VPR); - // - static CodeField<6, 10> VD(FIELD_R_VPR); + // + static CodeField<6, 10> VD(FIELD_R_VPR); - // - static CodeField<11, 15> VA(FIELD_R_VPR); + // + static CodeField<11, 15> VA(FIELD_R_VPR); - // - static CodeField<16, 20> VB(FIELD_R_VPR); + // + static CodeField<16, 20> VB(FIELD_R_VPR); - // - static CodeField<21, 25> VC(FIELD_R_VPR); + // + static CodeField<21, 25> VC(FIELD_R_VPR); - // - static CodeField<11, 15> VUIMM; + // + static CodeField<11, 15> VUIMM; - // - static CodeFieldSigned<11, 15> VSIMM; + // + static CodeFieldSigned<11, 15> VSIMM; - // - static CodeField<22, 25> VSH; + // + static CodeField<22, 25> VSH; - //This field is used to specify a GPR to be used as a destination - static CodeField<6, 10> RD(FIELD_R_GPR); + //This field is used to specify a GPR to be used as a destination + static CodeField<6, 10> RD(FIELD_R_GPR); - //This field is used to specify a GPR to be used as a source - static CodeField<6, 10> RS(FIELD_R_GPR); + //This field is used to specify a GPR to be used as a source + static CodeField<6, 10> RS(FIELD_R_GPR); - //This field is used to specify a GPR to be used as a source or destination - static CodeField<11, 15> RA(FIELD_R_GPR); + //This field is used to specify a GPR to be used as a source or destination + static CodeField<11, 15> RA(FIELD_R_GPR); - //This field is used to specify a GPR to be used as a source - static CodeField<16, 20> RB(FIELD_R_GPR); + //This field is used to specify a GPR to be used as a source + static CodeField<16, 20> RB(FIELD_R_GPR); - //This field is used to specify the number of bytes to move in an immediate string load or store - static CodeField<16, 20> NB; + //This field is used to specify the number of bytes to move in an immediate string load or store + static CodeField<16, 20> NB; - //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a destination - static CodeField<6, 8> CRFD(FIELD_R_CR); + //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a destination + static CodeField<6, 8> CRFD(FIELD_R_CR); - //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a source - static CodeField<11, 13> CRFS(FIELD_R_CR); + //This field is used to specify one of the CR fields, or one of the FPSCR fields, as a source + static CodeField<11, 13> CRFS(FIELD_R_CR); - //This field is used to specify a bit in the CR to be used as a source - static CodeField<11, 15> CRBA(FIELD_R_CR); + //This field is used to specify a bit in the CR to be used as a source + static CodeField<11, 15> CRBA(FIELD_R_CR); - //This field is used to specify a bit in the CR to be used as a source - static CodeField<16, 20> CRBB(FIELD_R_CR); + //This field is used to specify a bit in the CR to be used as a source + static CodeField<16, 20> CRBB(FIELD_R_CR); - //This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction - static CodeField<6, 10> CRBD(FIELD_R_CR); + //This field is used to specify a bit in the CR, or in the FPSCR, as the destination of the result of an instruction + static CodeField<6, 10> CRBD(FIELD_R_CR); - //This field is used to specify options for the branch conditional instructions - static CodeField<6, 10> BO; + //This field is used to specify options for the branch conditional instructions + static CodeField<6, 10> BO; - //This field is used to specify a bit in the CR to be used as the condition of a branch conditional instruction - static CodeField<11, 15> BI; + //This field is used to specify a bit in the CR to be used as the condition of a branch conditional instruction + static CodeField<11, 15> BI; - //Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the - //right with '00' and sign-extended to 64 bits. - static CodeFieldSigned<16, 31> BD(FIELD_BRANCH); + //Immediate field specifying a 14-bit signed two's complement branch displacement that is concatenated on the + //right with '00' and sign-extended to 64 bits. + static CodeFieldSigned<16, 31> BD(FIELD_BRANCH); - // - static CodeField<19, 20> BH; + // + static CodeField<19, 20> BH; - // - static CodeField<11, 13> BFA; - - //Field used by the optional data stream variant of the dcbt instruction. - static CodeField<9, 10> TH; + // + static CodeField<11, 13> BFA; - //This field is used to specify the conditions on which to trap - static CodeField<6, 10> TO; + //Field used by the optional data stream variant of the dcbt instruction. + static CodeField<9, 10> TH; - // - static CodeField<21, 25> MB; + //This field is used to specify the conditions on which to trap + static CodeField<6, 10> TO; - // - static CodeField<26, 30> ME; + // + static CodeField<21, 25> MB; - //This field is used to specify a shift amount - static CodeField<16, 20> SH; + // + static CodeField<26, 30> ME; - /* - Absolute address bit. - 0 The immediate field represents an address relative to the current instruction address (CIA). (For more - information on the CIA, see Table 8-3.) The effective (logical) address of the branch is either the sum - of the LI field sign-extended to 64 bits and the address of the branch instruction or the sum of the BD - field sign-extended to 64 bits and the address of the branch instruction. - 1 The immediate field represents an absolute address. The effective address (EA) of the branch is the - LI field sign-extended to 64 bits or the BD field sign-extended to 64 bits. - */ - static CodeField<30> AA; + //This field is used to specify a shift amount + static CodeField<16, 20> SH; - static CodeFieldSignedOffset<6, 29, 2> LI(FIELD_BRANCH); - - // - static CodeFieldSignedOffset<6, 29, 2> LL(FIELD_BRANCH); - /* - Link bit. - 0 Does not update the link register (LR). - 1 Updates the LR. If the instruction is a branch instruction, the address of the instruction following the - branch instruction is placed into the LR. - */ - static CodeField<31> LK; - - //This field is used for extended arithmetic to enable setting OV and SO in the XER - static CodeField<21> OE; - - //Field used to specify whether an integer compare instruction is to compare 64-bit numbers or 32-bit numbers - static CodeField<10> L_10; - static CodeField<6> L_6; - static CodeField<9, 10> L_9_10; - static CodeField<11> L_11; - // - static CodeField<16, 19> I; - - // - static CodeField<16, 27> DQ; - - //This field is used to specify an FPR as the destination - static CodeField<6, 10> FRD; - - //This field is used to specify an FPR as a source - static CodeField<6, 10> FRS; - - // - static CodeField<7, 14> FM; - - //This field is used to specify an FPR as a source - static CodeField<11, 15> FRA(FIELD_R_FPR); - - //This field is used to specify an FPR as a source - static CodeField<16, 20> FRB(FIELD_R_FPR); - - //This field is used to specify an FPR as a source - static CodeField<21, 25> FRC(FIELD_R_FPR); - - //This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction. - static CodeField<12, 19> CRM; - - // - static CodeField<6, 31> SYS; - - //Immediate field specifying a 16-bit signed two's complement integer that is sign-extended to 64 bits - static CodeFieldSigned<16, 31> D; - - // - static CodeFieldSignedOffset<16, 29, 2> DS; - - //This immediate field is used to specify a 16-bit signed integer - static CodeFieldSigned<16, 31> simm16; - - //This immediate field is used to specify a 16-bit unsigned integer - static CodeField<16, 31> uimm16; - - /* - Record bit. - 0 Does not update the condition register (CR). - 1 Updates the CR to reflect the result of the operation. - For integer instructions, CR bits [0-2] are set to reflect the result as a signed quantity and CR bit [3] - receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit - string can be deduced from the EQ bit. For floating-point instructions, CR bits [4-7] are set to reflect - floating-point exception, floating-point enabled exception, floating-point invalid operation exception, - and floating-point overflow exception. - */ - static CodeField<31> RC; - - //Primary opcode field - static CodeField<0, 5> OPCD; - - static CodeField<26, 31> GD_04; //0x3f - static CodeField<21, 31> GD_04_0;//0x7ff - static CodeField<21, 30> GD_13; //0x3ff - static CodeField<27, 29> GD_1e; //0x7 - static CodeField<21, 30> GD_1f; //0x3ff - static CodeField<30, 31> GD_3a; //0x3 - static CodeField<26, 30> GD_3b; //0x1f - static CodeField<30, 31> GD_3e; //0x3 - static CodeField<26, 30> GD_3f;//0x1f - static CodeField<21, 30> GD_3f_0; //0x3ff - - static CodeField<9, 10> STRM; - - //static auto main_list = new_list(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD)); - static InstrList<1 << CodeField<0, 5>::size, ::PPUOpcodes> main_list_obj(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD)); - static auto main_list = &main_list_obj; - static auto g04_list = new_list(main_list, PPU_opcodes::G_04, GD_04); - static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_04_0)); - static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_13)); - static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1e)); - static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1f)); - static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3a)); - static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3b)); - static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3e)); - static auto g3f_list = new_list(main_list, PPU_opcodes::G_3f, GD_3f); - static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3f_0)); - - #define bind_instr(list, name, ...) \ - static const auto& name = make_instr(list, #name, &PPUOpcodes::name, ##__VA_ARGS__) - - bind_instr(main_list, TDI, TO, RA, simm16); - bind_instr(main_list, TWI, TO, RA, simm16); - bind_instr(main_list, MULLI, RD, RA, simm16); - bind_instr(main_list, SUBFIC, RD, RA, simm16); - bind_instr(main_list, CMPLI, CRFD, L_10, RA, uimm16); - bind_instr(main_list, CMPI, CRFD, L_10, RA, simm16); - bind_instr(main_list, ADDIC, RD, RA, simm16); - bind_instr(main_list, ADDIC_, RD, RA, simm16); - bind_instr(main_list, ADDI, RD, RA, simm16); - bind_instr(main_list, ADDIS, RD, RA, simm16); - bind_instr(main_list, BC, BO, BI, BD, AA, LK); - bind_instr(main_list, SC, SYS); - bind_instr(main_list, B, LI, AA, LK); - bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC); - bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC); - bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC); - bind_instr(main_list, ORI, RA, RS, uimm16); - bind_instr(main_list, ORIS, RA, RS, uimm16); - bind_instr(main_list, XORI, RA, RS, uimm16); - bind_instr(main_list, XORIS, RA, RS, uimm16); - bind_instr(main_list, ANDI_, RA, RS, uimm16); - bind_instr(main_list, ANDIS_, RA, RS, uimm16); - bind_instr(main_list, LWZ, RD, RA, D); - bind_instr(main_list, LWZU, RD, RA, D); - bind_instr(main_list, LBZ, RD, RA, D); - bind_instr(main_list, LBZU, RD, RA, D); - bind_instr(main_list, STW, RS, RA, D); - bind_instr(main_list, STWU, RS, RA, D); - bind_instr(main_list, STB, RS, RA, D); - bind_instr(main_list, STBU, RS, RA, D); - bind_instr(main_list, LHZ, RD, RA, D); - bind_instr(main_list, LHZU, RD, RA, D); - bind_instr(main_list, LHA, RD, RA, D); - bind_instr(main_list, LHAU, RD, RA, D); - bind_instr(main_list, STH, RS, RA, D); - bind_instr(main_list, STHU, RS, RA, D); - bind_instr(main_list, LMW, RD, RA, D); - bind_instr(main_list, STMW, RS, RA, D); - bind_instr(main_list, LFS, FRD, RA, D); - bind_instr(main_list, LFSU, FRD, RA, D); - bind_instr(main_list, LFD, FRD, RA, D); - bind_instr(main_list, LFDU, FRD, RA, D); - bind_instr(main_list, STFS, FRS, RA, D); - bind_instr(main_list, STFSU, FRS, RA, D); - bind_instr(main_list, STFD, FRS, RA, D); - bind_instr(main_list, STFDU, FRS, RA, D); - - bind_instr(g04_list, VMADDFP, VD, VA, VC, VB); - bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC); - bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC); - bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMMBM, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMSHM, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMSHS, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC); - bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC); - bind_instr(g04_list, VNMSUBFP, VD, VA, VC, VB); - bind_instr(g04_list, VPERM, VD, VA, VB, VC); - bind_instr(g04_list, VSEL, VD, VA, VB, VC); - bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH); - - bind_instr(g04_0_list, MFVSCR, VD); - bind_instr(g04_0_list, MTVSCR, VB); - bind_instr(g04_0_list, VADDCUW, VD, VA, VB); - bind_instr(g04_0_list, VADDFP, VD, VA, VB); - bind_instr(g04_0_list, VADDSBS, VD, VA, VB); - bind_instr(g04_0_list, VADDSHS, VD, VA, VB); - bind_instr(g04_0_list, VADDSWS, VD, VA, VB); - bind_instr(g04_0_list, VADDUBM, VD, VA, VB); - bind_instr(g04_0_list, VADDUBS, VD, VA, VB); - bind_instr(g04_0_list, VADDUHM, VD, VA, VB); - bind_instr(g04_0_list, VADDUHS, VD, VA, VB); - bind_instr(g04_0_list, VADDUWM, VD, VA, VB); - bind_instr(g04_0_list, VADDUWS, VD, VA, VB); - bind_instr(g04_0_list, VAND, VD, VA, VB); - bind_instr(g04_0_list, VANDC, VD, VA, VB); - bind_instr(g04_0_list, VAVGSB, VD, VA, VB); - bind_instr(g04_0_list, VAVGSH, VD, VA, VB); - bind_instr(g04_0_list, VAVGSW, VD, VA, VB); - bind_instr(g04_0_list, VAVGUB, VD, VA, VB); - bind_instr(g04_0_list, VAVGUH, VD, VA, VB); - bind_instr(g04_0_list, VAVGUW, VD, VA, VB); - bind_instr(g04_0_list, VCFSX, VD, VUIMM, VB); - bind_instr(g04_0_list, VCFUX, VD, VUIMM, VB); - bind_instr(g04_0_list, VCMPBFP, VD, VA, VB); - bind_instr(g04_0_list, VCMPBFP_, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQFP, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQFP_, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUB, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUB_, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUH, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUH_, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUW, VD, VA, VB); - bind_instr(g04_0_list, VCMPEQUW_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGEFP, VD, VA, VB); - bind_instr(g04_0_list, VCMPGEFP_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTFP, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTFP_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSB, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSB_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSH, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSH_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSW, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTSW_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUB, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUB_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUH, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUH_, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUW, VD, VA, VB); - bind_instr(g04_0_list, VCMPGTUW_, VD, VA, VB); - bind_instr(g04_0_list, VCTSXS, VD, VUIMM, VB); - bind_instr(g04_0_list, VCTUXS, VD, VUIMM, VB); - bind_instr(g04_0_list, VEXPTEFP, VD, VB); - bind_instr(g04_0_list, VLOGEFP, VD, VB); - bind_instr(g04_0_list, VMAXFP, VD, VA, VB); - bind_instr(g04_0_list, VMAXSB, VD, VA, VB); - bind_instr(g04_0_list, VMAXSH, VD, VA, VB); - bind_instr(g04_0_list, VMAXSW, VD, VA, VB); - bind_instr(g04_0_list, VMAXUB, VD, VA, VB); - bind_instr(g04_0_list, VMAXUH, VD, VA, VB); - bind_instr(g04_0_list, VMAXUW, VD, VA, VB); - bind_instr(g04_0_list, VMINFP, VD, VA, VB); - bind_instr(g04_0_list, VMINSB, VD, VA, VB); - bind_instr(g04_0_list, VMINSH, VD, VA, VB); - bind_instr(g04_0_list, VMINSW, VD, VA, VB); - bind_instr(g04_0_list, VMINUB, VD, VA, VB); - bind_instr(g04_0_list, VMINUH, VD, VA, VB); - bind_instr(g04_0_list, VMINUW, VD, VA, VB); - bind_instr(g04_0_list, VMRGHB, VD, VA, VB); - bind_instr(g04_0_list, VMRGHH, VD, VA, VB); - bind_instr(g04_0_list, VMRGHW, VD, VA, VB); - bind_instr(g04_0_list, VMRGLB, VD, VA, VB); - bind_instr(g04_0_list, VMRGLH, VD, VA, VB); - bind_instr(g04_0_list, VMRGLW, VD, VA, VB); - bind_instr(g04_0_list, VMULESB, VD, VA, VB); - bind_instr(g04_0_list, VMULESH, VD, VA, VB); - bind_instr(g04_0_list, VMULEUB, VD, VA, VB); - bind_instr(g04_0_list, VMULEUH, VD, VA, VB); - bind_instr(g04_0_list, VMULOSB, VD, VA, VB); - bind_instr(g04_0_list, VMULOSH, VD, VA, VB); - bind_instr(g04_0_list, VMULOUB, VD, VA, VB); - bind_instr(g04_0_list, VMULOUH, VD, VA, VB); - bind_instr(g04_0_list, VNOR, VD, VA, VB); - bind_instr(g04_0_list, VOR, VD, VA, VB); - bind_instr(g04_0_list, VPKPX, VD, VA, VB); - bind_instr(g04_0_list, VPKSHSS, VD, VA, VB); - bind_instr(g04_0_list, VPKSHUS, VD, VA, VB); - bind_instr(g04_0_list, VPKSWSS, VD, VA, VB); - bind_instr(g04_0_list, VPKSWUS, VD, VA, VB); - bind_instr(g04_0_list, VPKUHUM, VD, VA, VB); - bind_instr(g04_0_list, VPKUHUS, VD, VA, VB); - bind_instr(g04_0_list, VPKUWUM, VD, VA, VB); - bind_instr(g04_0_list, VPKUWUS, VD, VA, VB); - bind_instr(g04_0_list, VREFP, VD, VB); - bind_instr(g04_0_list, VRFIM, VD, VB); - bind_instr(g04_0_list, VRFIN, VD, VB); - bind_instr(g04_0_list, VRFIP, VD, VB); - bind_instr(g04_0_list, VRFIZ, VD, VB); - bind_instr(g04_0_list, VRLB, VD, VA, VB); - bind_instr(g04_0_list, VRLH, VD, VA, VB); - bind_instr(g04_0_list, VRLW, VD, VA, VB); - bind_instr(g04_0_list, VRSQRTEFP, VD, VB); - bind_instr(g04_0_list, VSL, VD, VA, VB); - bind_instr(g04_0_list, VSLB, VD, VA, VB); - bind_instr(g04_0_list, VSLH, VD, VA, VB); - bind_instr(g04_0_list, VSLO, VD, VA, VB); - bind_instr(g04_0_list, VSLW, VD, VA, VB); - bind_instr(g04_0_list, VSPLTB, VD, VUIMM, VB); - bind_instr(g04_0_list, VSPLTH, VD, VUIMM, VB); - bind_instr(g04_0_list, VSPLTISB, VD, VSIMM); - bind_instr(g04_0_list, VSPLTISH, VD, VSIMM); - bind_instr(g04_0_list, VSPLTISW, VD, VSIMM); - bind_instr(g04_0_list, VSPLTW, VD, VUIMM, VB); - bind_instr(g04_0_list, VSR, VD, VA, VB); - bind_instr(g04_0_list, VSRAB, VD, VA, VB); - bind_instr(g04_0_list, VSRAH, VD, VA, VB); - bind_instr(g04_0_list, VSRAW, VD, VA, VB); - bind_instr(g04_0_list, VSRB, VD, VA, VB); - bind_instr(g04_0_list, VSRH, VD, VA, VB); - bind_instr(g04_0_list, VSRO, VD, VA, VB); - bind_instr(g04_0_list, VSRW, VD, VA, VB); - bind_instr(g04_0_list, VSUBCUW, VD, VA, VB); - bind_instr(g04_0_list, VSUBFP, VD, VA, VB); - bind_instr(g04_0_list, VSUBSBS, VD, VA, VB); - bind_instr(g04_0_list, VSUBSHS, VD, VA, VB); - bind_instr(g04_0_list, VSUBSWS, VD, VA, VB); - bind_instr(g04_0_list, VSUBUBM, VD, VA, VB); - bind_instr(g04_0_list, VSUBUBS, VD, VA, VB); - bind_instr(g04_0_list, VSUBUHM, VD, VA, VB); - bind_instr(g04_0_list, VSUBUHS, VD, VA, VB); - bind_instr(g04_0_list, VSUBUWM, VD, VA, VB); - bind_instr(g04_0_list, VSUBUWS, VD, VA, VB); - bind_instr(g04_0_list, VSUMSWS, VD, VA, VB); - bind_instr(g04_0_list, VSUM2SWS, VD, VA, VB); - bind_instr(g04_0_list, VSUM4SBS, VD, VA, VB); - bind_instr(g04_0_list, VSUM4SHS, VD, VA, VB); - bind_instr(g04_0_list, VSUM4UBS, VD, VA, VB); - bind_instr(g04_0_list, VUPKHPX, VD, VB); - bind_instr(g04_0_list, VUPKHSB, VD, VB); - bind_instr(g04_0_list, VUPKHSH, VD, VB); - bind_instr(g04_0_list, VUPKLPX, VD, VB); - bind_instr(g04_0_list, VUPKLSB, VD, VB); - bind_instr(g04_0_list, VUPKLSH, VD, VB); - bind_instr(g04_0_list, VXOR, VD, VA, VB); - - bind_instr(g13_list, MCRF, CRFD, CRFS); - bind_instr(g13_list, BCLR, BO, BI, BH, LK); - bind_instr(g13_list, CRNOR, CRBD, CRBA, CRBB); - bind_instr(g13_list, CRANDC, CRBD, CRBA, CRBB); - bind_instr(g13_list, ISYNC); - bind_instr(g13_list, CRXOR, CRBD, CRBA, CRBB); - bind_instr(g13_list, CRNAND, CRBD, CRBA, CRBB); - bind_instr(g13_list, CRAND, CRBD, CRBA, CRBB); - bind_instr(g13_list, CREQV, CRBD, CRBA, CRBB); - bind_instr(g13_list, CRORC, CRBD, CRBA, CRBB); - bind_instr(g13_list, CROR, CRBD, CRBA, CRBB); - bind_instr(g13_list, BCCTR, BO, BI, BH, LK); - - bind_instr(g1e_list, RLDICL, RA, RS, sh, mb, RC); - bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC); - bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC); - bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC); - bind_instr(g1e_list, RLDC_LR, RA, RS, RB, mb, AA, RC); - - /*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB); - /*0x004*/bind_instr(g1f_list, TW, TO, RA, RB); - /*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB); - /*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB); - /*0x008*/bind_instr(g1f_list, SUBFC, RD, RA, RB, OE, RC); - /*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC); - /*0x00a*/bind_instr(g1f_list, ADDC, RD, RA, RB, OE, RC); - /*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC); - /*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM); - /*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB); - /*0x015*/bind_instr(g1f_list, LDX, RD, RA, RB); - /*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB); - /*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC); - /*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC); - /*0x01b*/bind_instr(g1f_list, SLD, RA, RS, RB, RC); - /*0x01c*/bind_instr(g1f_list, AND, RA, RS, RB, RC); - /*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB); - /*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB); - /*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB); - /*0x028*/bind_instr(g1f_list, SUBF, RD, RA, RB, OE, RC); - /*0x035*/bind_instr(g1f_list, LDUX, RD, RA, RB); - /*0x036*/bind_instr(g1f_list, DCBST, RA, RB); - /*0x037*/bind_instr(g1f_list, LWZUX, RD, RA, RB); - /*0x03a*/bind_instr(g1f_list, CNTLZD, RA, RS, RC); - /*0x03c*/bind_instr(g1f_list, ANDC, RA, RS, RB, RC); - /*0x03c*/bind_instr(g1f_list, TD, TO, RA, RB); - /*0x047*/bind_instr(g1f_list, LVEWX, VD, RA, RB); - /*0x049*/bind_instr(g1f_list, MULHD, RD, RA, RB, RC); - /*0x04b*/bind_instr(g1f_list, MULHW, RD, RA, RB, RC); - /*0x054*/bind_instr(g1f_list, LDARX, RD, RA, RB); - /*0x056*/bind_instr(g1f_list, DCBF, RA, RB); - /*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB); - /*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB); - /*0x068*/bind_instr(g1f_list, NEG, RD, RA, OE, RC); - /*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB); - /*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC); - /*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB); - /*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC); - /*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC); - /*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS); - /*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB); - /*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB); - /*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB); - /*0x0a7*/bind_instr(g1f_list, STVEHX, VS, RA, RB); - /*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB); - /*0x0b7*/bind_instr(g1f_list, STWUX, RS, RA, RB); - /*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB); - /*0x0c8*/bind_instr(g1f_list, SUBFZE, RD, RA, OE, RC); - /*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC); - /*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB); - /*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB); - /*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB); - /*0x0e8*/bind_instr(g1f_list, SUBFME, RD, RA, OE, RC); - /*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC); - /*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC); - /*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC); - /*0x0f6*/bind_instr(g1f_list, DCBTST, RA, RB, TH); - /*0x0f7*/bind_instr(g1f_list, STBUX, RS, RA, RB); - /*0x10a*/bind_instr(g1f_list, ADD, RD, RA, RB, OE, RC); - /*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH); - /*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB); - /*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC); - /*0x136*/bind_instr(g1f_list, ECIWX, RD, RA, RB); - /*0x137*/bind_instr(g1f_list, LHZUX, RD, RA, RB); - /*0x13c*/bind_instr(g1f_list, XOR, RA, RS, RB, RC); - /*0x153*/bind_instr(g1f_list, MFSPR, RD, SPR); - /*0x155*/bind_instr(g1f_list, LWAX, RD, RA, RB); - /*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6); - /*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB); - /*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB); - /*0x173*/bind_instr(g1f_list, MFTB, RD, SPR); - /*0x175*/bind_instr(g1f_list, LWAUX, RD, RA, RB); - /*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6); - /*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB); - /*0x197*/bind_instr(g1f_list, STHX, RS, RA, RB); - /*0x19c*/bind_instr(g1f_list, ORC, RA, RS, RB, RC); - /*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB); - /*0x1b7*/bind_instr(g1f_list, STHUX, RS, RA, RB); - /*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC); - /*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC); - /*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC); - /*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS); - /*0x1d6*/bind_instr(g1f_list, DCBI, RA, RB); - /*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC); - /*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB); - /*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC); - /*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC); - /*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB); - /*0x214*/bind_instr(g1f_list, LDBRX, RD, RA, RB); - /*0x215*/bind_instr(g1f_list, LSWX, RD, RA, RB); - /*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB); - /*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB); - /*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC); - /*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC); - /*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB); - /*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB); - /*0x255*/bind_instr(g1f_list, LSWI, RD, RA, NB); - /*0x256*/bind_instr(g1f_list, SYNC, L_9_10); - /*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB); - /*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB); - /*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB); - /*0x296*/bind_instr(g1f_list, STSWX, RS, RA, RB); - /*0x296*/bind_instr(g1f_list, STWBRX, RS, RA, RB); - /*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB); - /*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB); - /*0x2b7*/bind_instr(g1f_list, STFSUX, FRS, RA, RB); - /*0x2d5*/bind_instr(g1f_list, STSWI, RS, RA, NB); - /*0x2d7*/bind_instr(g1f_list, STFDX, FRS, RA, RB); - /*0x2d7*/bind_instr(g1f_list, STFDUX, FRS, RA, RB); - /*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB); - /*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB); - /*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC); - /*0x31a*/bind_instr(g1f_list, SRAD, RA, RS, RB, RC); - /*0x327*/bind_instr(g1f_list, LVRXL, VD, RA, RB); - /*0x336*/bind_instr(g1f_list, DSS, STRM, L_6); - /*0x338*/bind_instr(g1f_list, SRAWI, RA, RS, SH, RC); - /*0x33a*/bind_instr(g1f_list, SRADI1, RA, RS, sh, RC); - /*0x33b*/bind_instr(g1f_list, SRADI2, RA, RS, sh, RC); - /*0x356*/bind_instr(g1f_list, EIEIO); - /*0x387*/bind_instr(g1f_list, STVLXL, VS, RA, RB); - /*0x396*/bind_instr(g1f_list, STHBRX, RS, RA, RB); - /*0x39a*/bind_instr(g1f_list, EXTSH, RA, RS, RC); - /*0x387*/bind_instr(g1f_list, STVRXL, VS, RA, RB); - /*0x3ba*/bind_instr(g1f_list, EXTSB, RA, RS, RC); - /*0x3d7*/bind_instr(g1f_list, STFIWX, FRS, RA, RB); - /*0x3da*/bind_instr(g1f_list, EXTSW, RA, RS, RC); - /*0x3d6*/bind_instr(g1f_list, ICBI, RA, RB); - /*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB); - - bind_instr(g3a_list, LD, RD, RA, DS); - bind_instr(g3a_list, LDU, RD, RA, DS); - bind_instr(g3a_list, LWA, RD, RA, DS); - - bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC); - bind_instr(g3b_list, FSUBS, FRD, FRA, FRB, RC); - bind_instr(g3b_list, FADDS, FRD, FRA, FRB, RC); - bind_instr(g3b_list, FSQRTS, FRD, FRB, RC); - bind_instr(g3b_list, FRES, FRD, FRB, RC); - bind_instr(g3b_list, FMULS, FRD, FRA, FRC, RC); - bind_instr(g3b_list, FMADDS, FRD, FRA, FRC, FRB, RC); - bind_instr(g3b_list, FMSUBS, FRD, FRA, FRC, FRB, RC); - bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC); - bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC); - - bind_instr(g3e_list, STD, RS, RA, DS); - bind_instr(g3e_list, STDU, RS, RA, DS); - - bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC); - bind_instr(g3f_list, FMUL, FRD, FRA, FRC, RC); - bind_instr(g3f_list, FMSUB, FRD, FRA, FRC, FRB, RC); - bind_instr(g3f_list, FMADD, FRD, FRA, FRC, FRB, RC); - bind_instr(g3f_list, FNMSUB, FRD, FRA, FRC, FRB, RC); - bind_instr(g3f_list, FNMADD, FRD, FRA, FRC, FRB, RC); - - bind_instr(g3f_0_list, FDIV, FRD, FRA, FRB, RC); - bind_instr(g3f_0_list, FSUB, FRD, FRA, FRB, RC); - bind_instr(g3f_0_list, FADD, FRD, FRA, FRB, RC); - bind_instr(g3f_0_list, FSQRT, FRD, FRB, RC); - bind_instr(g3f_0_list, FRSQRTE, FRD, FRB, RC); - bind_instr(g3f_0_list, FCMPU, CRFD, FRA, FRB); - bind_instr(g3f_0_list, FRSP, FRD, FRB, RC); - bind_instr(g3f_0_list, FCTIW, FRD, FRB, RC); - bind_instr(g3f_0_list, FCTIWZ, FRD, FRB, RC); - bind_instr(g3f_0_list, FCMPO, CRFD, FRA, FRB); - bind_instr(g3f_0_list, FNEG, FRD, FRB, RC); - bind_instr(g3f_0_list, FMR, FRD, FRB, RC); - bind_instr(g3f_0_list, FNABS, FRD, FRB, RC); - bind_instr(g3f_0_list, FABS, FRD, FRB, RC); - bind_instr(g3f_0_list, FCFID, FRD, FRB, RC); - bind_instr(g3f_0_list, FCTID, FRD, FRB, RC); - bind_instr(g3f_0_list, FCTIDZ, FRD, FRB, RC); - - bind_instr(g3f_0_list, MTFSB1, CRBD, RC); - bind_instr(g3f_0_list, MCRFS, CRFD, CRFS); - bind_instr(g3f_0_list, MTFSB0, CRBD, RC); - bind_instr(g3f_0_list, MTFSFI, CRFD, I, RC); - bind_instr(g3f_0_list, MFFS, FRD, RC); - bind_instr(g3f_0_list, MTFSF, FM, FRB, RC); - - static auto LIS = std::bind(ADDIS, std::placeholders::_1, 0, std::placeholders::_2); - static auto NOP = std::bind(ORI, 0, 0, 0); - static auto BLR = std::bind(BCLR, 0x10 | 0x04, 0, 0, 0); + /* + Absolute address bit. + 0 The immediate field represents an address relative to the current instruction address (CIA). (For more + information on the CIA, see Table 8-3.) The effective (logical) address of the branch is either the sum + of the LI field sign-extended to 64 bits and the address of the branch instruction or the sum of the BD + field sign-extended to 64 bits and the address of the branch instruction. + 1 The immediate field represents an absolute address. The effective address (EA) of the branch is the + LI field sign-extended to 64 bits or the BD field sign-extended to 64 bits. + */ + static CodeField<30> AA; + static CodeFieldSignedOffset<6, 29, 2> LI(FIELD_BRANCH); + + // + static CodeFieldSignedOffset<6, 29, 2> LL(FIELD_BRANCH); + /* + Link bit. + 0 Does not update the link register (LR). + 1 Updates the LR. If the instruction is a branch instruction, the address of the instruction following the + branch instruction is placed into the LR. + */ + static CodeField<31> LK; + + //This field is used for extended arithmetic to enable setting OV and SO in the XER + static CodeField<21> OE; + + //Field used to specify whether an integer compare instruction is to compare 64-bit numbers or 32-bit numbers + static CodeField<10> L_10; + static CodeField<6> L_6; + static CodeField<9, 10> L_9_10; + static CodeField<11> L_11; + // + static CodeField<16, 19> I; + + // + static CodeField<16, 27> DQ; + + //This field is used to specify an FPR as the destination + static CodeField<6, 10> FRD; + + //This field is used to specify an FPR as a source + static CodeField<6, 10> FRS; + + // + static CodeField<7, 14> FM; + + //This field is used to specify an FPR as a source + static CodeField<11, 15> FRA(FIELD_R_FPR); + + //This field is used to specify an FPR as a source + static CodeField<16, 20> FRB(FIELD_R_FPR); + + //This field is used to specify an FPR as a source + static CodeField<21, 25> FRC(FIELD_R_FPR); + + //This field mask is used to identify the CR fields that are to be updated by the mtcrf instruction. + static CodeField<12, 19> CRM; + + // + static CodeField<6, 31> SYS; + + //Immediate field specifying a 16-bit signed two's complement integer that is sign-extended to 64 bits + static CodeFieldSigned<16, 31> D; + + // + static CodeFieldSignedOffset<16, 29, 2> DS; + + //This immediate field is used to specify a 16-bit signed integer + static CodeFieldSigned<16, 31> simm16; + + //This immediate field is used to specify a 16-bit unsigned integer + static CodeField<16, 31> uimm16; + + /* + Record bit. + 0 Does not update the condition register (CR). + 1 Updates the CR to reflect the result of the operation. + For integer instructions, CR bits [0-2] are set to reflect the result as a signed quantity and CR bit [3] + receives a copy of the summary overflow bit, XER[SO]. The result as an unsigned quantity or a bit + string can be deduced from the EQ bit. For floating-point instructions, CR bits [4-7] are set to reflect + floating-point exception, floating-point enabled exception, floating-point invalid operation exception, + and floating-point overflow exception. + */ + static CodeField<31> RC; + + //Primary opcode field + static CodeField<0, 5> OPCD; + + static CodeField<26, 31> GD_04; //0x3f + static CodeField<21, 31> GD_04_0;//0x7ff + static CodeField<21, 30> GD_13; //0x3ff + static CodeField<27, 29> GD_1e; //0x7 + static CodeField<21, 30> GD_1f; //0x3ff + static CodeField<30, 31> GD_3a; //0x3 + static CodeField<26, 30> GD_3b; //0x1f + static CodeField<30, 31> GD_3e; //0x3 + static CodeField<26, 30> GD_3f;//0x1f + static CodeField<21, 30> GD_3f_0; //0x3ff + + static CodeField<9, 10> STRM; + } + + namespace lists + { + using namespace fields; + + //static auto main_list = new_list(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD)); + static InstrList<1 << CodeField<0, 5>::size, ::PPUOpcodes> main_list_obj(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD)); + static auto main_list = &main_list_obj; + static auto g04_list = new_list(main_list, PPU_opcodes::G_04, GD_04); + static auto g04_0_list = new_list(g04_list, GD_04_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_04_0)); + static auto g13_list = new_list(main_list, PPU_opcodes::G_13, GD_13, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_13)); + static auto g1e_list = new_list(main_list, PPU_opcodes::G_1e, GD_1e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1e)); + static auto g1f_list = new_list(main_list, PPU_opcodes::G_1f, GD_1f, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_1f)); + static auto g3a_list = new_list(main_list, PPU_opcodes::G_3a, GD_3a, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3a)); + static auto g3b_list = new_list(main_list, PPU_opcodes::G_3b, GD_3b, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3b)); + static auto g3e_list = new_list(main_list, PPU_opcodes::G_3e, GD_3e, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3e)); + static auto g3f_list = new_list(main_list, PPU_opcodes::G_3f, GD_3f); + static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3f_0)); + +#define bind_instr(list, name, ...) \ + static const auto& name = make_instr(list, #name, &PPUOpcodes::name, ##__VA_ARGS__) + + bind_instr(main_list, TDI, TO, RA, simm16); + bind_instr(main_list, TWI, TO, RA, simm16); + bind_instr(main_list, MULLI, RD, RA, simm16); + bind_instr(main_list, SUBFIC, RD, RA, simm16); + bind_instr(main_list, CMPLI, CRFD, L_10, RA, uimm16); + bind_instr(main_list, CMPI, CRFD, L_10, RA, simm16); + bind_instr(main_list, ADDIC, RD, RA, simm16); + bind_instr(main_list, ADDIC_, RD, RA, simm16); + bind_instr(main_list, ADDI, RD, RA, simm16); + bind_instr(main_list, ADDIS, RD, RA, simm16); + bind_instr(main_list, BC, BO, BI, BD, AA, LK); + bind_instr(main_list, SC, SYS); + bind_instr(main_list, B, LI, AA, LK); + bind_instr(main_list, RLWIMI, RA, RS, SH, MB, ME, RC); + bind_instr(main_list, RLWINM, RA, RS, SH, MB, ME, RC); + bind_instr(main_list, RLWNM, RA, RS, RB, MB, ME, RC); + bind_instr(main_list, ORI, RA, RS, uimm16); + bind_instr(main_list, ORIS, RA, RS, uimm16); + bind_instr(main_list, XORI, RA, RS, uimm16); + bind_instr(main_list, XORIS, RA, RS, uimm16); + bind_instr(main_list, ANDI_, RA, RS, uimm16); + bind_instr(main_list, ANDIS_, RA, RS, uimm16); + bind_instr(main_list, LWZ, RD, RA, D); + bind_instr(main_list, LWZU, RD, RA, D); + bind_instr(main_list, LBZ, RD, RA, D); + bind_instr(main_list, LBZU, RD, RA, D); + bind_instr(main_list, STW, RS, RA, D); + bind_instr(main_list, STWU, RS, RA, D); + bind_instr(main_list, STB, RS, RA, D); + bind_instr(main_list, STBU, RS, RA, D); + bind_instr(main_list, LHZ, RD, RA, D); + bind_instr(main_list, LHZU, RD, RA, D); + bind_instr(main_list, LHA, RD, RA, D); + bind_instr(main_list, LHAU, RD, RA, D); + bind_instr(main_list, STH, RS, RA, D); + bind_instr(main_list, STHU, RS, RA, D); + bind_instr(main_list, LMW, RD, RA, D); + bind_instr(main_list, STMW, RS, RA, D); + bind_instr(main_list, LFS, FRD, RA, D); + bind_instr(main_list, LFSU, FRD, RA, D); + bind_instr(main_list, LFD, FRD, RA, D); + bind_instr(main_list, LFDU, FRD, RA, D); + bind_instr(main_list, STFS, FRS, RA, D); + bind_instr(main_list, STFSU, FRS, RA, D); + bind_instr(main_list, STFD, FRS, RA, D); + bind_instr(main_list, STFDU, FRS, RA, D); + + bind_instr(g04_list, VMADDFP, VD, VA, VC, VB); + bind_instr(g04_list, VMHADDSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMHRADDSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMLADDUHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMMBM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMSHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMSHS, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUBM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUHM, VD, VA, VB, VC); + bind_instr(g04_list, VMSUMUHS, VD, VA, VB, VC); + bind_instr(g04_list, VNMSUBFP, VD, VA, VC, VB); + bind_instr(g04_list, VPERM, VD, VA, VB, VC); + bind_instr(g04_list, VSEL, VD, VA, VB, VC); + bind_instr(g04_list, VSLDOI, VD, VA, VB, VSH); + + bind_instr(g04_0_list, MFVSCR, VD); + bind_instr(g04_0_list, MTVSCR, VB); + bind_instr(g04_0_list, VADDCUW, VD, VA, VB); + bind_instr(g04_0_list, VADDFP, VD, VA, VB); + bind_instr(g04_0_list, VADDSBS, VD, VA, VB); + bind_instr(g04_0_list, VADDSHS, VD, VA, VB); + bind_instr(g04_0_list, VADDSWS, VD, VA, VB); + bind_instr(g04_0_list, VADDUBM, VD, VA, VB); + bind_instr(g04_0_list, VADDUBS, VD, VA, VB); + bind_instr(g04_0_list, VADDUHM, VD, VA, VB); + bind_instr(g04_0_list, VADDUHS, VD, VA, VB); + bind_instr(g04_0_list, VADDUWM, VD, VA, VB); + bind_instr(g04_0_list, VADDUWS, VD, VA, VB); + bind_instr(g04_0_list, VAND, VD, VA, VB); + bind_instr(g04_0_list, VANDC, VD, VA, VB); + bind_instr(g04_0_list, VAVGSB, VD, VA, VB); + bind_instr(g04_0_list, VAVGSH, VD, VA, VB); + bind_instr(g04_0_list, VAVGSW, VD, VA, VB); + bind_instr(g04_0_list, VAVGUB, VD, VA, VB); + bind_instr(g04_0_list, VAVGUH, VD, VA, VB); + bind_instr(g04_0_list, VAVGUW, VD, VA, VB); + bind_instr(g04_0_list, VCFSX, VD, VUIMM, VB); + bind_instr(g04_0_list, VCFUX, VD, VUIMM, VB); + bind_instr(g04_0_list, VCMPBFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPBFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUB, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUH, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUW, VD, VA, VB); + bind_instr(g04_0_list, VCMPEQUW_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGEFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPGEFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTFP, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTFP_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSB, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSH, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSW, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTSW_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUB, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUB_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUH, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUH_, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUW, VD, VA, VB); + bind_instr(g04_0_list, VCMPGTUW_, VD, VA, VB); + bind_instr(g04_0_list, VCTSXS, VD, VUIMM, VB); + bind_instr(g04_0_list, VCTUXS, VD, VUIMM, VB); + bind_instr(g04_0_list, VEXPTEFP, VD, VB); + bind_instr(g04_0_list, VLOGEFP, VD, VB); + bind_instr(g04_0_list, VMAXFP, VD, VA, VB); + bind_instr(g04_0_list, VMAXSB, VD, VA, VB); + bind_instr(g04_0_list, VMAXSH, VD, VA, VB); + bind_instr(g04_0_list, VMAXSW, VD, VA, VB); + bind_instr(g04_0_list, VMAXUB, VD, VA, VB); + bind_instr(g04_0_list, VMAXUH, VD, VA, VB); + bind_instr(g04_0_list, VMAXUW, VD, VA, VB); + bind_instr(g04_0_list, VMINFP, VD, VA, VB); + bind_instr(g04_0_list, VMINSB, VD, VA, VB); + bind_instr(g04_0_list, VMINSH, VD, VA, VB); + bind_instr(g04_0_list, VMINSW, VD, VA, VB); + bind_instr(g04_0_list, VMINUB, VD, VA, VB); + bind_instr(g04_0_list, VMINUH, VD, VA, VB); + bind_instr(g04_0_list, VMINUW, VD, VA, VB); + bind_instr(g04_0_list, VMRGHB, VD, VA, VB); + bind_instr(g04_0_list, VMRGHH, VD, VA, VB); + bind_instr(g04_0_list, VMRGHW, VD, VA, VB); + bind_instr(g04_0_list, VMRGLB, VD, VA, VB); + bind_instr(g04_0_list, VMRGLH, VD, VA, VB); + bind_instr(g04_0_list, VMRGLW, VD, VA, VB); + bind_instr(g04_0_list, VMULESB, VD, VA, VB); + bind_instr(g04_0_list, VMULESH, VD, VA, VB); + bind_instr(g04_0_list, VMULEUB, VD, VA, VB); + bind_instr(g04_0_list, VMULEUH, VD, VA, VB); + bind_instr(g04_0_list, VMULOSB, VD, VA, VB); + bind_instr(g04_0_list, VMULOSH, VD, VA, VB); + bind_instr(g04_0_list, VMULOUB, VD, VA, VB); + bind_instr(g04_0_list, VMULOUH, VD, VA, VB); + bind_instr(g04_0_list, VNOR, VD, VA, VB); + bind_instr(g04_0_list, VOR, VD, VA, VB); + bind_instr(g04_0_list, VPKPX, VD, VA, VB); + bind_instr(g04_0_list, VPKSHSS, VD, VA, VB); + bind_instr(g04_0_list, VPKSHUS, VD, VA, VB); + bind_instr(g04_0_list, VPKSWSS, VD, VA, VB); + bind_instr(g04_0_list, VPKSWUS, VD, VA, VB); + bind_instr(g04_0_list, VPKUHUM, VD, VA, VB); + bind_instr(g04_0_list, VPKUHUS, VD, VA, VB); + bind_instr(g04_0_list, VPKUWUM, VD, VA, VB); + bind_instr(g04_0_list, VPKUWUS, VD, VA, VB); + bind_instr(g04_0_list, VREFP, VD, VB); + bind_instr(g04_0_list, VRFIM, VD, VB); + bind_instr(g04_0_list, VRFIN, VD, VB); + bind_instr(g04_0_list, VRFIP, VD, VB); + bind_instr(g04_0_list, VRFIZ, VD, VB); + bind_instr(g04_0_list, VRLB, VD, VA, VB); + bind_instr(g04_0_list, VRLH, VD, VA, VB); + bind_instr(g04_0_list, VRLW, VD, VA, VB); + bind_instr(g04_0_list, VRSQRTEFP, VD, VB); + bind_instr(g04_0_list, VSL, VD, VA, VB); + bind_instr(g04_0_list, VSLB, VD, VA, VB); + bind_instr(g04_0_list, VSLH, VD, VA, VB); + bind_instr(g04_0_list, VSLO, VD, VA, VB); + bind_instr(g04_0_list, VSLW, VD, VA, VB); + bind_instr(g04_0_list, VSPLTB, VD, VUIMM, VB); + bind_instr(g04_0_list, VSPLTH, VD, VUIMM, VB); + bind_instr(g04_0_list, VSPLTISB, VD, VSIMM); + bind_instr(g04_0_list, VSPLTISH, VD, VSIMM); + bind_instr(g04_0_list, VSPLTISW, VD, VSIMM); + bind_instr(g04_0_list, VSPLTW, VD, VUIMM, VB); + bind_instr(g04_0_list, VSR, VD, VA, VB); + bind_instr(g04_0_list, VSRAB, VD, VA, VB); + bind_instr(g04_0_list, VSRAH, VD, VA, VB); + bind_instr(g04_0_list, VSRAW, VD, VA, VB); + bind_instr(g04_0_list, VSRB, VD, VA, VB); + bind_instr(g04_0_list, VSRH, VD, VA, VB); + bind_instr(g04_0_list, VSRO, VD, VA, VB); + bind_instr(g04_0_list, VSRW, VD, VA, VB); + bind_instr(g04_0_list, VSUBCUW, VD, VA, VB); + bind_instr(g04_0_list, VSUBFP, VD, VA, VB); + bind_instr(g04_0_list, VSUBSBS, VD, VA, VB); + bind_instr(g04_0_list, VSUBSHS, VD, VA, VB); + bind_instr(g04_0_list, VSUBSWS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUBM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUBS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUHM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUHS, VD, VA, VB); + bind_instr(g04_0_list, VSUBUWM, VD, VA, VB); + bind_instr(g04_0_list, VSUBUWS, VD, VA, VB); + bind_instr(g04_0_list, VSUMSWS, VD, VA, VB); + bind_instr(g04_0_list, VSUM2SWS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4SBS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4SHS, VD, VA, VB); + bind_instr(g04_0_list, VSUM4UBS, VD, VA, VB); + bind_instr(g04_0_list, VUPKHPX, VD, VB); + bind_instr(g04_0_list, VUPKHSB, VD, VB); + bind_instr(g04_0_list, VUPKHSH, VD, VB); + bind_instr(g04_0_list, VUPKLPX, VD, VB); + bind_instr(g04_0_list, VUPKLSB, VD, VB); + bind_instr(g04_0_list, VUPKLSH, VD, VB); + bind_instr(g04_0_list, VXOR, VD, VA, VB); + + bind_instr(g13_list, MCRF, CRFD, CRFS); + bind_instr(g13_list, BCLR, BO, BI, BH, LK); + bind_instr(g13_list, CRNOR, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRANDC, CRBD, CRBA, CRBB); + bind_instr(g13_list, ISYNC); + bind_instr(g13_list, CRXOR, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRNAND, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRAND, CRBD, CRBA, CRBB); + bind_instr(g13_list, CREQV, CRBD, CRBA, CRBB); + bind_instr(g13_list, CRORC, CRBD, CRBA, CRBB); + bind_instr(g13_list, CROR, CRBD, CRBA, CRBB); + bind_instr(g13_list, BCCTR, BO, BI, BH, LK); + + bind_instr(g1e_list, RLDICL, RA, RS, sh, mb, RC); + bind_instr(g1e_list, RLDICR, RA, RS, sh, me, RC); + bind_instr(g1e_list, RLDIC, RA, RS, sh, mb, RC); + bind_instr(g1e_list, RLDIMI, RA, RS, sh, mb, RC); + bind_instr(g1e_list, RLDC_LR, RA, RS, RB, mb, AA, RC); + + /*0x000*/bind_instr(g1f_list, CMP, CRFD, L_10, RA, RB); + /*0x004*/bind_instr(g1f_list, TW, TO, RA, RB); + /*0x006*/bind_instr(g1f_list, LVSL, VD, RA, RB); + /*0x007*/bind_instr(g1f_list, LVEBX, VD, RA, RB); + /*0x008*/bind_instr(g1f_list, SUBFC, RD, RA, RB, OE, RC); + /*0x009*/bind_instr(g1f_list, MULHDU, RD, RA, RB, RC); + /*0x00a*/bind_instr(g1f_list, ADDC, RD, RA, RB, OE, RC); + /*0x00b*/bind_instr(g1f_list, MULHWU, RD, RA, RB, RC); + /*0x013*/bind_instr(g1f_list, MFOCRF, L_11, RD, CRM); + /*0x014*/bind_instr(g1f_list, LWARX, RD, RA, RB); + /*0x015*/bind_instr(g1f_list, LDX, RD, RA, RB); + /*0x017*/bind_instr(g1f_list, LWZX, RD, RA, RB); + /*0x018*/bind_instr(g1f_list, SLW, RA, RS, RB, RC); + /*0x01a*/bind_instr(g1f_list, CNTLZW, RA, RS, RC); + /*0x01b*/bind_instr(g1f_list, SLD, RA, RS, RB, RC); + /*0x01c*/bind_instr(g1f_list, AND, RA, RS, RB, RC); + /*0x020*/bind_instr(g1f_list, CMPL, CRFD, L_10, RA, RB); + /*0x026*/bind_instr(g1f_list, LVSR, VD, RA, RB); + /*0x027*/bind_instr(g1f_list, LVEHX, VD, RA, RB); + /*0x028*/bind_instr(g1f_list, SUBF, RD, RA, RB, OE, RC); + /*0x035*/bind_instr(g1f_list, LDUX, RD, RA, RB); + /*0x036*/bind_instr(g1f_list, DCBST, RA, RB); + /*0x037*/bind_instr(g1f_list, LWZUX, RD, RA, RB); + /*0x03a*/bind_instr(g1f_list, CNTLZD, RA, RS, RC); + /*0x03c*/bind_instr(g1f_list, ANDC, RA, RS, RB, RC); + /*0x03c*/bind_instr(g1f_list, TD, TO, RA, RB); + /*0x047*/bind_instr(g1f_list, LVEWX, VD, RA, RB); + /*0x049*/bind_instr(g1f_list, MULHD, RD, RA, RB, RC); + /*0x04b*/bind_instr(g1f_list, MULHW, RD, RA, RB, RC); + /*0x054*/bind_instr(g1f_list, LDARX, RD, RA, RB); + /*0x056*/bind_instr(g1f_list, DCBF, RA, RB); + /*0x057*/bind_instr(g1f_list, LBZX, RD, RA, RB); + /*0x067*/bind_instr(g1f_list, LVX, VD, RA, RB); + /*0x068*/bind_instr(g1f_list, NEG, RD, RA, OE, RC); + /*0x077*/bind_instr(g1f_list, LBZUX, RD, RA, RB); + /*0x07c*/bind_instr(g1f_list, NOR, RA, RS, RB, RC); + /*0x087*/bind_instr(g1f_list, STVEBX, VS, RA, RB); + /*0x088*/bind_instr(g1f_list, SUBFE, RD, RA, RB, OE, RC); + /*0x08a*/bind_instr(g1f_list, ADDE, RD, RA, RB, OE, RC); + /*0x090*/bind_instr(g1f_list, MTOCRF, L_11, CRM, RS); + /*0x095*/bind_instr(g1f_list, STDX, RS, RA, RB); + /*0x096*/bind_instr(g1f_list, STWCX_, RS, RA, RB); + /*0x097*/bind_instr(g1f_list, STWX, RS, RA, RB); + /*0x0a7*/bind_instr(g1f_list, STVEHX, VS, RA, RB); + /*0x0b5*/bind_instr(g1f_list, STDUX, RS, RA, RB); + /*0x0b7*/bind_instr(g1f_list, STWUX, RS, RA, RB); + /*0x0c7*/bind_instr(g1f_list, STVEWX, VS, RA, RB); + /*0x0c8*/bind_instr(g1f_list, SUBFZE, RD, RA, OE, RC); + /*0x0ca*/bind_instr(g1f_list, ADDZE, RD, RA, OE, RC); + /*0x0d6*/bind_instr(g1f_list, STDCX_, RS, RA, RB); + /*0x0d7*/bind_instr(g1f_list, STBX, RS, RA, RB); + /*0x0e7*/bind_instr(g1f_list, STVX, VS, RA, RB); + /*0x0e8*/bind_instr(g1f_list, SUBFME, RD, RA, OE, RC); + /*0x0e9*/bind_instr(g1f_list, MULLD, RD, RA, RB, OE, RC); + /*0x0ea*/bind_instr(g1f_list, ADDME, RD, RA, OE, RC); + /*0x0eb*/bind_instr(g1f_list, MULLW, RD, RA, RB, OE, RC); + /*0x0f6*/bind_instr(g1f_list, DCBTST, RA, RB, TH); + /*0x0f7*/bind_instr(g1f_list, STBUX, RS, RA, RB); + /*0x10a*/bind_instr(g1f_list, ADD, RD, RA, RB, OE, RC); + /*0x116*/bind_instr(g1f_list, DCBT, RA, RB, TH); + /*0x117*/bind_instr(g1f_list, LHZX, RD, RA, RB); + /*0x11c*/bind_instr(g1f_list, EQV, RA, RS, RB, RC); + /*0x136*/bind_instr(g1f_list, ECIWX, RD, RA, RB); + /*0x137*/bind_instr(g1f_list, LHZUX, RD, RA, RB); + /*0x13c*/bind_instr(g1f_list, XOR, RA, RS, RB, RC); + /*0x153*/bind_instr(g1f_list, MFSPR, RD, SPR); + /*0x155*/bind_instr(g1f_list, LWAX, RD, RA, RB); + /*0x156*/bind_instr(g1f_list, DST, RA, RB, STRM, L_6); + /*0x157*/bind_instr(g1f_list, LHAX, RD, RA, RB); + /*0x167*/bind_instr(g1f_list, LVXL, VD, RA, RB); + /*0x173*/bind_instr(g1f_list, MFTB, RD, SPR); + /*0x175*/bind_instr(g1f_list, LWAUX, RD, RA, RB); + /*0x176*/bind_instr(g1f_list, DSTST, RA, RB, STRM, L_6); + /*0x177*/bind_instr(g1f_list, LHAUX, RD, RA, RB); + /*0x197*/bind_instr(g1f_list, STHX, RS, RA, RB); + /*0x19c*/bind_instr(g1f_list, ORC, RA, RS, RB, RC); + /*0x1b6*/bind_instr(g1f_list, ECOWX, RS, RA, RB); + /*0x1b7*/bind_instr(g1f_list, STHUX, RS, RA, RB); + /*0x1bc*/bind_instr(g1f_list, OR, RA, RS, RB, RC); + /*0x1c9*/bind_instr(g1f_list, DIVDU, RD, RA, RB, OE, RC); + /*0x1cb*/bind_instr(g1f_list, DIVWU, RD, RA, RB, OE, RC); + /*0x1d3*/bind_instr(g1f_list, MTSPR, SPR, RS); + /*0x1d6*///DCBI + /*0x1dc*/bind_instr(g1f_list, NAND, RA, RS, RB, RC); + /*0x1e7*/bind_instr(g1f_list, STVXL, VS, RA, RB); + /*0x1e9*/bind_instr(g1f_list, DIVD, RD, RA, RB, OE, RC); + /*0x1eb*/bind_instr(g1f_list, DIVW, RD, RA, RB, OE, RC); + /*0x207*/bind_instr(g1f_list, LVLX, VD, RA, RB); + /*0x214*/bind_instr(g1f_list, LDBRX, RD, RA, RB); + /*0x215*/bind_instr(g1f_list, LSWX, RD, RA, RB); + /*0x216*/bind_instr(g1f_list, LWBRX, RD, RA, RB); + /*0x217*/bind_instr(g1f_list, LFSX, FRD, RA, RB); + /*0x218*/bind_instr(g1f_list, SRW, RA, RS, RB, RC); + /*0x21b*/bind_instr(g1f_list, SRD, RA, RS, RB, RC); + /*0x227*/bind_instr(g1f_list, LVRX, VD, RA, RB); + /*0x237*/bind_instr(g1f_list, LFSUX, FRD, RA, RB); + /*0x255*/bind_instr(g1f_list, LSWI, RD, RA, NB); + /*0x256*/bind_instr(g1f_list, SYNC, L_9_10); + /*0x257*/bind_instr(g1f_list, LFDX, FRD, RA, RB); + /*0x277*/bind_instr(g1f_list, LFDUX, FRD, RA, RB); + /*0x287*/bind_instr(g1f_list, STVLX, VS, RA, RB); + /*0x296*/bind_instr(g1f_list, STSWX, RS, RA, RB); + /*0x296*/bind_instr(g1f_list, STWBRX, RS, RA, RB); + /*0x297*/bind_instr(g1f_list, STFSX, FRS, RA, RB); + /*0x2a7*/bind_instr(g1f_list, STVRX, VS, RA, RB); + /*0x2b7*/bind_instr(g1f_list, STFSUX, FRS, RA, RB); + /*0x2d5*/bind_instr(g1f_list, STSWI, RS, RA, NB); + /*0x2d7*/bind_instr(g1f_list, STFDX, FRS, RA, RB); + /*0x2d7*/bind_instr(g1f_list, STFDUX, FRS, RA, RB); + /*0x307*/bind_instr(g1f_list, LVLXL, VD, RA, RB); + /*0x316*/bind_instr(g1f_list, LHBRX, RD, RA, RB); + /*0x318*/bind_instr(g1f_list, SRAW, RA, RS, RB, RC); + /*0x31a*/bind_instr(g1f_list, SRAD, RA, RS, RB, RC); + /*0x327*/bind_instr(g1f_list, LVRXL, VD, RA, RB); + /*0x336*/bind_instr(g1f_list, DSS, STRM, L_6); + /*0x338*/bind_instr(g1f_list, SRAWI, RA, RS, SH, RC); + /*0x33a*/bind_instr(g1f_list, SRADI1, RA, RS, sh, RC); + /*0x33b*/bind_instr(g1f_list, SRADI2, RA, RS, sh, RC); + /*0x356*/bind_instr(g1f_list, EIEIO); + /*0x387*/bind_instr(g1f_list, STVLXL, VS, RA, RB); + /*0x396*/bind_instr(g1f_list, STHBRX, RS, RA, RB); + /*0x39a*/bind_instr(g1f_list, EXTSH, RA, RS, RC); + /*0x387*/bind_instr(g1f_list, STVRXL, VS, RA, RB); + /*0x3ba*/bind_instr(g1f_list, EXTSB, RA, RS, RC); + /*0x3d7*/bind_instr(g1f_list, STFIWX, FRS, RA, RB); + /*0x3da*/bind_instr(g1f_list, EXTSW, RA, RS, RC); + /*0x3d6*/bind_instr(g1f_list, ICBI, RA, RB); + /*0x3f6*/bind_instr(g1f_list, DCBZ, RA, RB); + + bind_instr(g3a_list, LD, RD, RA, DS); + bind_instr(g3a_list, LDU, RD, RA, DS); + bind_instr(g3a_list, LWA, RD, RA, DS); + + bind_instr(g3b_list, FDIVS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FSUBS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FADDS, FRD, FRA, FRB, RC); + bind_instr(g3b_list, FSQRTS, FRD, FRB, RC); + bind_instr(g3b_list, FRES, FRD, FRB, RC); + bind_instr(g3b_list, FMULS, FRD, FRA, FRC, RC); + bind_instr(g3b_list, FMADDS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FMSUBS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FNMSUBS, FRD, FRA, FRC, FRB, RC); + bind_instr(g3b_list, FNMADDS, FRD, FRA, FRC, FRB, RC); + + bind_instr(g3e_list, STD, RS, RA, DS); + bind_instr(g3e_list, STDU, RS, RA, DS); + + bind_instr(g3f_list, FSEL, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FMUL, FRD, FRA, FRC, RC); + bind_instr(g3f_list, FMSUB, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FMADD, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FNMSUB, FRD, FRA, FRC, FRB, RC); + bind_instr(g3f_list, FNMADD, FRD, FRA, FRC, FRB, RC); + + bind_instr(g3f_0_list, FDIV, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FSUB, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FADD, FRD, FRA, FRB, RC); + bind_instr(g3f_0_list, FSQRT, FRD, FRB, RC); + bind_instr(g3f_0_list, FRSQRTE, FRD, FRB, RC); + bind_instr(g3f_0_list, FCMPU, CRFD, FRA, FRB); + bind_instr(g3f_0_list, FRSP, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIW, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIWZ, FRD, FRB, RC); + bind_instr(g3f_0_list, FCMPO, CRFD, FRA, FRB); + bind_instr(g3f_0_list, FNEG, FRD, FRB, RC); + bind_instr(g3f_0_list, FMR, FRD, FRB, RC); + bind_instr(g3f_0_list, FNABS, FRD, FRB, RC); + bind_instr(g3f_0_list, FABS, FRD, FRB, RC); + bind_instr(g3f_0_list, FCFID, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTID, FRD, FRB, RC); + bind_instr(g3f_0_list, FCTIDZ, FRD, FRB, RC); + + bind_instr(g3f_0_list, MTFSB1, CRBD, RC); + bind_instr(g3f_0_list, MCRFS, CRFD, CRFS); + bind_instr(g3f_0_list, MTFSB0, CRBD, RC); + bind_instr(g3f_0_list, MTFSFI, CRFD, I, RC); + bind_instr(g3f_0_list, MFFS, FRD, RC); + bind_instr(g3f_0_list, MTFSF, FM, FRB, RC); + + enum + { + r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, + r12, r13, r14, r15, r16, r17, r18, r19, r20, r21, + r22, r23, r24, r25, r26, r27, r28, r29, r30, r31 + }; + } + + namespace implicts + { + using namespace lists; + + static auto LIS = std::bind(ADDIS, std::placeholders::_1, r0, std::placeholders::_2); + static auto LI = std::bind(ADDI, std::placeholders::_1, r0, std::placeholders::_2); + static auto NOP = std::bind(ORI, r0, r0, 0); + static auto MR = std::bind(OR, std::placeholders::_1, std::placeholders::_2, std::placeholders::_2, false); + static auto BLR = std::bind(BCLR, 0x10 | 0x04, 0, 0, 0); + static auto BCTR = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 0); + static auto BCTRL = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 1); + static auto MTCTR = std::bind(MTSPR, (0x1 << 5) | 0x8, std::placeholders::_1); + } + + + using namespace lists; + using namespace implicts; #undef bind_instr -}; +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 104418d7bd..90dc8ccbf5 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -146,8 +146,25 @@ private: case 0x001: return CPU.XER.XER; case 0x008: return CPU.LR; case 0x009: return CPU.CTR; - case 0x100: return CPU.USPRG0; + case 0x100: + case 0x101: + case 0x102: + case 0x103: + case 0x104: + case 0x105: + case 0x106: + case 0x107: return CPU.USPRG[n - 0x100]; + case 0x10C: return get_time(); + + case 0x110: + case 0x111: + case 0x112: + case 0x113: + case 0x114: + case 0x115: + case 0x116: + case 0x117: return CPU.SPRG[n - 0x110]; } UNK(fmt::Format("ReadSPR error: Unknown SPR 0x%x!", n)); @@ -163,8 +180,25 @@ private: case 0x001: CPU.XER.XER = value; return; case 0x008: CPU.LR = value; return; case 0x009: CPU.CTR = value; return; - case 0x100: CPU.USPRG0 = value; return; + case 0x100: + case 0x101: + case 0x102: + case 0x103: + case 0x104: + case 0x105: + case 0x106: + case 0x107: CPU.USPRG[n - 0x100] = value; break; + case 0x10C: UNK("WriteSPR: Write to time-based SPR. Report this to a developer!"); return; + + case 0x110: + case 0x111: + case 0x112: + case 0x113: + case 0x114: + case 0x115: + case 0x116: + case 0x117: CPU.SPRG[n - 0x110] = value; break; } UNK(fmt::Format("WriteSPR error: Unknown SPR 0x%x!", n)); diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp index 9c3b760ea7..532b26d36a 100644 --- a/rpcs3/Emu/Cell/PPUProgramCompiler.cpp +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.cpp @@ -1,7 +1,7 @@ #include "stdafx_gui.h" #include "PPUProgramCompiler.h" #include "Utilities/rFile.h" - +/* using namespace PPU_instr; template @@ -78,10 +78,10 @@ SectionInfo::SectionInfo(const std::string& _name) section_name_offs += name.length() + 1; } -void SectionInfo::SetDataSize(u32 size, u32 align) +void SectionInfo::SetDataSize(u32 size, u32 addralign) { - if(align) shdr.sh_addralign = align; - if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign); + if (addralign) shdr.sh_addralign = addralign; + if (shdr.sh_addralign) size = align(size, shdr.sh_addralign); if(!code.empty()) { @@ -985,7 +985,7 @@ void CompilePPUProgram::Compile() elf_info.e_shnum = 15; elf_info.e_shstrndx = elf_info.e_shnum - 1; elf_info.e_phoff = elf_info.e_ehsize; - u32 section_offset = AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100); + u32 section_offset = align(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100); static const u32 sceStub_text_block = 8 * 4; @@ -1143,7 +1143,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_sceStub_text; memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr)); s_sceStub_text.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_sceStub_text.sh_addralign); + section_offset = align(section_offset, s_sceStub_text.sh_addralign); s_sceStub_text.sh_type = 1; s_sceStub_text.sh_offset = section_offset; s_sceStub_text.sh_addr = section_offset + 0x10000; @@ -1167,7 +1167,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_lib_stub_top; memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr)); s_lib_stub_top.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_lib_stub_top.sh_addralign); + section_offset = align(section_offset, s_lib_stub_top.sh_addralign); s_lib_stub_top.sh_type = 1; s_lib_stub_top.sh_name = section_name_offset; s_lib_stub_top.sh_offset = section_offset; @@ -1186,7 +1186,7 @@ void CompilePPUProgram::Compile() s_lib_stub.sh_offset = section_offset; s_lib_stub.sh_addr = section_offset + 0x10000; s_lib_stub.sh_flags = 2; - s_lib_stub.sh_size = sizeof(Elf64_StubHeader) * modules.size(); + s_lib_stub.sh_size = sizeof(sys_stub) * modules.size(); sections_names.push_back(".lib.stub"); section_name_offset += std::string(".lib.stub").length() + 1; section_offset += s_lib_stub.sh_size; @@ -1207,7 +1207,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_rodata_sceFNID; memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr)); s_rodata_sceFNID.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign); + section_offset = align(section_offset, s_rodata_sceFNID.sh_addralign); s_rodata_sceFNID.sh_type = 1; s_rodata_sceFNID.sh_name = section_name_offset; s_rodata_sceFNID.sh_offset = section_offset; @@ -1221,7 +1221,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_rodata_sceResident; memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr)); s_rodata_sceResident.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_rodata_sceResident.sh_addralign); + section_offset = align(section_offset, s_rodata_sceResident.sh_addralign); s_rodata_sceResident.sh_type = 1; s_rodata_sceResident.sh_name = section_name_offset; s_rodata_sceResident.sh_offset = section_offset; @@ -1232,7 +1232,7 @@ void CompilePPUProgram::Compile() { s_rodata_sceResident.sh_size += module.m_name.length() + 1; } - s_rodata_sceResident.sh_size = AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign); + s_rodata_sceResident.sh_size = align(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign); sections_names.push_back(".rodata.sceResident"); section_name_offset += std::string(".rodata.sceResident").length() + 1; section_offset += s_rodata_sceResident.sh_size; @@ -1240,7 +1240,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_lib_ent_top; memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr)); s_lib_ent_top.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_lib_ent_top.sh_addralign); + section_offset = align(section_offset, s_lib_ent_top.sh_addralign); s_lib_ent_top.sh_size = 4; s_lib_ent_top.sh_flags = 2; s_lib_ent_top.sh_type = 1; @@ -1267,7 +1267,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_sys_proc_prx_param; memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr)); s_sys_proc_prx_param.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign); + section_offset = align(section_offset, s_sys_proc_prx_param.sh_addralign); s_sys_proc_prx_param.sh_type = 1; s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param); s_sys_proc_prx_param.sh_name = section_name_offset; @@ -1280,14 +1280,14 @@ void CompilePPUProgram::Compile() const u32 prog_load_0_end = section_offset; - section_offset = AlignAddr(section_offset + 0x10000, 0x10000); + section_offset = align(section_offset + 0x10000, 0x10000); const u32 prog_load_1_start = section_offset; Elf64_Shdr s_data_sceFStub; memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr)); s_data_sceFStub.sh_name = section_name_offset; s_data_sceFStub.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_data_sceFStub.sh_addralign); + section_offset = align(section_offset, s_data_sceFStub.sh_addralign); s_data_sceFStub.sh_flags = 3; s_data_sceFStub.sh_type = 1; s_data_sceFStub.sh_offset = section_offset; @@ -1300,7 +1300,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_tbss; memset(&s_tbss, 0, sizeof(Elf64_Shdr)); s_tbss.sh_addralign = 4; - section_offset = AlignAddr(section_offset, s_tbss.sh_addralign); + section_offset = align(section_offset, s_tbss.sh_addralign); s_tbss.sh_size = 4; s_tbss.sh_flags = 0x403; s_tbss.sh_type = 8; @@ -1314,7 +1314,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_opd; memset(&s_opd, 0, sizeof(Elf64_Shdr)); s_opd.sh_addralign = 8; - section_offset = AlignAddr(section_offset, s_opd.sh_addralign); + section_offset = align(section_offset, s_opd.sh_addralign); s_opd.sh_size = 2*4; s_opd.sh_type = 1; s_opd.sh_offset = section_offset; @@ -1475,7 +1475,7 @@ void CompilePPUProgram::Compile() if(!m_file_path.empty() && !m_analyze && !m_error) { - s_opd.sh_size = AlignAddr(s_opd.sh_size, s_opd.sh_addralign); + s_opd.sh_size = align(s_opd.sh_size, s_opd.sh_addralign); section_offset += s_opd.sh_size; const u32 prog_load_1_end = section_offset; @@ -1483,7 +1483,7 @@ void CompilePPUProgram::Compile() Elf64_Shdr s_shstrtab; memset(&s_shstrtab, 0, sizeof(Elf64_Shdr)); s_shstrtab.sh_addralign = 1; - section_offset = AlignAddr(section_offset, s_shstrtab.sh_addralign); + section_offset = align(section_offset, s_shstrtab.sh_addralign); s_shstrtab.sh_name = section_name_offset; s_shstrtab.sh_type = 3; s_shstrtab.sh_offset = section_offset; @@ -1505,7 +1505,7 @@ void CompilePPUProgram::Compile() elf_info.e_machine = MACHINE_PPC64; //PowerPC64 elf_info.e_version = 1; //ver 1 elf_info.e_flags = 0x0; - elf_info.e_shoff = AlignAddr(section_offset, 4); + elf_info.e_shoff = align(section_offset, 4); u8* opd_data = new u8[s_opd.sh_size]; u32 entry_point = s_text.sh_addr; @@ -1523,14 +1523,14 @@ void CompilePPUProgram::Compile() sys_proc_prx_param prx_param; memset(&prx_param, 0, sizeof(sys_proc_prx_param)); - prx_param.size = re32(0x40); - prx_param.magic = re32(0x1b434cec); - prx_param.version = re32(0x4); - prx_param.libentstart = re32(s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size); - prx_param.libentend = re32(s_lib_ent_btm.sh_addr); - prx_param.libstubstart = re32(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size); - prx_param.libstubend = re32(s_lib_stub_btm.sh_addr); - prx_param.ver = re16(0x101); + prx_param.size = 0x40; + prx_param.magic = 0x1b434cec; + prx_param.version = 0x4; + prx_param.libentstart = s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size; + prx_param.libentend = s_lib_ent_btm.sh_addr; + prx_param.libstubstart = vm::bptr::make(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size); + prx_param.libstubend = vm::bptr::make(s_lib_stub_btm.sh_addr); + prx_param.ver = 0x101; elf_info.e_entry = s_opd.sh_addr; @@ -1588,20 +1588,20 @@ void CompilePPUProgram::Compile() f.Seek(s_lib_stub.sh_offset); for(u32 i=0, nameoffs=4, dataoffs=0; i::make(s_rodata_sceResident.sh_addr + nameoffs); + stub.s_nid = vm::bptr::make(s_rodata_sceFNID.sh_addr + dataoffs); + stub.s_text = vm::bptr::make(s_data_sceFStub.sh_addr + dataoffs); + stub.s_imports = modules[i].m_imports.size(); dataoffs += modules[i].m_imports.size() * 4; - f.Write(&stub, sizeof(Elf64_StubHeader)); + f.Write(&stub, sizeof(sys_stub)); nameoffs += modules[i].m_name.length() + 1; } @@ -1732,3 +1732,4 @@ void CompilePPUProgram::Compile() system("make_fself.cmd"); } } +*/ \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUProgramCompiler.h b/rpcs3/Emu/Cell/PPUProgramCompiler.h index 608fbc4c1e..5070c34516 100644 --- a/rpcs3/Emu/Cell/PPUProgramCompiler.h +++ b/rpcs3/Emu/Cell/PPUProgramCompiler.h @@ -1,7 +1,7 @@ #pragma once #include "PPUInstrTable.h" #include "Loader/ELF64.h" - +/* enum ArgType { ARG_ERR = 0, @@ -189,3 +189,4 @@ protected: public: void Compile(); }; +*/ \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index a950332fc7..e8189828a6 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -10,6 +10,8 @@ #include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPULLVMRecompiler.h" +//#include "Emu/Cell/PPURecompiler.h" +#include "Emu/CPU/CPUThreadManager.h" PPUThread& GetCurrentPPUThread() { @@ -39,11 +41,11 @@ void PPUThread::DoReset() memset(FPR, 0, sizeof(FPR)); memset(GPR, 0, sizeof(GPR)); memset(SPRG, 0, sizeof(SPRG)); + memset(USPRG, 0, sizeof(USPRG)); CR.CR = 0; LR = 0; CTR = 0; - USPRG0 = 0; TB = 0; XER.XER = 0; FPSCR.FPSCR = 0; @@ -84,8 +86,10 @@ void PPUThread::InitRegs() } */ - GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200; + GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200; GPR[2] = rtoc; + GPR[11] = entry; + GPR[12] = Emu.GetMallocPageSize(); GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; LR = Emu.GetPPUThreadExit(); @@ -122,6 +126,8 @@ void PPUThread::DoRun() #endif break; + //case 3: m_dec = new PPURecompiler(*this); break; + default: LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue()); Emu.Pause(); @@ -218,12 +224,24 @@ void PPUThread::FastStop() void PPUThread::Task() { - if (m_custom_task) + if (custom_task) { - m_custom_task(*this); + custom_task(*this); } else { CPUThread::Task(); } } + +ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +{ + thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + + thread->SetName(name); + thread->SetEntry(entry); + thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize); + thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); + + argc = 0; +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 1f408210b9..e7f50f81e6 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -1,5 +1,6 @@ #pragma once #include "Emu/Cell/PPCThread.h" +#include "Emu/Memory/vm.h" enum { @@ -530,11 +531,8 @@ public: u64 LR; //SPR 0x008 : Link Register u64 CTR; //SPR 0x009 : Count Register - union - { - u64 USPRG0; //SPR 0x100 : User-SPR General-Purpose Register 0 - u64 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers - }; + u64 USPRG[8]; //SPR 0x100 - 0x107: User-SPR General-Purpose Registers + u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers //TBR : Time-Base Registers union @@ -554,7 +552,7 @@ public: u64 R_VALUE; // reservation value (BE) u32 owned_mutexes; - std::function m_custom_task; + std::function custom_task; public: PPUThread(); @@ -799,3 +797,49 @@ protected: }; PPUThread& GetCurrentPPUThread(); + +class ppu_thread : cpu_thread +{ + static const u32 stack_align = 0x10; + vm::ptr argv; + u32 argc; + vm::ptr envp; + +public: + ppu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + + cpu_thread& args(std::initializer_list values) override + { + if (!values.size()) + return *this; + + assert(argc == 0); + + envp.set(vm::alloc(align((u32)sizeof(*envp), stack_align), vm::main)); + *envp = 0; + argv.set(vm::alloc(sizeof(*argv) * values.size(), vm::main)); + + for (auto &arg : values) + { + u32 arg_size = align(u32(arg.size() + 1), stack_align); + u32 arg_addr = vm::alloc(arg_size, vm::main); + + std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); + + argv[argc++] = arg_addr; + } + + return *this; + } + + cpu_thread& run() override + { + thread->Run(); + + static_cast(thread)->GPR[3] = argc; + static_cast(thread)->GPR[4] = argv.addr(); + static_cast(thread)->GPR[5] = envp.addr(); + + return *this; + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index bf8d55b984..719cdc8cab 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1163,7 +1163,6 @@ void SPUThread::StopAndSignal(u32 code) } default: - { if (!SPU.Out_MBox.GetCount()) { LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); @@ -1175,5 +1174,16 @@ void SPUThread::StopAndSignal(u32 code) Emu.Pause(); break; } - } } + +spu_thread::spu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +{ + thread = &Emu.GetCPU().AddThread(CPU_THREAD_SPU); + + thread->SetName(name); + thread->SetEntry(entry); + thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize); + thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); + + argc = 0; +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 5553d2fc28..aaffd7d00d 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -583,3 +583,49 @@ protected: }; SPUThread& GetCurrentSPUThread(); + +class spu_thread : cpu_thread +{ + static const u32 stack_align = 0x10; + vm::ptr argv; + u32 argc; + vm::ptr envp; + +public: + spu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + + cpu_thread& args(std::initializer_list values) override + { + if (!values.size()) + return *this; + + assert(argc == 0); + + envp.set(Memory.MainMem.AllocAlign((u32)sizeof(envp), stack_align)); + *envp = 0; + argv.set(Memory.MainMem.AllocAlign(u32(sizeof(argv)* values.size()), stack_align)); + + for (auto &arg : values) + { + u32 arg_size = align(u32(arg.size() + 1), stack_align); + u32 arg_addr = Memory.MainMem.AllocAlign(arg_size, stack_align); + + std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); + + argv[argc++] = arg_addr; + } + + return *this; + } + + cpu_thread& run() override + { + thread->Run(); + + static_cast(thread)->GPR[3].from64(argc); + static_cast(thread)->GPR[4].from64(argv.addr()); + static_cast(thread)->GPR[5].from64(envp.addr()); + + return *this; + } +}; \ No newline at end of file diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 59c6c5feb3..ddb837d725 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -108,9 +108,9 @@ void MemoryBase::Init(MemoryType type) memset(RawSPUMem, 0, sizeof(RawSPUMem)); #ifdef _WIN32 - if (!g_base_addr) + if (!vm::g_base_addr) #else - if ((s64)g_base_addr == (s64)-1) + if ((s64)vm::g_base_addr == (s64)-1) #endif { LOG_ERROR(MEMORY, "Initializing memory failed"); @@ -119,7 +119,7 @@ void MemoryBase::Init(MemoryType type) } else { - LOG_NOTICE(MEMORY, "Initializing memory: m_base_addr = 0x%llx", (u64)g_base_addr); + LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr); } switch (type) @@ -128,6 +128,8 @@ void MemoryBase::Init(MemoryType type) MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000)); MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000)); MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 0x10000000)); + MemoryBlocks.push_back(SPRXMem.SetRange(0x50000000, 0x10000000)); + MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000)); MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000)); break; @@ -217,6 +219,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size) } MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size)); + LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size); return true; } @@ -412,12 +415,6 @@ void DynamicMemoryBlockBase::Delete() bool DynamicMemoryBlockBase::AllocFixed(u64 addr, u32 size) { - if (!MemoryBlock::GetStartAddr()) - { - LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocFixed(addr=0x%llx, size=0x%x): memory block not initialized", addr, size); - return false; - } - size = PAGE_4K(size + (addr & 4095)); // align size addr &= ~4095; // align start address @@ -452,7 +449,7 @@ u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align); return 0; } - + size = PAGE_4K(size); u32 exsize; @@ -579,9 +576,9 @@ bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size) bool VirtualMemoryBlock::IsMyAddress(const u64 addr) { - for(u32 i=0; i= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) + if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) { return true; } @@ -620,7 +617,7 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size) bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr) { - if(!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1))) + if (!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1))) return false; m_mapped_memory.emplace_back(addr, realaddr, size); @@ -629,9 +626,9 @@ bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr) bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr, u32& size) { - for(u32 i=0; i= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) + if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) { result = m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr); return true; @@ -691,9 +688,9 @@ bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result) u64 VirtualMemoryBlock::getMappedAddress(u64 realAddress) { - for(u32 i=0; i= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size) + if (realAddress >= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size) { return m_mapped_memory[i].addr + (realAddress - m_mapped_memory[i].realAddress); } @@ -711,7 +708,7 @@ void VirtualMemoryBlock::Delete() bool VirtualMemoryBlock::Reserve(u32 size) { - if(size + GetReservedAmount() > GetEndAddr() - GetStartAddr()) + if (size + GetReservedAmount() > GetEndAddr() - GetStartAddr()) return false; m_reserve_size += size; @@ -720,7 +717,7 @@ bool VirtualMemoryBlock::Reserve(u32 size) bool VirtualMemoryBlock::Unreserve(u32 size) { - if(size > GetReservedAmount()) + if (size > GetReservedAmount()) return false; m_reserve_size -= size; @@ -730,4 +727,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size) u32 VirtualMemoryBlock::GetReservedAmount() { return m_reserve_size; -} +} \ No newline at end of file diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index 1ec1201b3c..1fccab32b8 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -7,8 +7,6 @@ using std::nullptr_t; #define safe_delete(x) do {delete (x);(x)=nullptr;} while(0) #define safe_free(x) do {free(x);(x)=nullptr;} while(0) -extern void* const g_base_addr; - enum MemoryType { Memory_PS3, @@ -24,6 +22,11 @@ enum : u32 RAW_SPU_PROB_OFFSET = 0x00040000, }; +namespace vm +{ + extern void* const g_base_addr; +} + class MemoryBase { std::vector MemoryBlocks; @@ -33,8 +36,10 @@ public: MemoryBlock* UserMemory; DynamicMemoryBlock MainMem; + DynamicMemoryBlock SPRXMem; DynamicMemoryBlock PRXMem; DynamicMemoryBlock RSXCMDMem; + DynamicMemoryBlock MmaperMem; DynamicMemoryBlock RSXFBMem; DynamicMemoryBlock StackMem; MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]; @@ -69,7 +74,7 @@ public: static void* const GetBaseAddr() { - return g_base_addr; + return vm::g_base_addr; } __noinline void InvalidAddress(const char* func, const u64 addr); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 91708cf50c..95e879e6bb 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -1,23 +1,22 @@ #include "stdafx.h" #include "Memory.h" -#ifdef _WIN32 -#include - -void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); -#else -#include - -/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -void* const g_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); -#endif - namespace vm { + #ifdef _WIN32 + #include + void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); + #else + #include + + /* OS X uses MAP_ANON instead of MAP_ANONYMOUS */ + #ifndef MAP_ANONYMOUS + #define MAP_ANONYMOUS MAP_ANON + #endif + + void* const g_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + #endif + bool check_addr(u32 addr) { // Checking address before using it is unsafe. @@ -28,20 +27,117 @@ namespace vm //TODO bool map(u32 addr, u32 size, u32 flags) { - return false; + return Memory.Map(addr, size); } bool unmap(u32 addr, u32 size, u32 flags) { - return false; + return Memory.Unmap(addr); } - u32 alloc(u32 size) + u32 alloc(u32 addr, u32 size, memory_location location) { - return 0; + return g_locations[location].fixed_allocator(addr, size); } - void unalloc(u32 addr) + u32 alloc(u32 size, memory_location location) { + return g_locations[location].allocator(size); + } + + void dealloc(u32 addr, memory_location location) + { + return g_locations[location].deallocator(addr); + } + + namespace ps3 + { + u32 main_alloc(u32 size) + { + return Memory.MainMem.AllocAlign(size, 1); + } + u32 main_fixed_alloc(u32 addr, u32 size) + { + return Memory.MainMem.AllocFixed(addr, size) ? addr : 0; + } + void main_dealloc(u32 addr) + { + Memory.MainMem.Free(addr); + } + + u32 g_stack_offset = 0; + + u32 stack_alloc(u32 size) + { + return Memory.StackMem.AllocAlign(size, 0x10); + } + u32 stack_fixed_alloc(u32 addr, u32 size) + { + return Memory.StackMem.AllocFixed(addr, size) ? addr : 0; + } + void stack_dealloc(u32 addr) + { + Memory.StackMem.Free(addr); + } + + u32 sprx_alloc(u32 size) + { + return Memory.SPRXMem.AllocAlign(size, 1); + } + u32 sprx_fixed_alloc(u32 addr, u32 size) + { + return Memory.SPRXMem.AllocFixed(Memory.SPRXMem.GetStartAddr() + addr, size) ? Memory.SPRXMem.GetStartAddr() + addr : 0; + } + void sprx_dealloc(u32 addr) + { + Memory.SPRXMem.Free(addr); + } + + u32 user_space_alloc(u32 size) + { + return Memory.PRXMem.AllocAlign(size, 1); + } + u32 user_space_fixed_alloc(u32 addr, u32 size) + { + return Memory.PRXMem.AllocFixed(addr, size) ? addr : 0; + } + void user_space_dealloc(u32 addr) + { + Memory.PRXMem.Free(addr); + } + + void init() + { + Memory.Init(Memory_PS3); + } + } + + namespace psv + { + void init() + { + Memory.Init(Memory_PSV); + } + } + + namespace psp + { + void init() + { + Memory.Init(Memory_PSP); + } + } + + location_info g_locations[memory_location_count] = + { + { 0x00010000, 0x2FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc }, + { 0x00010000, 0x2FFF0000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc }, + { 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc }, + { 0x00010000, 0x2FFF0000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc }, + }; + + void close() + { + Memory.Close(); } } \ No newline at end of file diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 44378084be..75a9052412 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -1,17 +1,53 @@ #pragma once +#include "Memory.h" namespace vm { + enum memory_location + { + main, + stack, + sprx, + user_space, + + memory_location_count + }; + + struct location_info + { + u32 addr_offset; + u32 size; + + u32(*allocator)(u32 size); + u32(*fixed_allocator)(u32 addr, u32 size); + void(*deallocator)(u32 addr); + + u32 alloc_offset; + }; + + extern location_info g_locations[memory_location_count]; + + static void set_stack_size(u32 size) {} + static void initialize_stack() {} + + extern void* const g_base_addr; bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); - u32 alloc(u32 size); - void unalloc(u32 addr); + u32 alloc(u32 size, memory_location location = user_space); + u32 alloc(u32 addr, u32 size, memory_location location = user_space); + void dealloc(u32 addr, memory_location location = user_space); - template + template T* const get_ptr(u32 addr) { return (T*)((u8*)g_base_addr + addr); } + + template + T* const get_ptr(u64 addr) + { + return get_ptr((u32)addr); + } template T& get_ref(u32 addr) @@ -19,8 +55,16 @@ namespace vm return *get_ptr(addr); } + template + T& get_ref(u64 addr) + { + return get_ref((u32)addr); + } + namespace ps3 { + void init(); + static u8 read8(u32 addr) { return *((u8*)g_base_addr + addr); @@ -36,9 +80,9 @@ namespace vm return re16(*(u16*)((u8*)g_base_addr + addr)); } - static void write16(u32 addr, u16 value) + static void write16(u32 addr, be_t value) { - *(u16*)((u8*)g_base_addr + addr) = re16(value); + *(be_t*)((u8*)g_base_addr + addr) = value; } static u32 read32(u32 addr) @@ -53,11 +97,11 @@ namespace vm } } - static void write32(u32 addr, u32 value) + static void write32(u32 addr, be_t value) { if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET) { - *(u32*)((u8*)g_base_addr + addr) = re32(value); + *(be_t*)((u8*)g_base_addr + addr) = value; } else { @@ -70,9 +114,24 @@ namespace vm return re64(*(u64*)((u8*)g_base_addr + addr)); } + static void write64(u32 addr, be_t value) + { + *(be_t*)((u8*)g_base_addr + addr) = value; + } + + static void write16(u32 addr, u16 value) + { + write16(addr, be_t::make(value)); + } + + static void write32(u32 addr, u32 value) + { + write32(addr, be_t::make(value)); + } + static void write64(u32 addr, u64 value) { - *(u64*)((u8*)g_base_addr + addr) = re64(value); + write64(addr, be_t::make(value)); } static u128 read128(u32 addr) @@ -88,6 +147,8 @@ namespace vm namespace psv { + void init(); + static u8 read8(u32 addr) { return *((u8*)g_base_addr + addr); @@ -138,8 +199,17 @@ namespace vm *(u128*)((u8*)g_base_addr + addr) = value; } } + + namespace psp + { + using namespace psv; + + void init(); + } + + void close(); } #include "vm_ref.h" #include "vm_ptr.h" -#include "vm_var.h" +#include "vm_var.h" \ No newline at end of file diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 7a956f9e4d..c984b18e0a 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -10,7 +10,7 @@ namespace vm AT m_addr; public: - typedef T type; + typedef typename std::remove_cv::type type; _ptr_base operator++ (int) { @@ -38,49 +38,49 @@ namespace vm return *this; } - _ptr_base& operator += (int count) + _ptr_base& operator += (AT count) { m_addr += count * sizeof(AT); return *this; } - _ptr_base& operator -= (int count) + _ptr_base& operator -= (AT count) { m_addr -= count * sizeof(AT); return *this; } - _ptr_base operator + (int count) const - { - return make(m_addr + count * sizeof(AT)); - } + _ptr_base operator + (typename remove_be_t::type count) const { return make(m_addr + count * sizeof(AT)); } + _ptr_base operator + (typename to_be_t::type count) const { return make(m_addr + count * sizeof(AT)); } + _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * sizeof(AT)); } + _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * sizeof(AT)); } - _ptr_base operator - (int count) const - { - return make(m_addr - count * sizeof(AT)); - } + __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + explicit operator bool() const { return m_addr != 0; } __forceinline _ptr_base::value, typename to_be_t::type, AT>>& operator *() const { return vm::get_ref<_ptr_base::value, typename to_be_t::type, AT>>>(m_addr); } - __forceinline _ptr_base::value, typename to_be_t::type, AT>>& operator [](int index) const + __forceinline _ptr_base::value, typename to_be_t::type, AT>>& operator [](AT index) const { return vm::get_ref<_ptr_base::value, typename to_be_t::type, AT>>>(m_addr + sizeof(AT)* index); } - operator bool() const - { - return m_addr != 0; - } - //typedef typename invert_be_t::type AT2; template operator const _ptr_base() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return (_ptr_base&)addr; } @@ -108,6 +108,8 @@ namespace vm AT m_addr; public: + typedef typename std::remove_cv::type type; + __forceinline T* const operator -> () const { return vm::get_ptr(m_addr); @@ -139,38 +141,44 @@ namespace vm return *this; } - _ptr_base& operator += (int count) + _ptr_base& operator += (AT count) { m_addr += count * sizeof(T); return *this; } - _ptr_base& operator -= (int count) + _ptr_base& operator -= (AT count) { m_addr -= count * sizeof(T); return *this; } - _ptr_base operator + (int count) const - { - return make(m_addr + count * sizeof(T)); - } - - _ptr_base operator - (int count) const - { - return make(m_addr - count * sizeof(T)); - } + _ptr_base operator + (typename remove_be_t::type count) const { return make(m_addr + count * sizeof(T)); } + _ptr_base operator + (typename to_be_t::type count) const { return make(m_addr + count * sizeof(T)); } + _ptr_base operator - (typename remove_be_t::type count) const { return make(m_addr - count * sizeof(T)); } + _ptr_base operator - (typename to_be_t::type count) const { return make(m_addr - count * sizeof(T)); } __forceinline T& operator *() const { - return get_ref(m_addr); + return vm::get_ref(m_addr); } - __forceinline T& operator [](int index) const + __forceinline T& operator [](AT index) const { - return get_ref(m_addr + sizeof(T) * index); + return vm::get_ref(m_addr + sizeof(AT)* index); } - + + __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + explicit operator bool() const { return m_addr != 0; } + explicit operator T*() const { return get_ptr(); } + /* operator _ref_base() { @@ -188,26 +196,27 @@ namespace vm return m_addr; } - void set(const AT value) + void set(AT value) { m_addr = value; } - operator bool() const + /* + operator T*() const { - return m_addr != 0; + return get_ptr(); } - + */ //typedef typename invert_be_t::type AT2; template operator const _ptr_base() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return (_ptr_base&)addr; } - T* const get_ptr() const + T* get_ptr() const { return vm::get_ptr(m_addr); } @@ -236,29 +245,39 @@ namespace vm m_addr = value; } - void* const get_ptr() const + void* get_ptr() const { return vm::get_ptr(m_addr); } - operator bool() const + explicit operator void*() const { - return m_addr != 0; + return get_ptr(); } + __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + explicit operator bool() const { return m_addr != 0; } + //typedef typename invert_be_t::type AT2; template operator const _ptr_base() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return (_ptr_base&)addr; } template operator const _ptr_base() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return (_ptr_base&)addr; } @@ -286,16 +305,26 @@ namespace vm m_addr = value; } - const void* const get_ptr() const + const void* get_ptr() const { return vm::get_ptr(m_addr); } - operator bool() const + explicit operator const void*() const { - return m_addr != 0; + return get_ptr(); } + __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + explicit operator bool() const { return m_addr != 0; } + //typedef typename invert_be_t::type AT2; template @@ -335,17 +364,22 @@ namespace vm m_addr = value; } - operator bool() const - { - return m_addr != 0; - } + __forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; } + __forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; } + __forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; } + __forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; } + __forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; } + __forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; } + __forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; } + __forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; } + explicit operator bool() const { return m_addr != 0; } //typedef typename invert_be_t::type AT2; template operator const _ptr_base() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return (_ptr_base&)addr; } @@ -356,7 +390,7 @@ namespace vm operator const std::function() const { - typename std::remove_const::type addr; addr = m_addr; + typename std::remove_const::type addr = m_addr; return [addr](T... args) -> RT { return make(addr)(args...); }; } @@ -366,7 +400,7 @@ namespace vm //BE pointer to LE data template struct bptrl : public _ptr_base::type> { - static bptrl make(typename to_be_t::type addr) + static bptrl make(AT addr) { return (bptrl&)addr; } @@ -378,7 +412,7 @@ namespace vm //BE pointer to BE data template struct bptrb : public _ptr_base::type, lvl, typename to_be_t::type> { - static bptrb make(typename to_be_t::type addr) + static bptrb make(AT addr) { return (bptrb&)addr; } @@ -413,7 +447,7 @@ namespace vm namespace ps3 { - //default pointer for HLE functions (LE ptrerence to BE data) + //default pointer for HLE functions (LE pointer to BE data) template struct ptr : public lptrb { static ptr make(AT addr) @@ -425,10 +459,10 @@ namespace vm //using lptrb::operator const _ptr_base::type, lvl, AT>; }; - //default pointer for HLE structures (BE ptrerence to BE data) + //default pointer for HLE structures (BE pointer to BE data) template struct bptr : public bptrb { - static bptr make(typename to_be_t::type addr) + static bptr make(AT addr) { return (bptr&)addr; } @@ -440,7 +474,7 @@ namespace vm namespace psv { - //default pointer for HLE functions & structures (LE ptrerence to LE data) + //default pointer for HLE functions & structures (LE pointer to LE data) template struct ptr : public lptrl { static ptr make(AT addr) diff --git a/rpcs3/Emu/SysCalls/ModuleManager.h b/rpcs3/Emu/SysCalls/ModuleManager.h index 33034a9739..5d40cd35ad 100644 --- a/rpcs3/Emu/SysCalls/ModuleManager.h +++ b/rpcs3/Emu/SysCalls/ModuleManager.h @@ -10,6 +10,8 @@ class ModuleManager std::vector m_modules_funcs_list; std::vector m_mod_init; //owner of Module bool initialized; + std::unordered_map m_registered_functions; + public: ModuleManager(); ~ModuleManager(); @@ -24,4 +26,20 @@ public: u32 GetFuncNumById(u32 id); Module* GetModuleByName(const std::string& name); Module* GetModuleById(u16 id); + + void register_function(u32 fnid, u32 fstub) + { + m_registered_functions[fnid] = fstub; + } + + bool get_function_stub(u32 fnid, be_t& res) + { + auto f = m_registered_functions.find(fnid); + + if (f == m_registered_functions.end()) + return false; + + res = f->second; + return true; + } }; \ No newline at end of file diff --git a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp b/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp index cbb9506377..260c8eb9bb 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAvconfExt.cpp @@ -16,15 +16,16 @@ int cellVideoOutGetScreenSize(u32 videoOut, vm::ptr screenSize) { cellAvconfExt->Warning("cellVideoOutGetScreenSize(videoOut=%d, screenSize_addr=0x%x)", videoOut, screenSize.addr()); - if (videoOut != CELL_VIDEO_OUT_PRIMARY) + if (!videoOut == CELL_VIDEO_OUT_PRIMARY) return CELL_VIDEO_OUT_ERROR_UNSUPPORTED_VIDEO_OUT; + //TODO: Use virtual screen size #ifdef _WIN32 HDC screen = GetDC(NULL); - float diagonal = roundf(sqrtf((powf(GetDeviceCaps(screen, HORZSIZE), 2) + powf(GetDeviceCaps(screen, VERTSIZE), 2))) * 0.0393); + float diagonal = round(sqrt((pow(GetDeviceCaps(screen, HORZSIZE), 2) + pow(GetDeviceCaps(screen, VERTSIZE), 2))) * 0.0393); #else // TODO: Linux implementation, without using wx - // float diagonal = roundf(sqrtf((powf(wxGetDisplaySizeMM().GetWidth(), 2) + powf(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393); + // float diagonal = round(sqrt((pow(wxGetDisplaySizeMM().GetWidth(), 2) + pow(wxGetDisplaySizeMM().GetHeight(), 2))) * 0.0393); #endif if (Ini.GS3DTV.GetValue()) diff --git a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp index ac359d0e1c..16a5064293 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellPamf.cpp @@ -77,16 +77,14 @@ int pamfStreamTypeToEsFilterId(u8 type, u8 ch, vm::ptr pEsF u8 pamfGetStreamType(vm::ptr pSelf, u8 stream) { //TODO: get stream type correctly - vm::ptr pAddr(pSelf->pAddr); - - switch (pAddr->stream_headers[stream].type) + switch (pSelf->pAddr->stream_headers[stream].type) { case 0x1b: return CELL_PAMF_STREAM_TYPE_AVC; case 0xdc: return CELL_PAMF_STREAM_TYPE_ATRAC3PLUS; case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM; case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA; default: - cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pAddr->stream_headers[stream].type); + cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type); return 0; } } @@ -94,18 +92,18 @@ u8 pamfGetStreamType(vm::ptr pSelf, u8 stream) u8 pamfGetStreamChannel(vm::ptr pSelf, u8 stream) { //TODO: get stream channel correctly - vm::ptr pAddr(pSelf->pAddr); - switch (pAddr->stream_headers[stream].type) + switch (pSelf->pAddr->stream_headers[stream].type) { case 0x1b: - if ((pAddr->stream_headers[stream].stream_id >= 0xe0) && (pAddr->stream_headers[stream].stream_id <= 0xef)) + if ((pSelf->pAddr->stream_headers[stream].stream_id >= 0xe0) && (pSelf->pAddr->stream_headers[stream].stream_id <= 0xef)) { - return pAddr->stream_headers[stream].stream_id - 0xe0; + return pSelf->pAddr->stream_headers[stream].stream_id - 0xe0; } else { - cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x", pAddr->stream_headers[stream].type, pAddr->stream_headers[stream].stream_id); + cellPamf->Error("pamfGetStreamChannel: stream type 0x%x got invalid stream id=0x%x", + pSelf->pAddr->stream_headers[stream].type, pSelf->pAddr->stream_headers[stream].stream_id); return 0; } case 0xdc: @@ -118,7 +116,7 @@ u8 pamfGetStreamChannel(vm::ptr pSelf, u8 stream) cellPamf->Todo("pamfGetStreamChannel: CELL_PAMF_STREAM_TYPE_USER_DATA"); return 0; default: - cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pAddr->stream_headers[stream].type); + cellPamf->Todo("pamfGetStreamType: unsupported stream type found(0x%x)", pSelf->pAddr->stream_headers[stream].type); return 0; } @@ -200,10 +198,8 @@ int cellPamfReaderGetPresentationStartTime(vm::ptr pSelf, vm::pt return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - const u32 upper = (u16)pAddr->start_pts_high; - pTimeStamp->upper = upper; - pTimeStamp->lower = pAddr->start_pts_low; + pTimeStamp->upper = (u32)(u16)pSelf->pAddr->start_pts_high; + pTimeStamp->lower = pSelf->pAddr->start_pts_low; return CELL_OK; } @@ -215,10 +211,8 @@ int cellPamfReaderGetPresentationEndTime(vm::ptr pSelf, vm::ptr< return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - const u32 upper = (u16)pAddr->end_pts_high; - pTimeStamp->upper = upper; - pTimeStamp->lower = pAddr->end_pts_low; + pTimeStamp->upper = (u32)(u16)pSelf->pAddr->end_pts_high; + pTimeStamp->lower = pSelf->pAddr->end_pts_low; return CELL_OK; } @@ -230,8 +224,7 @@ int cellPamfReaderGetMuxRateBound(vm::ptr pSelf) return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - return pAddr->mux_rate_max; + return pSelf->pAddr->mux_rate_max; } int cellPamfReaderGetNumberOfStreams(vm::ptr pSelf) @@ -242,8 +235,7 @@ int cellPamfReaderGetNumberOfStreams(vm::ptr pSelf) return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - return pAddr->stream_count; + return pSelf->pAddr->stream_count; } int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr pSelf, u8 streamType) @@ -254,11 +246,9 @@ int cellPamfReaderGetNumberOfSpecificStreams(vm::ptr pSelf, u8 s return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - int counts[6] = {0, 0, 0, 0, 0, 0}; - for (u8 i = 0; i < pAddr->stream_count; i++) + for (u8 i = 0; i < pSelf->pAddr->stream_count; i++) { counts[pamfGetStreamType(pSelf, i)]++; } @@ -289,18 +279,14 @@ int cellPamfReaderSetStreamWithIndex(vm::ptr pSelf, u8 streamInd return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - - if (streamIndex < pAddr->stream_count) + if (streamIndex < pSelf->pAddr->stream_count) { pSelf->stream = streamIndex; return CELL_OK; } - else - { - cellPamf->Error("cellPamfReaderSetStreamWithIndex: CELL_PAMF_ERROR_INVALID_ARG"); - return CELL_PAMF_ERROR_INVALID_ARG; - } + + cellPamf->Error("cellPamfReaderSetStreamWithIndex: CELL_PAMF_ERROR_INVALID_ARG"); + return CELL_PAMF_ERROR_INVALID_ARG; } int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 streamType, u8 ch) @@ -311,8 +297,6 @@ int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - if (streamType > 5) { cellPamf->Error("cellPamfReaderSetStreamWithTypeAndChannel: invalid stream type(%d)", streamType); @@ -320,7 +304,7 @@ int cellPamfReaderSetStreamWithTypeAndChannel(vm::ptr pSelf, u8 return CELL_PAMF_ERROR_INVALID_ARG; } - for (u8 i = 0; i < pAddr->stream_count; i++) + for (u8 i = 0; i < pSelf->pAddr->stream_count; i++) { if (pamfGetStreamType(pSelf, i) == streamType) { @@ -343,11 +327,9 @@ int cellPamfReaderSetStreamWithTypeAndIndex(vm::ptr pSelf, u8 st return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - u32 found = 0; - for (u8 i = 0; i < pAddr->stream_count; i++) + for (u8 i = 0; i < pSelf->pAddr->stream_count; i++) { const u8 type = pamfGetStreamType(pSelf, i); @@ -426,8 +408,6 @@ int cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - memset(vm::get_ptr(pInfo_addr), 0, size); switch (pamfGetStreamType(pSelf, pSelf->stream)) @@ -486,7 +466,7 @@ int cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u case CELL_PAMF_STREAM_TYPE_AC3: { auto pInfo = vm::ptr::make(pInfo_addr); - auto pAudio = vm::ptr::make(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + auto pAudio = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); if (size != sizeof(CellPamfAc3Info)) { @@ -501,7 +481,7 @@ int cellPamfReaderGetStreamInfo(vm::ptr pSelf, u32 pInfo_addr, u case CELL_PAMF_STREAM_TYPE_PAMF_LPCM: { auto pInfo = vm::ptr::make(pInfo_addr); - auto pAudio = vm::ptr::make(pSelf->pAddr + 0x98 + pSelf->stream * 0x30); + auto pAudio = vm::ptr::make(pSelf->pAddr.addr() + 0x98 + pSelf->stream * 0x30); if (size != sizeof(CellPamfLpcmInfo)) { @@ -537,8 +517,7 @@ int cellPamfReaderGetNumberOfEp(vm::ptr pSelf) return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - return pAddr->stream_headers[pSelf->stream].ep_num; + return pSelf->pAddr->stream_headers[pSelf->stream].ep_num; } int cellPamfReaderGetEpIteratorWithIndex(vm::ptr pSelf, u32 epIndex, vm::ptr pIt) @@ -549,7 +528,6 @@ int cellPamfReaderGetEpIteratorWithIndex(vm::ptr pSelf, u32 epIn return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); //TODO: return CELL_OK; } @@ -562,8 +540,6 @@ int cellPamfReaderGetEpIteratorWithTimeStamp(vm::ptr pSelf, vm:: return CELL_PAMF_ERROR_INVALID_PAMF; } - vm::ptr pAddr(pSelf->pAddr); - //TODO: return CELL_OK; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 78c7054e82..86db920f9f 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -14,7 +14,7 @@ #include "Emu/SysCalls/lv2/sys_time.h" #include "Emu/SysCalls/lv2/sys_mmapper.h" #include "Emu/SysCalls/lv2/sys_lwcond.h" -#include "Loader/ELF.h" +#include "Loader/ELF32.h" #include "Crypto/unself.h" #include "Emu/Cell/RawSPUThread.h" #include "sysPrxForUser.h" @@ -130,11 +130,10 @@ int sys_raw_spu_load(s32 id, vm::ptr path, vm::ptr entry) f.Seek(0); - ELFLoader l(f); - l.LoadInfo(); - l.LoadData(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); + u32 _entry; + LoadSpuImage(f, _entry, RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * id); - *entry = l.GetEntry(); + *entry = _entry; return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp index 90e781ead1..9f550557c1 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_net.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_net.cpp @@ -96,7 +96,7 @@ int sys_net_accept(s32 s, vm::ptr addr, vm::ptr pad { sys_net->Warning("accept(s=%d, family_addr=0x%x, paddrlen=0x%x)", s, addr.addr(), paddrlen.addr()); if (!addr) { - int ret = accept(s, NULL, NULL); + int ret = accept(s, nullptr, nullptr); *g_lastError = getLastError(); return ret; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp index 53891b7565..ba0242383d 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_mmapper.cpp @@ -24,13 +24,13 @@ s32 sys_mmapper_allocate_address(u32 size, u64 flags, u32 alignment, u32 alloc_a { default: case SYS_MEMORY_PAGE_SIZE_1M: - if(AlignAddr(size, alignment) & 0xfffff) + if(align(size, alignment) & 0xfffff) return CELL_EALIGN; addr = (u32)Memory.Alloc(size, 0x100000); break; case SYS_MEMORY_PAGE_SIZE_64K: - if(AlignAddr(size, alignment) & 0xffff) + if (align(size, alignment) & 0xffff) return CELL_EALIGN; addr = (u32)Memory.Alloc(size, 0x10000); break; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index fb7772db2e..3249dd6cd4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -160,11 +160,11 @@ PPUThread* ppu_thread_create(u32 entry, u64 arg, s32 prio, u32 stacksize, bool i new_thread.m_has_interrupt = false; new_thread.m_is_interrupt = is_interrupt; new_thread.SetName(name); - new_thread.m_custom_task = task; + new_thread.custom_task = task; sys_ppu_thread.Notice("*** New PPU Thread [%s] (%s, entry=0x%x): id = %d", name.c_str(), is_interrupt ? "interrupt" : - (is_joinable ? "joinable" : "non-joinable"), entry, id); + (is_joinable ? "joinable" : "detached"), entry, id); if (!is_interrupt) { @@ -194,15 +194,13 @@ s32 sys_ppu_thread_create(vm::ptr thread_id, u32 entry, u64 arg, s32 prio, { case 0: break; case SYS_PPU_THREAD_CREATE_JOINABLE: - { is_joinable = true; break; - } + case SYS_PPU_THREAD_CREATE_INTERRUPT: - { is_interrupt = true; break; - } + default: sys_ppu_thread.Error("sys_ppu_thread_create(): unknown flags value (0x%llx)", flags); return CELL_EPERM; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp b/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp index 3f1ff87e22..efdb47f96c 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_prx.cpp @@ -34,10 +34,10 @@ s32 sys_prx_load_module(vm::ptr path, u64 flags, vm::ptrsize = (u32)f.GetSize(); prx->address = (u32)Memory.Alloc(prx->size, 4); - prx->path = path; + prx->path = (const char*)path; // Load the PRX into memory - f.Read(vm::get_ptr(prx->address), prx->size); + f.Read(vm::get_ptr(prx->address), prx->size); u32 id = sys_prx.GetNewId(prx, TYPE_PRX); return id; diff --git a/rpcs3/Emu/SysCalls/lv2/sys_prx.h b/rpcs3/Emu/SysCalls/lv2/sys_prx.h index e83daad0be..2e024c1bde 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_prx.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_prx.h @@ -28,11 +28,74 @@ enum CELL_PRX_ERROR_ELF_IS_REGISTERED = 0x80011910, // Fixed ELF is already registered }; +// Information about imported or exported libraries in PRX modules +struct sys_prx_library_info_t +{ + u8 size; + u8 unk0; + be_t version; + be_t attributes; + be_t num_func; + be_t num_var; + be_t num_tlsvar; + u8 info_hash; + u8 info_tlshash; + u8 unk1[2]; + be_t name_addr; + be_t fnid_addr; + be_t fstub_addr; + be_t unk4; + be_t unk5; + be_t unk6; + be_t unk7; +}; + +// ELF file headers +struct sys_prx_param_t +{ + be_t size; + be_t magic; + be_t version; + be_t unk0; + be_t libentstart; + be_t libentend; + vm::bptr libstubstart; + vm::bptr libstubend; + be_t ver; + be_t unk1; + be_t unk2; +}; + +// PRX file headers +struct sys_prx_module_info_t +{ + be_t attributes; + be_t version; + s8 name[28]; + be_t toc; + vm::bptr exports_start; + vm::bptr exports_end; + be_t imports_start; + be_t imports_end; +}; + +// Relocation information of the SCE_PPURELA segment +struct sys_prx_relocation_info_t +{ + be_t offset; + be_t unk0; + u8 index_value; + u8 index_addr; + be_t type; + vm::bptr ptr; +}; + + // Data types struct sys_prx_load_module_option_t { be_t size; - be_t base_addr; // void* + vm::bptr base_addr; }; struct sys_prx_start_module_option_t diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 4c7163f3d2..1f6a00bbdf 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -7,20 +7,26 @@ #include "Emu/Cell/RawSPUThread.h" #include "Emu/FS/vfsStreamMemory.h" #include "Emu/FS/vfsFile.h" -#include "Loader/ELF.h" +#include "Loader/elf32.h" #include "Crypto/unself.h" #include "sys_spu.h" static SysCallBase sys_spu("sys_spu"); +void LoadSpuImage(vfsStream& stream, u32& spu_ep, u32 addr) +{ + loader::handlers::elf32 h; + h.init(stream); + h.load_data(addr); + spu_ep = h.m_ehdr.data_be.e_entry; +} + u32 LoadSpuImage(vfsStream& stream, u32& spu_ep) { - ELFLoader l(stream); - l.LoadInfo(); const u32 alloc_size = 256 * 1024; - u32 spu_offset = (u32)Memory.MainMem.AllocAlign(alloc_size); - l.LoadData(spu_offset); - spu_ep = l.GetEntry(); + u32 spu_offset = (u32)vm::alloc(alloc_size, vm::main); + + LoadSpuImage(stream, spu_ep, spu_offset); return spu_offset; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index e9886b0e0d..a07e6d0ca3 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -154,6 +154,10 @@ struct SpuGroupInfo }; class SPUThread; +struct vfsStream; + +void LoadSpuImage(vfsStream& stream, u32& spu_ep, u32 addr); +u32 LoadSpuImage(vfsStream& stream, u32& spu_ep); // Aux s32 spu_image_import(sys_spu_image& img, u32 src, u32 type); diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e6c3ff9e3f..7c6919724f 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -57,6 +57,8 @@ Emulator::Emulator() , m_sync_prim_manager(new SyncPrimManager()) , m_vfs(new VFS()) { + m_loader.register_handler(new loader::handlers::elf32); + m_loader.register_handler(new loader::handlers::elf64); } Emulator::~Emulator() @@ -235,78 +237,13 @@ void Emulator::Load() return; } - bool is_error; - Loader l(f); - - try + if (!m_loader.load(f)) { - if(!(is_error = !l.Analyze())) - { - switch(l.GetMachine()) - { - case MACHINE_SPU: - Memory.Init(Memory_PS3); - Memory.MainMem.AllocFixed(Memory.MainMem.GetStartAddr(), 0x40000); - break; - - case MACHINE_PPC64: - Memory.Init(Memory_PS3); - break; - - case MACHINE_MIPS: - Memory.Init(Memory_PSP); - break; - - case MACHINE_ARM: - Memory.Init(Memory_PSV); - break; - - default: - throw std::string("Unknown machine!"); - } - - is_error = !l.Load(); - } - - } - catch(const std::string& e) - { - LOG_ERROR(LOADER, "%s", e.c_str()); - is_error = true; - } - catch(...) - { - LOG_ERROR(LOADER, "Unhandled loader error."); - is_error = true; - } - - CPUThreadType thread_type; - - if(!is_error) - { - switch(l.GetMachine()) - { - case MACHINE_PPC64: thread_type = CPU_THREAD_PPU; break; - case MACHINE_SPU: thread_type = CPU_THREAD_SPU; break; - case MACHINE_ARM: thread_type = CPU_THREAD_ARMv7; break; - - default: - LOG_ERROR(LOADER, "Unimplemented thread type for machine."); - is_error = true; - break; - } - } - - if(is_error) - { - Memory.Close(); - Stop(); + LOG_ERROR(LOADER, "Loading '%s' failed", m_elf_path.c_str()); + vm::close(); return; } - // setting default values - Emu.m_sdk_version = -1; // possibly "unknown" value - // trying to load some info from PARAM.SFO vfsFile f2("/app_home/PARAM.SFO"); if (f2.IsOpened()) @@ -326,83 +263,6 @@ void Emulator::Load() LoadPoints(BreakPointsDBName); - CPUThread& thread = GetCPU().AddThread(thread_type); - - switch(l.GetMachine()) - { - case MACHINE_SPU: - LOG_NOTICE(LOADER, "offset = 0x%llx", Memory.MainMem.GetStartAddr()); - LOG_NOTICE(LOADER, "max addr = 0x%x", l.GetMaxAddr()); - thread.SetOffset(Memory.MainMem.GetStartAddr()); - thread.SetEntry(l.GetEntry() - Memory.MainMem.GetStartAddr()); - thread.Run(); - break; - - case MACHINE_PPC64: - { - m_rsx_callback = (u32)Memory.MainMem.AllocAlign(4 * 4) + 4; - vm::write32(m_rsx_callback - 4, m_rsx_callback); - - auto callback_data = vm::ptr::make(m_rsx_callback); - callback_data[0] = ADDI(11, 0, 0x3ff); - callback_data[1] = SC(2); - callback_data[2] = BCLR(0x10 | 0x04, 0, 0, 0); - - m_ppu_thr_exit = (u32)Memory.MainMem.AllocAlign(4 * 4); - - auto ppu_thr_exit_data = vm::ptr::make(m_ppu_thr_exit); - //ppu_thr_exit_data += ADDI(3, 0, 0); // why it kills return value (GPR[3]) ? - ppu_thr_exit_data[0] = ADDI(11, 0, 41); - ppu_thr_exit_data[1] = SC(2); - ppu_thr_exit_data[2] = BCLR(0x10 | 0x04, 0, 0, 0); - - m_ppu_thr_stop = (u32)Memory.MainMem.AllocAlign(2 * 4); - - auto ppu_thr_stop_data = vm::ptr::make(m_ppu_thr_stop); - ppu_thr_stop_data[0] = SC(4); - ppu_thr_stop_data[1] = BCLR(0x10 | 0x04, 0, 0, 0); - - vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); - - thread.SetEntry(l.GetEntry()); - thread.SetStackSize(0x10000); - thread.SetPrio(0x50); - thread.Run(); - - u32 arg1 = Memory.MainMem.AllocAlign(m_elf_path.size() + 1 + 0x20, 0x10) + 0x20; - memcpy(vm::get_ptr(arg1), m_elf_path.c_str(), m_elf_path.size() + 1); - u32 argv = arg1 - 0x20; - vm::write64(argv, arg1); - - static_cast(thread).GPR[3] = 1; // arg count - static_cast(thread).GPR[4] = argv; // probably, args** - static_cast(thread).GPR[5] = argv + 0x10; // unknown - static_cast(thread).GPR[6] = 0; // unknown - static_cast(thread).GPR[12] = Emu.GetMallocPageSize(); // ??? - //thread.AddArgv("-emu"); - } - break; - - case MACHINE_ARM: - { - u32 entry = l.GetEntry(); - - auto code = vm::psv::ptr::make(entry & ~3); - - // evil way to find entry point in .sceModuleInfo.rodata - while (code[0] != 0xffffffffu) - { - entry = code[0] + 0x81000000; - code++; - } - - thread.SetEntry(entry & ~1); - thread.Run(); - - break; - } - } - m_status = Ready; GetGSManager().Init(); @@ -415,7 +275,6 @@ void Emulator::Load() void Emulator::Run() { - if(!IsReady()) { Load(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 05c8927eee..7a7aacff96 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -47,7 +47,8 @@ public: proc_param.malloc_pagesize = 0x100000; proc_param.sdk_version = 0x360001; - //TODO + proc_param.primary_stacksize = 0x100000; + proc_param.primary_prio = 0x50; } void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) @@ -106,6 +107,7 @@ class Emulator VFS* m_vfs; EmuInfo m_info; + loader::loader m_loader; public: std::string m_path; @@ -121,6 +123,11 @@ public: void SetPath(const std::string& path, const std::string& elf_path = ""); void SetTitleID(const std::string& id); + std::string GetPath() const + { + return m_elf_path; + } + std::recursive_mutex& GetCoreMutex() { return m_core_mutex; } CPUThreadManager& GetCPU() { return *m_thread_manager; } @@ -149,6 +156,21 @@ public: m_info.SetTLSData(addr, filesz, memsz); } + void SetRSXCallback(u32 addr) + { + m_rsx_callback = addr; + } + + void SetPPUThreadExit(u32 addr) + { + m_ppu_thr_exit = addr; + } + + void SetPPUThreadStop(u32 addr) + { + m_ppu_thr_stop = addr; + } + EmuInfo& GetInfo() { return m_info; } u64 GetTLSAddr() const { return m_info.GetTLSAddr(); } diff --git a/rpcs3/Gui/CompilerELF.cpp b/rpcs3/Gui/CompilerELF.cpp index c4254163e2..0dcd836eca 100644 --- a/rpcs3/Gui/CompilerELF.cpp +++ b/rpcs3/Gui/CompilerELF.cpp @@ -421,5 +421,5 @@ void CompilerELF::SetOpStyle(const std::string& text, const wxColour& color, boo void CompilerELF::DoAnalyzeCode(bool compile) { - CompilePPUProgram(fmt::ToUTF8(asm_list->GetValue()), "compiled.elf", asm_list, hex_list, err_list, !compile).Compile(); +// CompilePPUProgram(fmt::ToUTF8(asm_list->GetValue()), "compiled.elf", asm_list, hex_list, err_list, !compile).Compile(); } diff --git a/rpcs3/Gui/DisAsmFrame.cpp b/rpcs3/Gui/DisAsmFrame.cpp index e4c4fe2c17..c7c52acff9 100644 --- a/rpcs3/Gui/DisAsmFrame.cpp +++ b/rpcs3/Gui/DisAsmFrame.cpp @@ -1,4 +1,5 @@ #include "stdafx_gui.h" +#if 0 #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" @@ -512,3 +513,4 @@ void DisAsmFrame::MouseWheel(wxMouseEvent& event) event.Skip(); } +#endif \ No newline at end of file diff --git a/rpcs3/Gui/DisAsmFrame.h b/rpcs3/Gui/DisAsmFrame.h index 0f9f30b271..4e2bf0b3b9 100644 --- a/rpcs3/Gui/DisAsmFrame.h +++ b/rpcs3/Gui/DisAsmFrame.h @@ -1,5 +1,5 @@ #pragma once - +#if 0 class PPCThread; class DisAsmFrame : public wxFrame @@ -31,4 +31,6 @@ public: } virtual void AddLine(const wxString line); -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/rpcs3/Gui/LLEModulesManager.cpp b/rpcs3/Gui/LLEModulesManager.cpp new file mode 100644 index 0000000000..387e0e6433 --- /dev/null +++ b/rpcs3/Gui/LLEModulesManager.cpp @@ -0,0 +1,65 @@ +#include "stdafx_gui.h" +#include "Utilities/Log.h" +#include "Loader/ELF64.h" +#include "Emu/FS/vfsDir.h" +#include "Emu/FS/vfsFile.h" +#include "LLEModulesManager.h" +#include "Emu/System.h" +#include "Emu/FS/VFS.h" + +LLEModulesManagerFrame::LLEModulesManagerFrame(wxWindow* parent) : FrameBase(parent, wxID_ANY, "", "LLEModulesManagerFrame", wxSize(800, 600)) +{ + wxBoxSizer *s_panel = new wxBoxSizer(wxVERTICAL); + wxBoxSizer *s_p_panel = new wxBoxSizer(wxVERTICAL); + wxPanel *p_main = new wxPanel(this); + m_check_list = new wxCheckListBox(p_main, wxID_ANY); + s_p_panel->Add(m_check_list, 0, wxEXPAND | wxALL, 5); + p_main->SetSizerAndFit(s_p_panel); + s_panel->Add(p_main, 0, wxEXPAND | wxALL, 5); + SetSizerAndFit(s_panel); + + Refresh(); + //Bind(wxEVT_CHECKLISTBOX, [this](wxCommandEvent& event) { UpdateSelection(); }); + Bind(wxEVT_SIZE, [p_main, this](wxSizeEvent& event) { p_main->SetSize(GetClientSize()); m_check_list->SetSize(p_main->GetClientSize() - wxSize(10, 10)); }); +} + +void LLEModulesManagerFrame::Refresh() +{ + m_check_list->Clear(); + + std::string path = "/dev_flash/sys/external/"; + + Emu.GetVFS().Init(path); + + vfsDir dir(path); + + loader::handlers::elf64 sprx_loader; + for (const DirEntryInfo* info = dir.Read(); info; info = dir.Read()) + { + if (info->flags & DirEntry_TypeFile) + { + vfsFile f(path + info->name); + if (sprx_loader.init(f) != loader::handler::ok) + { + continue; + } + + if (!sprx_loader.is_sprx()) + { + continue; + } + + sprx_loader.load(); + + m_check_list->Check(m_check_list->Append(sprx_loader.sprx_get_module_name() + + " v" + std::to_string((int)sprx_loader.m_sprx_module_info.version[0]) + "." + std::to_string((int)sprx_loader.m_sprx_module_info.version[1]))); + } + } + + Emu.GetVFS().UnMountAll(); +} + +void LLEModulesManagerFrame::UpdateSelection() +{ + +} \ No newline at end of file diff --git a/rpcs3/Gui/LLEModulesManager.h b/rpcs3/Gui/LLEModulesManager.h new file mode 100644 index 0000000000..f6344bba3b --- /dev/null +++ b/rpcs3/Gui/LLEModulesManager.h @@ -0,0 +1,13 @@ +#pragma once +#include "Gui/FrameBase.h" +#include + +class LLEModulesManagerFrame : public FrameBase +{ + wxCheckListBox *m_check_list; + +public: + LLEModulesManagerFrame(wxWindow *parent); + void Refresh(); + void UpdateSelection(); +}; \ No newline at end of file diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index b3e5da35ad..a21acdb18d 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -20,6 +20,7 @@ #include "Gui/KernelExplorer.h" #include "Gui/MemoryViewer.h" #include "Gui/RSXDebugger.h" +#include "Gui/LLEModulesManager.h" #include @@ -44,6 +45,7 @@ enum IDs id_config_vhdd_manager, id_config_autopause_manager, id_config_savedata_manager, + id_config_lle_modules_manager, id_tools_compiler, id_tools_kernel_explorer, id_tools_memory_viewer, @@ -98,6 +100,8 @@ MainFrame::MainFrame() menu_conf->Append(id_config_vfs_manager, "Virtual File System Manager"); menu_conf->Append(id_config_vhdd_manager, "Virtual HDD Manager"); menu_conf->Append(id_config_savedata_manager, "Save Data Utility"); + menu_conf->Append(id_config_lle_modules_manager, "LLE Modules Manager"); + wxMenu* menu_tools = new wxMenu(); menubar->Append(menu_tools, "Tools"); @@ -137,6 +141,7 @@ MainFrame::MainFrame() Bind(wxEVT_MENU, &MainFrame::ConfigVHDD, this, id_config_vhdd_manager); Bind(wxEVT_MENU, &MainFrame::ConfigAutoPause, this, id_config_autopause_manager); Bind(wxEVT_MENU, &MainFrame::ConfigSaveData, this, id_config_savedata_manager); + Bind(wxEVT_MENU, &MainFrame::ConfigLLEModules, this, id_config_lle_modules_manager); Bind(wxEVT_MENU, &MainFrame::OpenELFCompiler, this, id_tools_compiler); Bind(wxEVT_MENU, &MainFrame::OpenKernelExplorer, this, id_tools_kernel_explorer); @@ -673,6 +678,11 @@ void MainFrame::ConfigSaveData(wxCommandEvent& event) SaveDataListDialog(this, true).ShowModal(); } +void MainFrame::ConfigLLEModules(wxCommandEvent& event) +{ + (new LLEModulesManagerFrame(this))->Show(); +} + void MainFrame::OpenELFCompiler(wxCommandEvent& WXUNUSED(event)) { (new CompilerELF(this)) -> Show(); diff --git a/rpcs3/Gui/MainFrame.h b/rpcs3/Gui/MainFrame.h index 3e1b625048..359e932c6a 100644 --- a/rpcs3/Gui/MainFrame.h +++ b/rpcs3/Gui/MainFrame.h @@ -40,6 +40,7 @@ private: void ConfigVHDD(wxCommandEvent& event); void ConfigAutoPause(wxCommandEvent& event); void ConfigSaveData(wxCommandEvent& event); + void ConfigLLEModules(wxCommandEvent& event); void OpenELFCompiler(wxCommandEvent& evt); void OpenKernelExplorer(wxCommandEvent& evt); void OpenMemoryViewer(wxCommandEvent& evt); diff --git a/rpcs3/Loader/ELF.cpp b/rpcs3/Loader/ELF.cpp deleted file mode 100644 index b3708bf910..0000000000 --- a/rpcs3/Loader/ELF.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "stdafx.h" -#include "Emu/FS/vfsStream.h" -#include "ELF.h" -#include "ELF64.h" -#include "ELF32.h" - -void Elf_Ehdr::Show() -{ -} - -void Elf_Ehdr::Load(vfsStream& f) -{ - e_magic = Read32(f); - e_class = Read8(f); -} - -ELFLoader::ELFLoader(vfsStream& f) - : m_elf_file(f) - , LoaderBase() - , m_loader(nullptr) -{ -} - -bool ELFLoader::LoadInfo() -{ - if(!m_elf_file.IsOpened()) - return false; - - m_elf_file.Seek(0); - ehdr.Load(m_elf_file); - if(!ehdr.CheckMagic()) - return false; - - switch(ehdr.GetClass()) - { - case CLASS_ELF32: - m_loader = new ELF32Loader(m_elf_file); - break; - case CLASS_ELF64: - m_loader = new ELF64Loader(m_elf_file); - break; - } - - if(!(m_loader && m_loader->LoadInfo())) - return false; - - entry = m_loader->GetEntry(); - machine = m_loader->GetMachine(); - - return true; -} - -bool ELFLoader::LoadData(u64 offset) -{ - return m_loader && m_loader->LoadData(offset); -} - -bool ELFLoader::Close() -{ - delete m_loader; - m_loader = nullptr; - return m_elf_file.Close(); -} diff --git a/rpcs3/Loader/ELF.h b/rpcs3/Loader/ELF.h deleted file mode 100644 index 44b888b9ff..0000000000 --- a/rpcs3/Loader/ELF.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "Loader.h" - -struct vfsStream; - -enum ElfClass -{ - CLASS_Unknown, - CLASS_ELF32, - CLASS_ELF64, -}; - -struct Elf_Ehdr -{ - u32 e_magic; - u8 e_class; - - virtual void Show(); - - virtual void Load(vfsStream& f); - - bool CheckMagic() const { return e_magic == 0x7F454C46; } - - ElfClass GetClass() const - { - switch(e_class) - { - case 1: return CLASS_ELF32; - case 2: return CLASS_ELF64; - } - - return CLASS_Unknown; - } -}; - -class ELFLoader : public LoaderBase -{ - vfsStream& m_elf_file; - LoaderBase* m_loader; - -public: - Elf_Ehdr ehdr; - - ELFLoader(vfsStream& f); - virtual ~ELFLoader() - { - Close(); - } - - virtual bool LoadInfo(); - 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 1d35143e01..aa8d7d2dd3 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -3,623 +3,127 @@ #include "Utilities/rFile.h" #include "Emu/FS/vfsStream.h" #include "Emu/Memory/Memory.h" -#include "Emu/ARMv7/PSVFuncList.h" #include "ELF32.h" +#include "Emu/Cell/SPUThread.h" +#include "Emu/ARMv7/ARMv7Thread.h" +#include "Emu/System.h" -//#define LOADER_DEBUG - -void Elf32_Ehdr::Show() +namespace loader { -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Magic: %08x", e_magic); - LOG_NOTICE(LOADER, "Class: %s", "ELF32"); - LOG_NOTICE(LOADER, "Data: %s", Ehdr_DataToString(e_data).c_str()); - LOG_NOTICE(LOADER, "Current Version: %d", e_curver); - LOG_NOTICE(LOADER, "OS/ABI: %s", Ehdr_OS_ABIToString(e_os_abi).c_str()); - LOG_NOTICE(LOADER, "ABI version: %lld", e_abi_ver); - LOG_NOTICE(LOADER, "Type: %s", Ehdr_TypeToString(e_type).c_str()); - LOG_NOTICE(LOADER, "Machine: %s", Ehdr_MachineToString(e_machine).c_str()); - LOG_NOTICE(LOADER, "Version: %d", e_version); - LOG_NOTICE(LOADER, "Entry point address: 0x%x", e_entry); - LOG_NOTICE(LOADER, "Program headers offset: 0x%08x", e_phoff); - LOG_NOTICE(LOADER, "Section headers offset: 0x%08x", e_shoff); - LOG_NOTICE(LOADER, "Flags: 0x%x", e_flags); - LOG_NOTICE(LOADER, "Size of this header: %d", e_ehsize); - LOG_NOTICE(LOADER, "Size of program headers: %d", e_phentsize); - LOG_NOTICE(LOADER, "Number of program headers: %d", e_phnum); - LOG_NOTICE(LOADER, "Size of section headers: %d", e_shentsize); - LOG_NOTICE(LOADER, "Number of section headers: %d", e_shnum); - LOG_NOTICE(LOADER, "Section header string table index: %d", e_shstrndx); -#endif -} - -void Elf32_Ehdr::Load(vfsStream& f) -{ - e_magic = Read32(f); - e_class = Read8(f); - e_data = Read8(f); - e_curver = Read8(f); - e_os_abi = Read8(f); - - if(IsLittleEndian()) + namespace handlers { - e_abi_ver = Read64LE(f); - e_type = Read16LE(f); - e_machine = Read16LE(f); - e_version = Read32LE(f); - e_entry = Read32LE(f); - e_phoff = Read32LE(f); - e_shoff = Read32LE(f); - e_flags = Read32LE(f); - e_ehsize = Read16LE(f); - e_phentsize = Read16LE(f); - e_phnum = Read16LE(f); - e_shentsize = Read16LE(f); - e_shnum = Read16LE(f); - e_shstrndx = Read16LE(f); - } - else - { - e_abi_ver = Read64(f); - e_type = Read16(f); - e_machine = Read16(f); - e_version = Read32(f); - e_entry = Read32(f); - e_phoff = Read32(f); - e_shoff = Read32(f); - e_flags = Read32(f); - e_ehsize = Read16(f); - e_phentsize = Read16(f); - e_phnum = Read16(f); - e_shentsize = Read16(f); - e_shnum = Read16(f); - e_shstrndx = Read16(f); - } -} - -void Elf32_Desc::Load(vfsStream& f) -{ - revision = Read32(f); - ls_size = Read32(f); - stack_size = Read32(f); - flags = Read32(f); -} - -void Elf32_Desc::LoadLE(vfsStream& f) -{ - revision = Read32LE(f); - ls_size = Read32LE(f); - stack_size = Read32LE(f); - flags = Read32LE(f); -} - -void Elf32_Note::Load(vfsStream& f) -{ - namesz = Read32(f); - descsz = Read32(f); - type = Read32(f); - f.Read(name, 8); - - if (descsz == 32) - { - f.Read(desc_text, descsz); - } - else - { - desc.Load(f); - } -} - -void Elf32_Note::LoadLE(vfsStream& f) -{ - namesz = Read32LE(f); - descsz = Read32LE(f); - type = Read32LE(f); - f.Read(name, 8); - - if (descsz == 32) - { - f.Read(desc_text, descsz); - } - else - { - desc.Load(f); - } -} - -void Elf32_Shdr::Load(vfsStream& f) -{ - sh_name = Read32(f); - sh_type = Read32(f); - sh_flags = Read32(f); - sh_addr = Read32(f); - sh_offset = Read32(f); - sh_size = Read32(f); - sh_link = Read32(f); - sh_info = Read32(f); - sh_addralign = Read32(f); - sh_entsize = Read32(f); -} - -void Elf32_Shdr::LoadLE(vfsStream& f) -{ - sh_name = Read32LE(f); - sh_type = Read32LE(f); - sh_flags = Read32LE(f); - sh_addr = Read32LE(f); - sh_offset = Read32LE(f); - sh_size = Read32LE(f); - sh_link = Read32LE(f); - sh_info = Read32LE(f); - sh_addralign = Read32LE(f); - sh_entsize = Read32LE(f); -} - -void Elf32_Shdr::Show() -{ -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Name offset: 0x%x", sh_name); - LOG_NOTICE(LOADER, "Type: 0x%d", sh_type); - LOG_NOTICE(LOADER, "Addr: 0x%x", sh_addr); - LOG_NOTICE(LOADER, "Offset: 0x%x", sh_offset); - LOG_NOTICE(LOADER, "Size: 0x%x", sh_size); - LOG_NOTICE(LOADER, "EntSize: %d", sh_entsize); - LOG_NOTICE(LOADER, "Flags: 0x%x", sh_flags); - LOG_NOTICE(LOADER, "Link: 0x%x", sh_link); - LOG_NOTICE(LOADER, "Info: %d", sh_info); - LOG_NOTICE(LOADER, "Address align: 0x%x", sh_addralign); -#endif -} - -void Elf32_Phdr::Load(vfsStream& f) -{ - p_type = Read32(f); - p_offset = Read32(f); - p_vaddr = Read32(f); - p_paddr = Read32(f); - p_filesz = Read32(f); - p_memsz = Read32(f); - p_flags = Read32(f); - p_align = Read32(f); -} - -void Elf32_Phdr::LoadLE(vfsStream& f) -{ - p_type = Read32LE(f); - p_offset = Read32LE(f); - p_vaddr = Read32LE(f); - p_paddr = Read32LE(f); - p_filesz = Read32LE(f); - p_memsz = Read32LE(f); - p_flags = Read32LE(f); - p_align = Read32LE(f); -} - -void Elf32_Phdr::Show() -{ -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Type: %s", Phdr_TypeToString(p_type).c_str()); - LOG_NOTICE(LOADER, "Offset: 0x%08x", p_offset); - LOG_NOTICE(LOADER, "Virtual address: 0x%08x", p_vaddr); - LOG_NOTICE(LOADER, "Physical address: 0x%08x", p_paddr); - LOG_NOTICE(LOADER, "File size: 0x%08x", p_filesz); - LOG_NOTICE(LOADER, "Memory size: 0x%08x", p_memsz); - LOG_NOTICE(LOADER, "Flags: %s", Phdr_FlagsToString(p_flags).c_str()); - LOG_NOTICE(LOADER, "Align: 0x%x", p_align); -#endif -} - -void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr) -{ - Write32(f, ehdr.e_magic); - Write8(f, ehdr.e_class); - Write8(f, ehdr.e_data); - Write8(f, ehdr.e_curver); - Write8(f, ehdr.e_os_abi); - Write64(f, ehdr.e_abi_ver); - Write16(f, ehdr.e_type); - Write16(f, ehdr.e_machine); - Write32(f, ehdr.e_version); - Write32(f, ehdr.e_entry); - Write32(f, ehdr.e_phoff); - Write32(f, ehdr.e_shoff); - Write32(f, ehdr.e_flags); - Write16(f, ehdr.e_ehsize); - Write16(f, ehdr.e_phentsize); - Write16(f, ehdr.e_phnum); - Write16(f, ehdr.e_shentsize); - Write16(f, ehdr.e_shnum); - Write16(f, ehdr.e_shstrndx); -} - -void WritePhdr(rFile& f, Elf32_Phdr& phdr) -{ - Write32(f, phdr.p_type); - Write32(f, phdr.p_offset); - Write32(f, phdr.p_vaddr); - Write32(f, phdr.p_paddr); - Write32(f, phdr.p_filesz); - Write32(f, phdr.p_memsz); - Write32(f, phdr.p_flags); - Write32(f, phdr.p_align); -} - -void WriteShdr(rFile& f, Elf32_Shdr& shdr) -{ - Write32(f, shdr.sh_name); - Write32(f, shdr.sh_type); - Write32(f, shdr.sh_flags); - Write32(f, shdr.sh_addr); - Write32(f, shdr.sh_offset); - Write32(f, shdr.sh_size); - Write32(f, shdr.sh_link); - Write32(f, shdr.sh_info); - Write32(f, shdr.sh_addralign); - Write32(f, shdr.sh_entsize); -} - -ELF32Loader::ELF32Loader(vfsStream& f) - : elf32_f(f) - , LoaderBase() -{ -} - -bool ELF32Loader::LoadInfo() -{ - if(!elf32_f.IsOpened()) return false; - - if(!LoadEhdrInfo()) return false; - if(!LoadPhdrInfo()) return false; - if(!LoadShdrInfo()) return false; - - return true; -} - -bool ELF32Loader::LoadData(u64 offset) -{ - if(!elf32_f.IsOpened()) return false; - - if(!LoadEhdrData(offset)) return false; - if(!LoadPhdrData(offset)) return false; - if(!LoadShdrData(offset)) return false; - - return true; -} - -bool ELF32Loader::Close() -{ - return elf32_f.Close(); -} - -bool ELF32Loader::LoadEhdrInfo() -{ - elf32_f.Seek(0); - ehdr.Load(elf32_f); - - if(!ehdr.CheckMagic()) return false; - - if(ehdr.IsLittleEndian()) - LOG_WARNING(LOADER, "ELF32 LE"); - - switch(ehdr.e_machine) - { - case MACHINE_MIPS: - case MACHINE_PPC64: - case MACHINE_SPU: - case MACHINE_ARM: - machine = (Elf_Machine)ehdr.e_machine; - break; - - default: - machine = MACHINE_Unknown; - LOG_ERROR(LOADER, "Unknown elf32 machine: 0x%x", ehdr.e_machine); - return false; - } - - entry = ehdr.GetEntry(); - if(entry == 0) - { - LOG_ERROR(LOADER, "elf32 error: entry is null!"); - return false; - } - - return true; -} - -bool ELF32Loader::LoadPhdrInfo() -{ - if(ehdr.e_phoff == 0 && ehdr.e_phnum) - { - LOG_ERROR(LOADER, "LoadPhdr32 error: Program header offset is null!"); - return false; - } - - elf32_f.Seek(ehdr.e_phoff); - for(uint i=0; i= entry && entry < phdr_arr[i].p_paddr + phdr_arr[i].p_memsz) + error_code res = handler::init(stream); + + if (res != ok) + return res; + + m_stream->Read(&m_ehdr, sizeof(ehdr)); + + if (!m_ehdr.check()) { - entry += phdr_arr[i].p_vaddr; - LOG_WARNING(LOADER, "virtual entry = 0x%x", entry); - break; - } - } - } - - return true; -} - -bool ELF32Loader::LoadShdrInfo() -{ - elf32_f.Seek(ehdr.e_shoff); - for(u32 i=0; i= shdr_arr.size()) - { - LOG_WARNING(LOADER, "LoadShdr32 error: shstrndx too big!"); - return true; - } - - for(u32 i=0; i max_addr) + if (m_ehdr.data_le.e_phnum && (m_ehdr.is_le() ? m_ehdr.data_le.e_phentsize : m_ehdr.data_be.e_phentsize) != sizeof(phdr)) { - max_addr = phdr_arr[i].p_vaddr + phdr_arr[i].p_memsz; + return broken_file; } - if(phdr_arr[i].p_vaddr != phdr_arr[i].p_paddr) + if (m_ehdr.data_le.e_shnum && (m_ehdr.is_le() ? m_ehdr.data_le.e_shentsize : m_ehdr.data_be.e_shentsize) != sizeof(shdr)) { - LOG_WARNING - ( - LOADER, - "LoadPhdr32 different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x", - phdr_arr[i].p_paddr, phdr_arr[i].p_vaddr - ); + return broken_file; } - switch(machine) + LOG_ERROR(LOADER, "m_ehdr.e_type = 0x%x", (u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_type : m_ehdr.data_be.e_type)); + + if (m_ehdr.data_le.e_phnum) { - case MACHINE_SPU: break; - case MACHINE_MIPS: Memory.PSP.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; - case MACHINE_ARM: Memory.PSV.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; - - default: - continue; - } - - elf32_f.Seek(phdr_arr[i].p_offset); - elf32_f.Read(vm::get_ptr(phdr_arr[i].p_vaddr + offset), phdr_arr[i].p_filesz); - } - else if(phdr_arr[i].p_type == 0x00000004) - { - elf32_f.Seek(phdr_arr[i].p_offset); - Elf32_Note note; - if(ehdr.IsLittleEndian()) note.LoadLE(elf32_f); - else note.Load(elf32_f); - - if(note.type != 1) - { - LOG_ERROR(LOADER, "ELF32: Bad NOTE type (%d)", note.type); - break; - } - - if(note.namesz != sizeof(note.name)) - { - LOG_ERROR(LOADER, "ELF32: Bad NOTE namesz (%d)", note.namesz); - break; - } - - if(note.descsz != sizeof(note.desc) && note.descsz != 32) - { - LOG_ERROR(LOADER, "ELF32: Bad NOTE descsz (%d)", note.descsz); - break; - } - - //if(note.desc.flags) - //{ - // LOG_ERROR(LOADER, "ELF32: Bad NOTE flags (0x%x)", note.desc.flags); - // break; - //} - - if(note.descsz == sizeof(note.desc)) - { - LOG_WARNING(LOADER, "name = %s", std::string((const char *)note.name, 8).c_str()); - LOG_WARNING(LOADER, "ls_size = %d", note.desc.ls_size); - LOG_WARNING(LOADER, "stack_size = %d", note.desc.stack_size); + m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum); + m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_phoff : m_ehdr.data_be.e_phoff)); + size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr); + if (m_stream->Read(m_phdrs.data(), size) != size) + return broken_file; } else + m_phdrs.clear(); + + if (m_ehdr.data_le.e_shnum) { - LOG_WARNING(LOADER, "desc = '%s'", std::string(note.desc_text, 32).c_str()); + m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum); + m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_shoff : m_ehdr.data_be.e_shoff)); + size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr); + + if (m_stream->Read(m_shdrs.data(), size) != size) + return broken_file; } - } -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, ""); -#endif - } + else + m_shdrs.clear(); - return true; -} - -bool ELF32Loader::LoadShdrData(u64 offset) -{ - u32 fnid_addr = 0; - - for(u32 i=0; i max_addr) + handler::error_code elf32::load() { - max_addr = shdr.sh_addr + shdr.sh_size; - } - - // probably should be in LoadPhdrData() - if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceFNID.rodata")) - { - fnid_addr = shdr.sh_addr; - } - else if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceFStub.rodata")) - { - list_known_psv_modules(); - - auto fnid = vm::psv::ptr::make(fnid_addr); - auto fstub = vm::psv::ptr::make(shdr.sh_addr); - - for (u32 j = 0; j < shdr.sh_size / 4; j++) + Elf_Machine machine; + switch (machine = (Elf_Machine)(u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_machine : m_ehdr.data_be.e_machine)) { - u32 nid = fnid[j]; - u32 addr = fstub[j]; + case MACHINE_MIPS: vm::psp::init(); break; + case MACHINE_ARM: vm::psv::init(); break; + case MACHINE_SPU: vm::ps3::init(); break; - if (auto func = get_psv_func_by_nid(nid)) + default: + return bad_version; + } + + error_code res = load_data(0); + + if (res != ok) + return res; + + switch (machine) + { + case MACHINE_MIPS: break; + case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; + case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; + } + + return ok; + } + + handler::error_code elf32::load_data(u32 offset) + { + for (auto &phdr : m_phdrs) + { + u32 memsz = m_ehdr.is_le() ? phdr.data_le.p_memsz : phdr.data_be.p_memsz; + u32 filesz = m_ehdr.is_le() ? phdr.data_le.p_filesz : phdr.data_be.p_filesz; + u32 vaddr = offset + (m_ehdr.is_le() ? phdr.data_le.p_vaddr : phdr.data_be.p_vaddr); + u32 offset = m_ehdr.is_le() ? phdr.data_le.p_offset : phdr.data_be.p_offset; + + switch (m_ehdr.is_le() ? phdr.data_le.p_type : phdr.data_be.p_type) { - if (func->module) - func->module->Notice("Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); - else - LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); + case 0x00000001: //LOAD + if (phdr.data_le.p_memsz) + { + if (!vm::alloc(vaddr, memsz, vm::main)) + { + LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz); - // writing Thumb code (temporarily, because it should be ARM) - vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function) - vm::psv::write16(addr + 2, (u16)get_psv_func_index(func)); - vm::psv::write16(addr + 4, 0x4770); // BX LR - vm::psv::write16(addr + 6, 0); // null - } - else - { - LOG_ERROR(LOADER, "Unimplemented function 0x%08x (addr=0x%x)", nid, addr); + return loading_error; + } - vm::psv::write16(addr + 0, 0xf870); // HACK (special instruction that calls HLE function) - vm::psv::write16(addr + 2, 0x0000); // (zero index) - vm::psv::write16(addr + 4, 0x4770); // BX LR - vm::psv::write16(addr + 6, 0); // null + if (filesz) + { + m_stream->Seek(handler::get_stream_offset() + offset); + m_stream->Read(vm::get_ptr(vaddr), filesz); + } + } + break; } } - } - else if (machine == MACHINE_ARM && !strcmp(shdr_name_arr[i].c_str(), ".sceRefs.rodata")) - { - auto code = vm::psv::ptr::make(shdr.sh_addr); - u32 data = 0; - for (; code.addr() < shdr.sh_addr + shdr.sh_size; code++) - { - switch (*code) - { - case 0x000000ff: - { - // save address for future use - data = *++code; - break; - } - case 0x0000002f: - { - // movw r12,# instruction will be replaced - const u32 addr = *++code; - vm::psv::write16(addr + 0, 0xf240 | (data & 0x800) >> 1 | (data & 0xf000) >> 12); // MOVW - vm::psv::write16(addr + 2, 0x0c00 | (data & 0x700) << 4 | (data & 0xff)); - break; - } - case 0x00000030: - { - // movt r12,# instruction will be replaced - const u32 addr = *++code; - vm::psv::write16(addr + 0, 0xf2c0 | (data & 0x8000000) >> 17 | (data & 0xf0000000) >> 28); // MOVT - vm::psv::write16(addr + 2, 0x0c00 | (data & 0x7000000) >> 12 | (data & 0xff0000) >> 16); - break; - } - case 0x00000000: - { - // probably, no operation - break; - } - default: LOG_NOTICE(LOADER, "sceRefs: unknown code found (0x%08x)", *code); - } - } + return ok; } } - - //TODO - return true; -} +} \ No newline at end of file diff --git a/rpcs3/Loader/ELF32.h b/rpcs3/Loader/ELF32.h index 1d573824d3..dc37dd5f0b 100644 --- a/rpcs3/Loader/ELF32.h +++ b/rpcs3/Loader/ELF32.h @@ -4,135 +4,137 @@ struct vfsStream; class rFile; -struct Elf32_Ehdr +namespace loader { - u32 e_magic; - u8 e_class; - u8 e_data; - u8 e_curver; - u8 e_os_abi; - u64 e_abi_ver; - u16 e_type; - u16 e_machine; - u32 e_version; - u32 e_entry; - u32 e_phoff; - u32 e_shoff; - u32 e_flags; - u16 e_ehsize; - u16 e_phentsize; - u16 e_phnum; - u16 e_shentsize; - u16 e_shnum; - u16 e_shstrndx; - - void Show(); - - bool IsLittleEndian() const + namespace handlers { - return e_data == 1; + class elf32 : public handler + { + public: + struct ehdr + { + u32 e_magic; + u8 e_class; + u8 e_data; + u8 e_curver; + u8 e_os_abi; + + union + { + struct + { + u64 e_abi_ver; + u16 e_type; + u16 e_machine; + u32 e_version; + u16 e_entry; + u32 e_phoff; + u32 e_shoff; + u32 e_flags; + u16 e_ehsize; + u16 e_phentsize; + u16 e_phnum; + u16 e_shentsize; + u16 e_shnum; + u16 e_shstrndx; + } data_le; + + struct + { + be_t e_abi_ver; + be_t e_type; + be_t e_machine; + be_t e_version; + be_t e_entry; + be_t e_phoff; + be_t e_shoff; + be_t e_flags; + be_t e_ehsize; + be_t e_phentsize; + be_t e_phnum; + be_t e_shentsize; + be_t e_shnum; + be_t e_shstrndx; + } data_be; + }; + + bool is_le() const { return e_data == 1; } + bool check() const { return e_magic == 0x7F454C46; } + }; + + struct shdr + { + union + { + struct + { + u32 sh_name; + u32 sh_type; + u32 sh_flags; + u32 sh_addr; + u32 sh_offset; + u32 sh_size; + u32 sh_link; + u32 sh_info; + u32 sh_addralign; + u32 sh_entsize; + } data_le; + + struct + { + be_t sh_name; + be_t sh_type; + be_t sh_flags; + be_t sh_addr; + be_t sh_offset; + be_t sh_size; + be_t sh_link; + be_t sh_info; + be_t sh_addralign; + be_t sh_entsize; + } data_be; + }; + }; + + struct phdr + { + union + { + struct + { + u32 p_type; + u32 p_offset; + u32 p_vaddr; + u32 p_paddr; + u32 p_filesz; + u32 p_memsz; + u32 p_flags; + u32 p_align; + } data_le; + + struct + { + be_t p_type; + be_t p_offset; + be_t p_vaddr; + be_t p_paddr; + be_t p_filesz; + be_t p_memsz; + be_t p_flags; + be_t p_align; + } data_be; + }; + }; + + ehdr m_ehdr; + std::vector m_phdrs; + std::vector m_shdrs; + + error_code init(vfsStream& stream) override; + error_code load() override; + error_code load_data(u32 offset); + + virtual ~elf32() = default; + }; } - - void Load(vfsStream& f); - - bool CheckMagic() const { return e_magic == 0x7F454C46; } - u32 GetEntry() const { return e_entry; } -}; - -struct Elf32_Desc -{ - u32 revision; - u32 ls_size; - u32 stack_size; - u32 flags; - - void Load(vfsStream& f); - - void LoadLE(vfsStream& f); -}; - -struct Elf32_Note -{ - u32 namesz; - u32 descsz; - u32 type; - u8 name[8]; - union - { - Elf32_Desc desc; - char desc_text[32]; - }; - - void Load(vfsStream& f); - - void LoadLE(vfsStream& f); -}; - -struct Elf32_Shdr -{ - u32 sh_name; - u32 sh_type; - u32 sh_flags; - u32 sh_addr; - u32 sh_offset; - u32 sh_size; - u32 sh_link; - u32 sh_info; - u32 sh_addralign; - u32 sh_entsize; - - void Load(vfsStream& f); - - void LoadLE(vfsStream& f); - - void Show(); -}; - -struct Elf32_Phdr -{ - u32 p_type; - u32 p_offset; - u32 p_vaddr; - u32 p_paddr; - u32 p_filesz; - u32 p_memsz; - u32 p_flags; - u32 p_align; - - void Load(vfsStream& f); - - void LoadLE(vfsStream& f); - - void Show(); -}; - -class ELF32Loader : public LoaderBase -{ - vfsStream& elf32_f; - -public: - Elf32_Ehdr ehdr; - std::vector shdr_name_arr; - std::vector shdr_arr; - std::vector phdr_arr; - - ELF32Loader(vfsStream& f); - ~ELF32Loader() {Close();} - - virtual bool LoadInfo(); - virtual bool LoadData(u64 offset); - virtual bool Close(); - -private: - bool LoadEhdrInfo(); - bool LoadPhdrInfo(); - bool LoadShdrInfo(); - - bool LoadEhdrData(u64 offset); - bool LoadPhdrData(u64 offset); - bool LoadShdrData(u64 offset); -}; - -void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr); -void WritePhdr(rFile& f, Elf32_Phdr& phdr); -void WriteShdr(rFile& f, Elf32_Shdr& shdr); +} diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 119a4913b9..40e2b80a4d 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -2,555 +2,489 @@ #include "Utilities/Log.h" #include "Utilities/rFile.h" #include "Emu/FS/vfsStream.h" +#include "Emu/FS/vfsFile.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/Static.h" -#include "Emu/Cell/PPUInstrTable.h" #include "Emu/SysCalls/ModuleManager.h" +#include "Emu/SysCalls/lv2/sys_prx.h" +#include "Emu/Cell/PPUInstrTable.h" +#include "Emu/CPU/CPUThreadManager.h" #include "ELF64.h" using namespace PPU_instr; -void Elf64_Ehdr::Load(vfsStream& f) +namespace loader { - e_magic = Read32(f); - e_class = Read8(f); - e_data = Read8(f); - e_curver = Read8(f); - e_os_abi = Read8(f); - e_abi_ver = Read64(f); - e_type = Read16(f); - e_machine = Read16(f); - e_version = Read32(f); - e_entry = Read64(f); - e_phoff = Read64(f); - e_shoff = Read64(f); - e_flags = Read32(f); - e_ehsize = Read16(f); - e_phentsize = Read16(f); - e_phnum = Read16(f); - e_shentsize = Read16(f); - e_shnum = Read16(f); - e_shstrndx = Read16(f); -} - -void Elf64_Ehdr::Show() -{ -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Magic: %08x", e_magic); - LOG_NOTICE(LOADER, "Class: %s", "ELF64"); - LOG_NOTICE(LOADER, "Data: %s", Ehdr_DataToString(e_data).c_str()); - LOG_NOTICE(LOADER, "Current Version: %d", e_curver); - LOG_NOTICE(LOADER, "OS/ABI: %s", Ehdr_OS_ABIToString(e_os_abi).c_str()); - LOG_NOTICE(LOADER, "ABI version: %lld", e_abi_ver); - LOG_NOTICE(LOADER, "Type: %s", Ehdr_TypeToString(e_type).c_str()); - LOG_NOTICE(LOADER, "Machine: %s", Ehdr_MachineToString(e_machine).c_str()); - LOG_NOTICE(LOADER, "Version: %d", e_version); - LOG_NOTICE(LOADER, "Entry point address: 0x%08llx", e_entry); - LOG_NOTICE(LOADER, "Program headers offset: 0x%08llx", e_phoff); - LOG_NOTICE(LOADER, "Section headers offset: 0x%08llx", e_shoff); - LOG_NOTICE(LOADER, "Flags: 0x%x", e_flags); - LOG_NOTICE(LOADER, "Size of this header: %d", e_ehsize); - LOG_NOTICE(LOADER, "Size of program headers: %d", e_phentsize); - LOG_NOTICE(LOADER, "Number of program headers: %d", e_phnum); - LOG_NOTICE(LOADER, "Size of section headers: %d", e_shentsize); - LOG_NOTICE(LOADER, "Number of section headers: %d", e_shnum); - LOG_NOTICE(LOADER, "Section header string table index: %d", e_shstrndx); -#endif -} - -void Elf64_Shdr::Load(vfsStream& f) -{ - sh_name = Read32(f); - sh_type = Read32(f); - sh_flags = Read64(f); - sh_addr = Read64(f); - sh_offset = Read64(f); - sh_size = Read64(f); - sh_link = Read32(f); - sh_info = Read32(f); - sh_addralign = Read64(f); - sh_entsize = Read64(f); -} - -void Elf64_Shdr::Show() -{ -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Name offset: 0x%x", sh_name); - LOG_NOTICE(LOADER, "Type: %d", sh_type); - LOG_NOTICE(LOADER, "Addr: 0x%llx", sh_addr); - LOG_NOTICE(LOADER, "Offset: 0x%llx", sh_offset); - LOG_NOTICE(LOADER, "Size: 0x%llx", sh_size); - LOG_NOTICE(LOADER, "EntSize: %lld", sh_entsize); - LOG_NOTICE(LOADER, "Flags: 0x%llx", sh_flags); - LOG_NOTICE(LOADER, "Link: 0x%x", sh_link); - LOG_NOTICE(LOADER, "Info: 0x%x", sh_info); - LOG_NOTICE(LOADER, "Address align: 0x%llx", sh_addralign); -#endif -} - -void Elf64_Phdr::Load(vfsStream& f) -{ - p_type = Read32(f); - p_flags = Read32(f); - p_offset = Read64(f); - p_vaddr = Read64(f); - p_paddr = Read64(f); - p_filesz = Read64(f); - p_memsz = Read64(f); - p_align = Read64(f); -} - -void Elf64_Phdr::Show() -{ -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "Type: %s", Phdr_TypeToString(p_type).c_str()); - LOG_NOTICE(LOADER, "Offset: 0x%08llx", p_offset); - LOG_NOTICE(LOADER, "Virtual address: 0x%08llx", p_vaddr); - LOG_NOTICE(LOADER, "Physical address: 0x%08llx", p_paddr); - LOG_NOTICE(LOADER, "File size: 0x%08llx", p_filesz); - LOG_NOTICE(LOADER, "Memory size: 0x%08llx", p_memsz); - LOG_NOTICE(LOADER, "Flags: %s", Phdr_FlagsToString(p_flags).c_str()); - LOG_NOTICE(LOADER, "Align: 0x%llx", p_align); -#endif -} - -void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr) -{ - Write32(f, ehdr.e_magic); - Write8(f, ehdr.e_class); - Write8(f, ehdr.e_data); - Write8(f, ehdr.e_curver); - Write8(f, ehdr.e_os_abi); - Write64(f, ehdr.e_abi_ver); - Write16(f, ehdr.e_type); - Write16(f, ehdr.e_machine); - Write32(f, ehdr.e_version); - Write64(f, ehdr.e_entry); - Write64(f, ehdr.e_phoff); - Write64(f, ehdr.e_shoff); - Write32(f, ehdr.e_flags); - Write16(f, ehdr.e_ehsize); - Write16(f, ehdr.e_phentsize); - Write16(f, ehdr.e_phnum); - Write16(f, ehdr.e_shentsize); - Write16(f, ehdr.e_shnum); - Write16(f, ehdr.e_shstrndx); -} - -void WritePhdr(rFile& f, Elf64_Phdr& phdr) -{ - Write32(f, phdr.p_type); - Write32(f, phdr.p_flags); - Write64(f, phdr.p_offset); - Write64(f, phdr.p_vaddr); - Write64(f, phdr.p_paddr); - Write64(f, phdr.p_filesz); - Write64(f, phdr.p_memsz); - Write64(f, phdr.p_align); -} - -void WriteShdr(rFile& f, Elf64_Shdr& shdr) -{ - Write32(f, shdr.sh_name); - Write32(f, shdr.sh_type); - Write64(f, shdr.sh_flags); - Write64(f, shdr.sh_addr); - Write64(f, shdr.sh_offset); - Write64(f, shdr.sh_size); - Write32(f, shdr.sh_link); - Write32(f, shdr.sh_info); - Write64(f, shdr.sh_addralign); - Write64(f, shdr.sh_entsize); -} - -ELF64Loader::ELF64Loader(vfsStream& f) - : elf64_f(f) - , LoaderBase() -{ - int a = 0; -} - -bool ELF64Loader::LoadInfo() -{ - if(!elf64_f.IsOpened()) return false; - - if(!LoadEhdrInfo()) return false; - if(!LoadPhdrInfo()) return false; - if(!LoadShdrInfo()) return false; - - return true; -} - -bool ELF64Loader::LoadData(u64 offset) -{ - if(!elf64_f.IsOpened()) return false; - - if(!LoadEhdrData(offset)) return false; - if(!LoadPhdrData(offset)) return false; - if(!LoadShdrData(offset)) return false; - - return true; -} - -bool ELF64Loader::Close() -{ - return elf64_f.Close(); -} - -bool ELF64Loader::LoadEhdrInfo(s64 offset) -{ - elf64_f.Seek(offset < 0 ? 0 : offset); - ehdr.Load(elf64_f); - - if(!ehdr.CheckMagic()) return false; - - if(ehdr.e_phentsize != sizeof(Elf64_Phdr)) + namespace handlers { - LOG_ERROR(LOADER, "elf64 error: e_phentsize[0x%x] != sizeof(Elf64_Phdr)[0x%x]", ehdr.e_phentsize, sizeof(Elf64_Phdr)); - return false; - } - - if(ehdr.e_shentsize != sizeof(Elf64_Shdr)) - { - LOG_ERROR(LOADER, "elf64 error: e_shentsize[0x%x] != sizeof(Elf64_Shdr)[0x%x]", ehdr.e_shentsize, sizeof(Elf64_Shdr)); - return false; - } - - switch(ehdr.e_machine) - { - case MACHINE_PPC64: - case MACHINE_SPU: - machine = (Elf_Machine)ehdr.e_machine; - break; - - default: - machine = MACHINE_Unknown; - LOG_ERROR(LOADER, "Unknown elf64 type: 0x%x", ehdr.e_machine); - return false; - } - - entry = (u32)ehdr.GetEntry(); - if(entry == 0) - { - LOG_ERROR(LOADER, "elf64 error: entry is null!"); - return false; - } - - return true; -} - -bool ELF64Loader::LoadPhdrInfo(s64 offset) -{ - phdr_arr.clear(); - - if(ehdr.e_phoff == 0 && ehdr.e_phnum) - { - LOG_ERROR(LOADER, "LoadPhdr64 error: Program header offset is null!"); - return false; - } - - elf64_f.Seek(offset < 0 ? ehdr.e_phoff : offset); - - for(u32 i=0; i= shdr_arr.size()) - { - LOG_WARNING(LOADER, "LoadShdr64 error: shstrndx too big!"); - return true; - } - - for(u32 i=0; iRead(&m_ehdr, sizeof(ehdr)); -bool ELF64Loader::LoadPhdrData(u64 offset) -{ - for(auto& phdr: phdr_arr) - { - phdr.Show(); - - if (phdr.p_vaddr < min_addr) - { - min_addr = (u32)phdr.p_vaddr; - } - - if (phdr.p_vaddr + phdr.p_memsz > max_addr) - { - max_addr = (u32)(phdr.p_vaddr + phdr.p_memsz); - } - - if (phdr.p_vaddr != phdr.p_paddr) - { - LOG_WARNING(LOADER, "ElfProgram different load addrs: paddr=0x%8.8x, vaddr=0x%8.8x", - phdr.p_paddr, phdr.p_vaddr); - } - - if(!Memory.MainMem.IsInMyRange(offset + phdr.p_vaddr, (u32)phdr.p_memsz)) - { -#ifdef LOADER_DEBUG - LOG_WARNING(LOADER, "Skipping..."); - LOG_WARNING(LOADER, ""); -#endif - continue; - } - - switch(phdr.p_type) - { - case 0x00000001: //LOAD - if(phdr.p_memsz) - { - if (!Memory.MainMem.AllocFixed(offset + phdr.p_vaddr, (u32)phdr.p_memsz)) - { - LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, offset + phdr.p_vaddr, (u32)phdr.p_memsz); - } - else if (phdr.p_filesz) - { - elf64_f.Seek(phdr.p_offset); - elf64_f.Read(vm::get_ptr(offset + phdr.p_vaddr), phdr.p_filesz); - Emu.GetSFuncManager().StaticAnalyse(vm::get_ptr(offset + phdr.p_vaddr), (u32)phdr.p_filesz, (u32)phdr.p_vaddr); - } - } - break; - - case 0x00000007: //TLS - Emu.SetTLSData(offset + phdr.p_vaddr, phdr.p_filesz, phdr.p_memsz); - break; - - case 0x60000001: //LOOS+1 + if (!m_ehdr.check()) { - if(!phdr.p_filesz) + return bad_file; + } + + if (m_ehdr.e_phnum && m_ehdr.e_phentsize != sizeof(phdr)) + { + return broken_file; + } + + if (m_ehdr.e_shnum && m_ehdr.e_shentsize != sizeof(shdr)) + { + return broken_file; + } + + LOG_ERROR(LOADER, "m_ehdr.e_type = 0x%x", m_ehdr.e_type.ToLE()); + + if (m_ehdr.e_machine != MACHINE_PPC64 && m_ehdr.e_machine != MACHINE_SPU) + { + LOG_ERROR(LOADER, "Unknown elf64 machine type: 0x%x", m_ehdr.e_machine.ToLE()); + return bad_version; + } + + if (m_ehdr.e_phnum) + { + m_phdrs.resize(m_ehdr.e_phnum); + m_stream->Seek(handler::get_stream_offset() + m_ehdr.e_phoff); + if (m_stream->Read(m_phdrs.data(), m_ehdr.e_phnum * sizeof(phdr)) != m_ehdr.e_phnum * sizeof(phdr)) + return broken_file; + } + else + m_phdrs.clear(); + + if (m_ehdr.e_shnum) + { + m_shdrs.resize(m_ehdr.e_shnum); + m_stream->Seek(handler::get_stream_offset() + m_ehdr.e_shoff); + if (m_stream->Read(m_shdrs.data(), m_ehdr.e_shnum * sizeof(shdr)) != m_ehdr.e_shnum * sizeof(shdr)) + return broken_file; + } + else + m_shdrs.clear(); + + if (is_sprx()) + { + LOG_NOTICE(LOADER, "SPRX loading..."); + + m_stream->Seek(handler::get_stream_offset() + m_phdrs[0].p_paddr.addr()); + m_stream->Read(&m_sprx_module_info, sizeof(sprx_module_info)); + + //m_stream->Seek(handler::get_stream_offset() + m_phdrs[1].p_vaddr.addr()); + //m_stream->Read(&m_sprx_function_info, sizeof(sprx_function_info)); + } + else + { + m_sprx_import_info.clear(); + m_sprx_export_info.clear(); + } + + return ok; + } + + handler::error_code elf64::load_sprx(sprx_info& info) + { + for (auto &phdr : m_phdrs) + { + switch (phdr.p_type) + { + case 0x1: //load + if (phdr.p_memsz) + { + sprx_segment_info segment; + segment.size = phdr.p_memsz; + segment.size_file = phdr.p_filesz; + + segment.begin.set(vm::alloc(segment.size, vm::sprx)); + + if (!segment.begin) + { + LOG_ERROR(LOADER, "%s() sprx: AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, phdr.p_vaddr.addr(), (u32)phdr.p_memsz); + + return loading_error; + } + + segment.initial_addr.set(phdr.p_vaddr.addr()); + LOG_ERROR(LOADER, "segment addr=0x%x, initial addr = 0x%x", segment.begin.addr(), segment.initial_addr.addr()); + + if (phdr.p_filesz) + { + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset); + m_stream->Read(segment.begin.get_ptr(), phdr.p_filesz); + } + + if (phdr.p_paddr) + { + sys_prx_module_info_t module_info; + m_stream->Seek(handler::get_stream_offset() + phdr.p_paddr.addr()); + m_stream->Read(&module_info, sizeof(module_info)); + LOG_ERROR(LOADER, "%s (%x):", module_info.name, (u32)module_info.toc); + + int import_count = (module_info.imports_end - module_info.imports_start) / sizeof(sys_prx_library_info_t); + + if (import_count) + { + LOG_ERROR(LOADER, "**** Lib '%s'has %d imports!", module_info.name, import_count); + break; + } + + sys_prx_library_info_t lib; + for (u32 e = module_info.exports_start.addr(); + e < module_info.exports_end.addr(); + e += lib.size ? lib.size : sizeof(sys_prx_library_info_t)) + { + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + e); + m_stream->Read(&lib, sizeof(lib)); + + std::string modulename; + if (lib.name_addr) + { + char name[27]; + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.name_addr); + modulename = std::string(name, m_stream->Read(name, sizeof(name))); + LOG_ERROR(LOADER, "**** %s", name); + } + + //ModuleManager& manager = Emu.GetModuleManager(); + //Module* module = manager.GetModuleByName(modulename); + + LOG_ERROR(LOADER, "**** 0x%x - 0x%x - 0x%x", (u32)lib.unk4, (u32)lib.unk5, (u32)lib.unk6); + + for (u16 i = 0, end = lib.num_func; i < end; ++i) + { + be_t fnid, fstub; + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.fnid_addr + i * sizeof(fnid)); + m_stream->Read(&fnid, sizeof(fnid)); + + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + lib.fstub_addr + i * sizeof(fstub)); + m_stream->Read(&fstub, sizeof(fstub)); + + info.exports[fnid] = fstub; + + //LOG_NOTICE(LOADER, "Exported function '%s' in '%s' module (LLE)", SysCalls::GetHLEFuncName(fnid).c_str(), module_name.c_str()); + LOG_ERROR(LOADER, "**** %s: [%s] -> 0x%x", modulename.c_str(), SysCalls::GetHLEFuncName(fnid).c_str(), (u32)fstub); + } + } + + for (u32 i = module_info.imports_start; + i < module_info.imports_end; + i += lib.size ? lib.size : sizeof(sys_prx_library_info_t)) + { + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset + i); + m_stream->Read(&lib, sizeof(lib)); + } + } + + info.segments.push_back(segment); + } + break; - const sys_process_param& proc_param = vm::get_ref(offset + phdr.p_vaddr); + case 0x700000a4: //relocation + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset); - if (proc_param.size < sizeof(sys_process_param)) - { - LOG_WARNING(LOADER, "Bad proc param size! [0x%x : 0x%x]", proc_param.size, sizeof(sys_process_param)); - } - if (proc_param.magic != 0x13bcc5f6) - { - LOG_ERROR(LOADER, "Bad magic! [0x%x]", proc_param.magic); - } - else - { -#ifdef LOADER_DEBUG - sys_process_param_info& info = Emu.GetInfo().GetProcParam(); - LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version.ToLE()); - LOG_NOTICE(LOADER, "*** primary prio: %d", info.primary_prio.ToLE()); - LOG_NOTICE(LOADER, "*** primary stacksize: 0x%x", info.primary_stacksize.ToLE()); - LOG_NOTICE(LOADER, "*** malloc pagesize: 0x%x", info.malloc_pagesize.ToLE()); - LOG_NOTICE(LOADER, "*** ppc seg: 0x%x", info.ppc_seg.ToLE()); - //LOG_NOTICE(LOADER, "*** crash dump param addr: 0x%x", info.crash_dump_param_addr.ToLE()); -#endif + for (uint i = 0; i < phdr.p_filesz; i += sizeof(sys_prx_relocation_info_t)) + { + sys_prx_relocation_info_t rel; + m_stream->Read(&rel, sizeof(rel)); + + u32 ADDR = info.segments[rel.index_addr].begin.addr() + rel.offset; + + switch ((u32)rel.type) + { + case 1: + LOG_ERROR(LOADER, "**** RELOCATION(1): 0x%x <- 0x%x", ADDR, (u32)(info.segments[rel.index_value].begin.addr() + rel.ptr.addr())); + *vm::ptr::make(ADDR) = info.segments[rel.index_value].begin.addr() + rel.ptr.addr(); + break; + + case 4: + LOG_ERROR(LOADER, "**** RELOCATION(4): 0x%x <- 0x%x", ADDR, (u16)(rel.ptr.addr())); + *vm::ptr::make(ADDR) = (u16)(u64)rel.ptr.addr(); + break; + + case 5: + LOG_ERROR(LOADER, "**** RELOCATION(5): 0x%x <- 0x%x", ADDR, (u16)(info.segments[rel.index_value].begin.addr() >> 16)); + *vm::ptr::make(ADDR) = info.segments[rel.index_value].begin.addr() >> 16; + break; + + case 6: + LOG_ERROR(LOADER, "**** RELOCATION(6): 0x%x <- 0x%x", ADDR, (u16)(info.segments[1].begin.addr() >> 16)); + *vm::ptr::make(ADDR) = info.segments[1].begin.addr() >> 16; + break; + + default: + LOG_ERROR(LOADER, "unknown prx relocation type (0x%x)", (u32)rel.type); + return bad_relocation_type; + } + } + + break; } } - break; - case 0x60000002: //LOOS+2 + for (auto &e : info.exports) { - if(!phdr.p_filesz) - break; + u32 stub = e.second; - const sys_proc_prx_param& proc_prx_param = vm::get_ref(offset + phdr.p_vaddr); - - -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "*** size: 0x%x", proc_prx_param.size.ToLE()); - LOG_NOTICE(LOADER, "*** magic: 0x%x", proc_prx_param.magic.ToLE()); - LOG_NOTICE(LOADER, "*** version: 0x%x", proc_prx_param.version.ToLE()); - LOG_NOTICE(LOADER, "*** libentstart: 0x%x", proc_prx_param.libentstart.ToLE()); - LOG_NOTICE(LOADER, "*** libentend: 0x%x", proc_prx_param.libentend.ToLE()); - LOG_NOTICE(LOADER, "*** libstubstart: 0x%x", proc_prx_param.libstubstart.ToLE()); - LOG_NOTICE(LOADER, "*** libstubend: 0x%x", proc_prx_param.libstubend.ToLE()); - LOG_NOTICE(LOADER, "*** ver: 0x%x", proc_prx_param.ver.ToLE()); -#endif - - if (proc_prx_param.magic != 0x1b434cec) + for (auto &s : info.segments) { - LOG_ERROR(LOADER, "Bad magic! (0x%x)", proc_prx_param.magic.ToLE()); - break; + if (stub >= s.initial_addr.addr() && stub < s.initial_addr.addr() + s.size_file) + { + stub += s.begin.addr() - s.initial_addr.addr(); + break; + } } - for (u32 s = proc_prx_param.libstubstart; s < proc_prx_param.libstubend; s += sizeof(Elf64_StubHeader)) - { - const Elf64_StubHeader& stub = vm::get_ref(offset + s); - - const std::string module_name = vm::get_ptr(stub.s_modulename); - Module* module = Emu.GetModuleManager().GetModuleByName(module_name); - if (module) - { - //module->SetLoaded(); - } - else - { - LOG_WARNING(LOADER, "Unknown module '%s'", module_name.c_str()); - } - -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, ""); - LOG_NOTICE(LOADER, "*** size: 0x%x", stub.s_size); - LOG_NOTICE(LOADER, "*** version: 0x%x", stub.s_version.ToLE()); - LOG_NOTICE(LOADER, "*** unk0: 0x%x", stub.s_unk0); - LOG_NOTICE(LOADER, "*** unk1: 0x%x", stub.s_unk1.ToLE()); - LOG_NOTICE(LOADER, "*** imports: %d", stub.s_imports.ToLE()); - LOG_NOTICE(LOADER, "*** module name: %s [0x%x]", module_name.c_str(), stub.s_modulename.ToLE()); - LOG_NOTICE(LOADER, "*** nid: 0x%016llx [0x%x]", vm::read64(stub.s_nid), stub.s_nid.ToLE()); - LOG_NOTICE(LOADER, "*** text: 0x%x", stub.s_text.ToLE()); -#endif - static const u32 section = 4 * 3; - u64 tbl = Memory.MainMem.AllocAlign(stub.s_imports * 4 * 2); - u64 dst = Memory.MainMem.AllocAlign(stub.s_imports * section); - - for (u32 i = 0; i < stub.s_imports; ++i) - { - const u32 nid = vm::read32(stub.s_nid + i * 4); - const u32 text = vm::read32(stub.s_text + i * 4); - - if (!module || !module->Load(nid)) - { - LOG_WARNING(LOADER, "Unimplemented function '%s' in '%s' module", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); - } - else //if (Ini.HLELogging.GetValue()) - { - LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); - } -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, "import %d:", i+1); - LOG_NOTICE(LOADER, "*** nid: 0x%x (0x%x)", nid, stub.s_nid + i*4); - LOG_NOTICE(LOADER, "*** text: 0x%x (0x%x)", text, stub.s_text + i*4); -#endif - vm::write32(stub.s_text + i*4, (u32)tbl + i*8); - - auto out_tbl = vm::ptr::make((u32)tbl + i * 8); - out_tbl[0] = (u32)dst + i*section; - out_tbl[1] = Emu.GetModuleManager().GetFuncNumById(nid); - - auto out_dst = vm::ptr::make((u32)dst + i * section); - out_dst[0] = OR(11, 2, 2, 0); - out_dst[1] = SC(2); - out_dst[2] = BLR(); - } - } -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, ""); -#endif + e.second = stub; } - break; - } -#ifdef LOADER_DEBUG - LOG_NOTICE(LOADER, ""); -#endif - } - return true; -} - -bool ELF64Loader::LoadShdrData(u64 offset) -{ - u64 max_addr = 0; - - for(uint i=0; i max_addr) max_addr = shdr.sh_addr + shdr.sh_size; - - if((shdr.sh_flags & SHF_ALLOC) != SHF_ALLOC) continue; - - const u64 addr = shdr.sh_addr; - const u64 size = shdr.sh_size; - - if(size == 0 || !Memory.IsGoodAddr(offset + addr, (u32)size)) continue; - - if(shdr.sh_addr && shdr.sh_addr < min_addr) + handler::error_code elf64::load() { - min_addr = (u32)shdr.sh_addr; + if (is_sprx()) + { + sprx_info info; + return load_sprx(info); + } + + Emu.m_sdk_version = -1; + + //store elf to memory + vm::ps3::init(); + + std::vector start_funcs; + std::vector stop_funcs; + + //load modules + static const char* lle_modules[] = { "lv2", "sre", "l10n", "gcm_sys", "fs" }; + //TODO: for (auto &module : lle_modules) + char* module; if (0) + { + elf64 sprx_handler; + vfsFile fsprx(std::string("/dev_flash/sys/external/lib") + module + ".sprx"); + + if (fsprx.IsOpened()) + { + sprx_handler.init(fsprx); + + if (sprx_handler.is_sprx()) + { + sprx_info info; + sprx_handler.load_sprx(info); + + std::unordered_map::iterator f; + + if ((f = info.exports.find(0xbc9a0086)) != info.exports.end()) + start_funcs.push_back(f->second); + + if ((f = info.exports.find(0xab779874)) != info.exports.end()) + stop_funcs.push_back(f->second); + + for (auto &e : info.exports) + { + if (e.first != 0xbc9a0086 && e.first != 0xab779874) + Emu.GetModuleManager().register_function(e.first, e.second); + } + } + } + } + + error_code res = load_data(0); + if (res != ok) + return res; + + //initialize process + auto rsx_callback_data = vm::ptr::make(Memory.MainMem.AllocAlign(4 * 4)); + *rsx_callback_data++ = (rsx_callback_data + 1).addr(); + Emu.SetRSXCallback(rsx_callback_data.addr()); + + rsx_callback_data[0] = ADDI(r11, 0, 0x3ff); + rsx_callback_data[1] = SC(2); + rsx_callback_data[2] = BLR(); + + auto ppu_thr_exit_data = vm::ptr::make(Memory.MainMem.AllocAlign(3 * 4)); + ppu_thr_exit_data[0] = ADDI(r11, 0, 41); + ppu_thr_exit_data[1] = SC(2); + ppu_thr_exit_data[2] = BLR(); + Emu.SetPPUThreadExit(ppu_thr_exit_data.addr()); + + auto ppu_thr_stop_data = vm::ptr::make(Memory.MainMem.AllocAlign(2 * 4)); + ppu_thr_stop_data[0] = SC(4); + ppu_thr_stop_data[1] = BLR(); + Emu.SetPPUThreadStop(ppu_thr_stop_data.addr()); + + //vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); + /* + //TODO + static const int branch_size = 6 * 4; + auto make_branch = [](vm::ptr& ptr, u32 addr) + { + u32 stub = vm::read32(addr); + u32 rtoc = vm::read32(addr + 4); + + *ptr++ = implicts::LI(r0, stub >> 16); + *ptr++ = ORIS(r0, r0, stub & 0xffff); + *ptr++ = implicts::LI(r2, rtoc >> 16); + *ptr++ = ORIS(r2, r2, rtoc & 0xffff); + *ptr++ = MTCTR(r0); + *ptr++ = BCTRL(); + }; + + auto entry = vm::ptr::make(vm::alloc(branch_size * (start_funcs.size() + 1), vm::main)); + + auto OPD = vm::ptr::make(vm::alloc(2 * 4)); + OPD[0] = entry.addr(); + OPD[1] = 0; + + for (auto &f : start_funcs) + { + make_branch(entry, f); + } + + make_branch(entry, m_ehdr.e_entry); + */ + + ppu_thread(m_ehdr.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); + + return ok; } - if(shdr.sh_addr + shdr.sh_size > max_addr) + handler::error_code elf64::load_data(u64 offset) { - max_addr = (u32)(shdr.sh_addr + shdr.sh_size); - } + for (auto &phdr : m_phdrs) + { + switch (phdr.p_type) + { + case 0x00000001: //LOAD + if (phdr.p_memsz) + { + if (!vm::alloc(phdr.p_vaddr.addr(), (u32)phdr.p_memsz, vm::main)) + { + LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, phdr.p_vaddr, (u32)phdr.p_memsz); - if((shdr.sh_type == SHT_RELA) || (shdr.sh_type == SHT_REL)) - { - LOG_ERROR(LOADER, "ELF64 ERROR: Relocation"); - continue; - } + return loading_error; + } - switch(shdr.sh_type) - { - case SHT_NOBITS: - //LOG_WARNING(LOADER, "SHT_NOBITS: addr=0x%llx, size=0x%llx", offset + addr, size); - //memset(&Memory[offset + addr], 0, size); - break; + if (phdr.p_filesz) + { + m_stream->Seek(handler::get_stream_offset() + phdr.p_offset); + m_stream->Read(phdr.p_vaddr.get_ptr(), phdr.p_filesz); + Emu.GetSFuncManager().StaticAnalyse(phdr.p_vaddr.get_ptr(), (u32)phdr.p_filesz, phdr.p_vaddr.addr()); + } + } + break; - case SHT_PROGBITS: - //elf64_f.Seek(shdr.sh_offset); - //elf64_f.Read(&Memory[offset + addr], shdr.sh_size); - break; + case 0x00000007: //TLS + Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value()); + break; + + case 0x60000001: //LOOS+1 + if (phdr.p_filesz) + { + const sys_process_param& proc_param = *(sys_process_param*)phdr.p_vaddr.get_ptr(); + + if (proc_param.size < sizeof(sys_process_param)) + { + LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", proc_param.size, sizeof(sys_process_param)); + } + if (proc_param.magic != 0x13bcc5f6) + { + LOG_ERROR(LOADER, "Bad process_param magic! [0x%x]", proc_param.magic); + } + else + { + sys_process_param_info& info = Emu.GetInfo().GetProcParam(); + /* + LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version.ToLE()); + LOG_NOTICE(LOADER, "*** primary prio: %d", info.primary_prio.ToLE()); + LOG_NOTICE(LOADER, "*** primary stacksize: 0x%x", info.primary_stacksize.ToLE()); + LOG_NOTICE(LOADER, "*** malloc pagesize: 0x%x", info.malloc_pagesize.ToLE()); + LOG_NOTICE(LOADER, "*** ppc seg: 0x%x", info.ppc_seg.ToLE()); + //LOG_NOTICE(LOADER, "*** crash dump param addr: 0x%x", info.crash_dump_param_addr.ToLE()); + */ + + info = proc_param.info; + Emu.m_sdk_version = info.sdk_version; + } + } + break; + + case 0x60000002: //LOOS+2 + if (phdr.p_filesz) + { + const sys_proc_prx_param& proc_prx_param = *(sys_proc_prx_param*)phdr.p_vaddr.get_ptr(); + + if (proc_prx_param.magic != 0x1b434cec) + { + LOG_ERROR(LOADER, "Bad magic! (0x%x)", proc_prx_param.magic.ToLE()); + break; + } + + for (auto stub = proc_prx_param.libstubstart; stub < proc_prx_param.libstubend; ++stub) + { + const std::string module_name = stub->s_modulename.get_ptr(); + Module* module = Emu.GetModuleManager().GetModuleByName(module_name); + if (module) + { + //module->SetLoaded(); + } + else + { + LOG_WARNING(LOADER, "Unknown module '%s'", module_name.c_str()); + } + + static const u32 tbl_section_size = 2 * 4; + static const u32 dst_section_size = 3 * 4; + auto& tbl = ptr::make(alloc(stub->s_imports * tbl_section_size)); + auto& dst = ptr::make(alloc(stub->s_imports * dst_section_size)); + + for (u32 i = 0; i < stub->s_imports; ++i) + { + const u32 nid = *stub->s_nid++; + + if (!Emu.GetModuleManager().get_function_stub(nid, stub->s_text[i])) + { + stub->s_text[i] = tbl.addr(); + + *tbl++ = dst.addr(); + *tbl++ = Emu.GetModuleManager().GetFuncNumById(nid); + + *dst++ = MR(11, 2); + *dst++ = SC(2); + *dst++ = BLR(); + + if (module && !module->Load(nid)) + { + LOG_WARNING(LOADER, "Unimplemented function '%s' in '%s' module (HLE)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); + } + else //if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module (HLE)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str()); + } + } + else + { + //Is function auto exported, than we can use it + LOG_NOTICE(LOADER, "Imported function '%s' in '%s' module (LLE: 0x%x)", SysCalls::GetHLEFuncName(nid).c_str(), module_name.c_str(), (u32)stub->s_text[i]); + } + } + } + } + break; + } + } + + return ok; } } - - return true; } diff --git a/rpcs3/Loader/ELF64.h b/rpcs3/Loader/ELF64.h index 7843b9f569..a5b2cde70b 100644 --- a/rpcs3/Loader/ELF64.h +++ b/rpcs3/Loader/ELF64.h @@ -1,102 +1,157 @@ #pragma once #include "Loader.h" +#include struct vfsStream; class rFile; -struct Elf64_Ehdr +namespace loader { - u32 e_magic; - u8 e_class; - u8 e_data; - u8 e_curver; - u8 e_os_abi; - u64 e_abi_ver; - u16 e_type; - u16 e_machine; - u32 e_version; - u64 e_entry; - u64 e_phoff; - u64 e_shoff; - u32 e_flags; - u16 e_ehsize; - u16 e_phentsize; - u16 e_phnum; - u16 e_shentsize; - u16 e_shnum; - u16 e_shstrndx; + namespace handlers + { + class elf64 : public handler + { + public: + struct ehdr + { + be_t e_magic; + u8 e_class; + u8 e_data; + u8 e_curver; + u8 e_os_abi; + be_t e_abi_ver; + be_t e_type; + be_t e_machine; + be_t e_version; + be_t e_entry; + be_t e_phoff; + be_t e_shoff; + be_t e_flags; + be_t e_ehsize; + be_t e_phentsize; + be_t e_phnum; + be_t e_shentsize; + be_t e_shnum; + be_t e_shstrndx; - void Load(vfsStream& f); + bool check() const { return e_magic.ToBE() == se32(0x7F454C46); } + } m_ehdr; - void Show(); + struct phdr + { + be_t p_type; + be_t p_flags; + be_t p_offset; + bptr p_vaddr; + bptr p_paddr; + be_t p_filesz; + be_t p_memsz; + be_t p_align; + }; - bool CheckMagic() const { return e_magic == 0x7F454C46; } - u64 GetEntry() const { return e_entry; } -}; + struct shdr + { + be_t sh_name; + be_t sh_type; + be_t sh_flags; + bptr sh_addr; + be_t sh_offset; + be_t sh_size; + be_t sh_link; + be_t sh_info; + be_t sh_addralign; + be_t sh_entsize; + }; -struct Elf64_Shdr -{ - u32 sh_name; - u32 sh_type; - u64 sh_flags; - u64 sh_addr; - u64 sh_offset; - u64 sh_size; - u32 sh_link; - u32 sh_info; - u64 sh_addralign; - u64 sh_entsize; + struct sprx_module_info + { + be_t attr; + u8 version[2]; + char name[28]; + be_t toc_addr; + be_t export_start; + be_t export_end; + be_t import_start; + be_t import_end; + } m_sprx_module_info; - void Load(vfsStream& f); + struct sprx_export_info + { + u8 size; + u8 padding; + be_t version; + be_t attr; + be_t func_count; + be_t vars_count; + be_t tls_vars_count; + be_t hash_info; + be_t tls_hash_info; + u8 reserved[2]; + be_t lib_name_offset; + be_t nid_offset; + be_t stub_offset; + }; - void Show(); -}; + struct sprx_import_info + { + u8 size; + u8 unused; + be_t version; + be_t attr; + be_t func_count; + be_t vars_count; + be_t tls_vars_count; + u8 reserved[4]; + be_t lib_name_offset; + be_t nid_offset; + be_t stub_offset; + //... + }; -struct Elf64_Phdr -{ - u32 p_type; - u32 p_flags; - u64 p_offset; - u64 p_vaddr; - u64 p_paddr; - u64 p_filesz; - u64 p_memsz; - u64 p_align; + struct sprx_function_info + { + be_t name_table_offset; + be_t entry_table_offset; + be_t padding; + } m_sprx_function_info; - void Load(vfsStream& f); + struct sprx_lib_info + { + std::string name; + }; - void Show(); -}; + struct sprx_segment_info + { + vm::ptr begin; + u32 size; + u32 size_file; + vm::ptr initial_addr; + std::vector modules; + }; -class ELF64Loader : public LoaderBase -{ - vfsStream& elf64_f; + struct sprx_info + { + std::unordered_map exports; + std::unordered_map imports; + std::vector segments; + }; -public: - Elf64_Ehdr ehdr; - std::vector shdr_name_arr; - std::vector shdr_arr; - std::vector phdr_arr; + std::vector m_phdrs; + std::vector m_shdrs; - ELF64Loader(vfsStream& f); - ~ELF64Loader() {Close();} + std::vector m_sprx_segments_info; + std::vector m_sprx_import_info; + std::vector m_sprx_export_info; - virtual bool LoadInfo(); - virtual bool LoadData(u64 offset = 0); - virtual bool Close(); + public: + virtual ~elf64() = default; - bool LoadEhdrInfo(s64 offset=-1); - bool LoadPhdrInfo(s64 offset=-1); - bool LoadShdrInfo(s64 offset=-1); - -private: - bool LoadEhdrData(u64 offset); - bool LoadPhdrData(u64 offset); - bool LoadShdrData(u64 offset); - - //bool LoadImports(); -}; - -void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr); -void WritePhdr(rFile& f, Elf64_Phdr& phdr); -void WriteShdr(rFile& f, Elf64_Shdr& shdr); + error_code init(vfsStream& stream) override; + error_code load() override; + error_code load_data(u64 offset); + error_code load_sprx(sprx_info& info); + bool is_sprx() const { return m_ehdr.e_type == 0xffa4; } + std::string sprx_get_module_name() const { return m_sprx_module_info.name; } + }; + } +} \ No newline at end of file diff --git a/rpcs3/Loader/Loader.cpp b/rpcs3/Loader/Loader.cpp index ed804f1f40..e2567a60f0 100644 --- a/rpcs3/Loader/Loader.cpp +++ b/rpcs3/Loader/Loader.cpp @@ -1,11 +1,38 @@ #include "stdafx.h" #include "Utilities/Log.h" #include "Loader.h" -#include "ELF.h" -#include "SELF.h" #include "PSF.h" #include "Emu/FS/vfsLocalFile.h" +namespace loader +{ + bool loader::load(vfsStream& stream) + { + for (auto i : m_handlers) + { + if (i->init(stream) == handler::ok) + { + if (i->load() == handler::ok) + { + return true; + } + } + + stream.Seek(i->get_stream_offset()); + } + + return false; + } + + handler::error_code handler::init(vfsStream& stream) + { + m_stream_offset = stream.Tell(); + m_stream = &stream; + + return ok; + } +}; + static const u64 g_spu_offset = 0x10000; const std::string Ehdr_DataToString(const u8 data) @@ -13,7 +40,7 @@ const std::string Ehdr_DataToString(const u8 data) if(data > 1) return fmt::Format("%d's complement, big endian", data); if(data < 1) return "Data is not found"; - return fmt::Format("%d's complement, small endian", data); + return fmt::Format("%d's complement, little endian", data); } const std::string Ehdr_TypeToString(const u16 type) @@ -35,7 +62,7 @@ const std::string Ehdr_OS_ABIToString(const u8 os_abi) case 0x66: return "Cell OS LV-2"; }; - return fmt::Format("Unknown (0x%x)", os_abi); + return fmt::Format("Unknown (%x)", os_abi); } const std::string Ehdr_MachineToString(const u16 machine) @@ -48,7 +75,7 @@ const std::string Ehdr_MachineToString(const u16 machine) case MACHINE_ARM: return "ARM"; }; - return fmt::Format("Unknown (0x%x)", machine); + return fmt::Format("Unknown (%x)", machine); } const std::string Phdr_FlagsToString(u32 flags) @@ -73,7 +100,7 @@ const std::string Phdr_FlagsToString(u32 flags) flags &= ~spu << 0x14; flags &= ~rsx << 0x18; - if(flags != 0) return fmt::Format("Unknown %s PPU[0x%x] SPU[0x%x] RSX[0x%x]", ret.c_str(), ppu, spu, rsx); + if(flags != 0) return fmt::Format("Unknown %s PPU[%x] SPU[%x] RSX[%x]", ret.c_str(), ppu, spu, rsx); ret += "PPU[" + FLAGS_TO_STRING(ppu) + "] "; ret += "SPU[" + FLAGS_TO_STRING(spu) + "] "; @@ -93,94 +120,5 @@ const std::string Phdr_TypeToString(const u32 type) case 0x60000002: return "LOOS+2"; }; - return fmt::Format("Unknown (0x%x)", type); -} - -Loader::Loader() - : m_stream(nullptr) - , m_loader(nullptr) -{ -} - -Loader::Loader(vfsFileBase& stream) - : m_stream(&stream) - , m_loader(nullptr) -{ -} - -Loader::~Loader() -{ - delete m_loader; - m_loader = nullptr; -} - -void Loader::Open(vfsFileBase& stream) -{ - m_stream = &stream; -} - -LoaderBase* Loader::SearchLoader() -{ - if(!m_stream) - return nullptr; - - LoaderBase* l = new ELFLoader(*m_stream); - if(l->LoadInfo()) - return l; - delete l; - - l = new SELFLoader(*m_stream); - if(l->LoadInfo()) - return l; - delete l; - - return nullptr; -} - -bool Loader::Analyze() -{ - delete m_loader; - - m_loader = SearchLoader(); - - if(!m_loader) - { - LOG_ERROR(LOADER, "Unknown file type"); - return false; - } - - machine = m_loader->GetMachine(); - entry = m_loader->GetMachine() == MACHINE_SPU ? m_loader->GetEntry() + g_spu_offset : m_loader->GetEntry(); - - return true; -} - -bool Loader::Load() -{ - if(!m_loader) - return false; - - if(!m_loader->LoadData(m_loader->GetMachine() == MACHINE_SPU ? g_spu_offset : 0)) - { - LOG_ERROR(LOADER, "Broken file"); - return false; - } - - /* - const std::string& root = fmt::ToUTF8(wxFileName(wxFileName(m_stream->GetPath()).GetPath()).GetPath()); - std::string ps3_path; - const std::string& psf_path = root + "/" + "PARAM.SFO"; - vfsFile f(psf_path); - if(f.IsOpened()) - { - PSFLoader psf_l(f); - if(psf_l.Load()) - { - CurGameInfo = psf_l.m_info; - CurGameInfo.root = root; - psf_l.Close(); - } - } - */ - return true; + return fmt::Format("Unknown (%x)", type); } diff --git a/rpcs3/Loader/Loader.h b/rpcs3/Loader/Loader.h index 0f14d38ab9..3e6fbf925a 100644 --- a/rpcs3/Loader/Loader.h +++ b/rpcs3/Loader/Loader.h @@ -1,6 +1,8 @@ #pragma once +#include "Emu/Memory/vm.h" struct vfsFileBase; +struct vfsStream; class rFile; #ifdef _DEBUG @@ -65,22 +67,7 @@ struct sys_process_param sys_process_param_info info; }; -struct sys_proc_prx_param -{ - be_t size; - be_t magic; - be_t version; - be_t pad0; - be_t libentstart; - be_t libentend; - be_t libstubstart; - be_t libstubend; - be_t ver; - be_t pad1; - be_t pad2; -}; - -struct Elf64_StubHeader +struct sys_stub { u8 s_size; // = 0x2c u8 s_unk0; @@ -89,59 +76,80 @@ struct Elf64_StubHeader be_t s_imports; be_t s_unk2; // = 0x0 be_t s_unk3; // = 0x0 - be_t s_modulename; - be_t s_nid; - be_t s_text; + vm::bptr s_modulename; + vm::bptr s_nid; + vm::bptr s_text; be_t s_unk4; // = 0x0 be_t s_unk5; // = 0x0 be_t s_unk6; // = 0x0 be_t s_unk7; // = 0x0 }; -class LoaderBase +struct sys_proc_prx_param { -protected: - u32 entry; - u32 min_addr; - u32 max_addr; - Elf_Machine machine; - - LoaderBase() - : machine(MACHINE_Unknown) - , entry(0) - , min_addr(0) - , max_addr(0) - { - } - -public: - virtual ~LoaderBase() = default; - - virtual bool LoadInfo() { return false; } - virtual bool LoadData(u64 offset = 0) { return false; } - Elf_Machine GetMachine() const { return machine; } - - u32 GetEntry() const { return entry; } - u32 GetMinAddr() const { return min_addr; } - u32 GetMaxAddr() const { return max_addr; } + be_t size; + be_t magic; + be_t version; + be_t pad0; + be_t libentstart; + be_t libentend; + vm::bptr libstubstart; + vm::bptr libstubend; + be_t ver; + be_t pad1; + be_t pad2; }; -class Loader : public LoaderBase +namespace loader { - vfsFileBase* m_stream; - LoaderBase* m_loader; + class handler + { + u64 m_stream_offset; -public: - Loader(); - Loader(vfsFileBase& stream); - virtual ~Loader(); + protected: + vfsStream* m_stream; - void Open(const std::string& path); - void Open(vfsFileBase& stream); - bool Analyze(); + public: + enum error_code + { + bad_version = -1, + bad_file = -2, + broken_file = -3, + loading_error = -4, + bad_relocation_type = -5, + ok = 0, + }; - bool Load(); + virtual ~handler() = default; -private: - LoaderBase* SearchLoader(); -}; \ No newline at end of file + virtual error_code init(vfsStream& stream); + virtual error_code load() = 0; + u64 get_stream_offset() const + { + return m_stream_offset; + } + }; + + class loader + { + std::vector m_handlers; + + public: + ~loader() + { + for (auto &h : m_handlers) + { + delete h; + } + } + + void register_handler(handler* handler) + { + m_handlers.push_back(handler); + } + + bool load(vfsStream& stream); + }; + + using namespace vm; +} diff --git a/rpcs3/Loader/SELF.cpp b/rpcs3/Loader/SELF.cpp deleted file mode 100644 index 0d3755cce9..0000000000 --- a/rpcs3/Loader/SELF.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "stdafx.h" -#include "Utilities/Log.h" -#include "Emu/FS/vfsStream.h" -#include "SELF.h" -#include "ELF64.h" - -void SceHeader::Load(vfsStream& f) -{ - se_magic = Read32(f); - se_hver = Read32(f); - se_flags = Read16(f); - se_type = Read16(f); - se_meta = Read32(f); - se_hsize = Read64(f); - se_esize = Read64(f); -} - -void SceHeader::Show() -{ - LOG_NOTICE(LOADER, "Magic: %08x", se_magic); - LOG_NOTICE(LOADER, "Class: %s", "SELF"); - LOG_NOTICE(LOADER, "hver: 0x%08x", se_hver); - LOG_NOTICE(LOADER, "flags: 0x%04x", se_flags); - LOG_NOTICE(LOADER, "type: 0x%04x", se_type); - LOG_NOTICE(LOADER, "meta: 0x%08x", se_meta); - LOG_NOTICE(LOADER, "hsize: 0x%llx", se_hsize); - LOG_NOTICE(LOADER, "esize: 0x%llx", se_esize); -} - -void SelfHeader::Load(vfsStream& f) -{ - se_htype = Read64(f); - se_appinfooff = Read64(f); - se_elfoff = Read64(f); - se_phdroff = Read64(f); - se_shdroff = Read64(f); - se_secinfoff = Read64(f); - se_sceveroff = Read64(f); - se_controloff = Read64(f); - se_controlsize = Read64(f); - pad = Read64(f); -} - -void SelfHeader::Show() -{ - LOG_NOTICE(LOADER, "header type: 0x%llx", se_htype); - LOG_NOTICE(LOADER, "app info offset: 0x%llx", se_appinfooff); - LOG_NOTICE(LOADER, "elf offset: 0x%llx", se_elfoff); - LOG_NOTICE(LOADER, "program header offset: 0x%llx", se_phdroff); - LOG_NOTICE(LOADER, "section header offset: 0x%llx", se_shdroff); - LOG_NOTICE(LOADER, "section info offset: 0x%llx", se_secinfoff); - LOG_NOTICE(LOADER, "sce version offset: 0x%llx", se_sceveroff); - LOG_NOTICE(LOADER, "control info offset: 0x%llx", se_controloff); - LOG_NOTICE(LOADER, "control info size: 0x%llx", se_controlsize); -} - -SELFLoader::SELFLoader(vfsStream& f) - : self_f(f) - , LoaderBase() -{ -} - -bool SELFLoader::LoadInfo() -{ - if(!self_f.IsOpened()) return false; - self_f.Seek(0); - sce_hdr.Load(self_f); - self_hdr.Load(self_f); - if(!sce_hdr.CheckMagic()) return false; - - return true; -} - -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(self_hdr.se_appinfooff) ) - { - LOG_ERROR(LOADER, "Broken SELF file."); - - return false; - } - - machine = l.GetMachine(); - entry = l.GetEntry(); - - return true; - - LOG_ERROR(LOADER, "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 deleted file mode 100644 index 3c4e7b9fbe..0000000000 --- a/rpcs3/Loader/SELF.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "Loader.h" - -struct vfsStream; - -struct SceHeader -{ - u32 se_magic; - u32 se_hver; - u16 se_flags; - u16 se_type; - u32 se_meta; - u64 se_hsize; - u64 se_esize; - - void Load(vfsStream& f); - - void Show(); - - bool CheckMagic() const { return se_magic == 0x53434500; } -}; - -struct SelfHeader -{ - u64 se_htype; - u64 se_appinfooff; - u64 se_elfoff; - u64 se_phdroff; - u64 se_shdroff; - u64 se_secinfoff; - u64 se_sceveroff; - u64 se_controloff; - u64 se_controlsize; - u64 pad; - - void Load(vfsStream& f); - - void Show(); -}; - -class SELFLoader : public LoaderBase -{ - vfsStream& self_f; - - SceHeader sce_hdr; - SelfHeader self_hdr; - -public: - SELFLoader(vfsStream& f); - - virtual bool LoadInfo(); - virtual bool LoadData(u64 offset = 0); -}; \ No newline at end of file diff --git a/rpcs3/Loader/TROPUSR.cpp b/rpcs3/Loader/TROPUSR.cpp index 6569ae3fd3..7d6b7fb655 100644 --- a/rpcs3/Loader/TROPUSR.cpp +++ b/rpcs3/Loader/TROPUSR.cpp @@ -133,7 +133,7 @@ bool TROPUSRLoader::Generate(const std::string& filepath, const std::string& con { if (n->GetName() == "trophy") { - u32 trophy_id = atoi(n->GetAttribute("id").c_str()); + u32 trophy_id = std::atoi(n->GetAttribute("id").c_str()); u32 trophy_grade; switch (((const char *)n->GetAttribute("ttype").c_str())[0]) { diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 2da63c0f47..969839a54d 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -239,13 +239,11 @@ - - @@ -459,13 +457,11 @@ - - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index b2ee29df86..05645dd26e 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -356,9 +356,6 @@ Emu\Memory - - Loader - Loader @@ -374,9 +371,6 @@ Loader - - Loader - Loader @@ -988,9 +982,6 @@ Emu\Memory - - Loader - Loader @@ -1006,9 +997,6 @@ Loader - - Loader - Loader diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj index e692156a04..946b6cb66e 100644 --- a/rpcs3/rpcs3.vcxproj +++ b/rpcs3/rpcs3.vcxproj @@ -173,6 +173,7 @@ + @@ -212,6 +213,7 @@ + diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters index 18a836398f..5fce1aa362 100644 --- a/rpcs3/rpcs3.vcxproj.filters +++ b/rpcs3/rpcs3.vcxproj.filters @@ -90,6 +90,9 @@ Gui + + Gui + @@ -185,5 +188,8 @@ Gui + + Gui + \ No newline at end of file diff --git a/rpcs3/stdafx.h b/rpcs3/stdafx.h index 88e422e2a3..2ca972bc49 100644 --- a/rpcs3/stdafx.h +++ b/rpcs3/stdafx.h @@ -50,7 +50,10 @@ typedef int16_t s16; typedef int32_t s32; typedef int64_t s64; -#define AlignAddr(addr, align) (((addr) + ((align) - 1)) & ~((align) - 1)) +template __forceinline T align(const T addr, int align) +{ + return (addr + (align - 1)) & ~(align - 1); +} #include "Utilities/StrFmt.h" #include "Utilities/BEType.h"