From 61a5459ccb48a25e499e1a6a82df64c3ac47e60e Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 31 Jan 2015 19:44:26 +0300 Subject: [PATCH 1/5] TLS for ARMv7 threads --- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 + rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 14 ++-- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 69 ++++++++++++++++++++ rpcs3/Emu/ARMv7/ARMv7Thread.h | 1 + rpcs3/Emu/Cell/PPUThread.cpp | 27 +------- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 28 +++----- rpcs3/Emu/System.h | 22 +++---- rpcs3/Loader/ELF32.cpp | 11 +++- rpcs3/Loader/ELF64.cpp | 5 +- 9 files changed, 115 insertions(+), 64 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 962f5dcc19..1316a26786 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -111,6 +111,8 @@ struct ARMv7Context } ITSTATE; + u32 TLS; + u32 R_ADDR; u64 R_DATA; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index ea01bcecc9..78c17f4fda 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -336,15 +336,17 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (ConditionPassed(context, cond)) { - if (cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) - { - LOG_ERROR(ARMv7, "TODO: TLS requested"); + // APSR flags are written if t = 15 - if (t < 15) + if (t < 15 && cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) + { + if (!context.TLS) { - context.GPR[t] = 0; - return; + throw "TLS not initialized"; } + + context.GPR[t] = context.TLS; + return; } throw fmt::format("Bad instruction: mrc p%d,%d,r%d,c%d,c%d,%d", cp, opc1, t, cn, cm, opc2); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 0b9710ffe2..3495376c79 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -30,6 +30,69 @@ void ARMv7Context::fast_call(u32 addr) return thread.FastCall(addr); } +#define TLS_MAX 128 + +u32 g_armv7_tls_start; + +std::array, TLS_MAX> g_armv7_tls_owners; + +void armv7_init_tls() +{ + g_armv7_tls_start = Emu.GetTLSMemsz() ? vm::cast(Memory.PSV.RAM.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096)) : 0; + + for (auto& v : g_armv7_tls_owners) + { + v.store(0, std::memory_order_relaxed); + } +} + +u32 armv7_get_tls(u32 thread) +{ + if (!Emu.GetTLSMemsz()) + { + return 0; + } + + for (u32 i = 0; i < TLS_MAX; i++) + { + if (g_armv7_tls_owners[i] == thread) + { + return g_armv7_tls_start + i * Emu.GetTLSMemsz(); // if already initialized, return TLS address + } + } + + for (u32 i = 0; i < TLS_MAX; i++) + { + u32 old = 0; + if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread)) + { + const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address + memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros + memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + return addr; + } + } + + throw "Out of TLS memory"; +} + +void armv7_free_tls(u32 thread) +{ + if (!Emu.GetTLSMemsz()) + { + return; + } + + for (auto& v : g_armv7_tls_owners) + { + u32 old = thread; + if (v.compare_exchange_strong(old, 0)) + { + return; + } + } +} + ARMv7Thread::ARMv7Thread() : CPUThread(CPU_THREAD_ARMv7) , context(*this) @@ -39,6 +102,11 @@ ARMv7Thread::ARMv7Thread() { } +ARMv7Thread::~ARMv7Thread() +{ + armv7_free_tls(GetId()); +} + void ARMv7Thread::InitRegs() { memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); @@ -47,6 +115,7 @@ void ARMv7Thread::InitRegs() context.ISET = Thumb; context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; + context.TLS = armv7_get_tls(GetId()); } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 2dd26772e7..c806f4b6c4 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -12,6 +12,7 @@ public: //const char* m_last_instr_name; ARMv7Thread(); + ~ARMv7Thread(); //void update_code(const u32 address) //{ diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 9a221b00c6..e064a54feb 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -55,7 +55,7 @@ void PPUThread::DoReset() XER.XER = 0; FPSCR.FPSCR = 0; VSCR.VSCR = 0; - VRSAVE = 0; + VRSAVE = 0; cycle = 0; } @@ -65,33 +65,8 @@ void PPUThread::InitRegs() const u32 pc = entry ? vm::read32(entry) : 0; const u32 rtoc = entry ? vm::read32(entry + 4) : 0; - //ConLog.Write("entry = 0x%x", entry); - //ConLog.Write("rtoc = 0x%x", rtoc); - SetPc(pc); - /* - const s32 thread_num = Emu.GetCPU().GetThreadNumById(GetType(), GetId()); - - if(thread_num < 0) - { - LOG_ERROR(PPU, "GetThreadNumById failed."); - Emu.Pause(); - return; - } - */ - - /* - const s32 tls_size = Emu.GetTLSFilesz() * thread_num; - - if(tls_size >= Emu.GetTLSMemsz()) - { - LOG_ERROR(PPU, "Out of TLS memory."); - Emu.Pause(); - return; - } - */ - GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200; GPR[2] = rtoc; //GPR[11] = entry; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 063655cc72..2a8d3cc699 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -23,12 +23,10 @@ Module *sysPrxForUser = nullptr; -u32 g_tls_size; // size of every thread's storage -u32 g_tls_start; // start of TLS memory area -u32 g_tls_image_addr; // address of TLS initialization area -u32 g_tls_image_size; // size of TLS initialization area +#define TLS_MAX 128 + +u32 g_tls_start; // start of TLS memory area -const u32 TLS_MAX = 256; std::array, TLS_MAX> g_tls_owners; void sys_initialize_tls() @@ -40,19 +38,16 @@ u32 ppu_get_tls(u32 thread) { if (!g_tls_start) { - g_tls_size = vm::cast(Emu.GetTLSMemsz(), "Emu.GetTLSMemsz"); // (not an address for vm::cast, but fine) - g_tls_start = vm::cast(Memory.Alloc(g_tls_size * TLS_MAX, 4096)); // memory for up to TLS_MAX threads - g_tls_image_addr = vm::cast(Emu.GetTLSAddr(), "Emu.GetTLSAddr"); - g_tls_image_size = vm::cast(Emu.GetTLSFilesz(), "Emu.GetTLSFilesz"); - - sysPrxForUser->Warning("TLS initialized (g_tls_size=0x%x, g_tls_start=0x%x, g_tls_image_addr=0x%x, g_tls_image_size=0x%x)", g_tls_size, g_tls_start, g_tls_image_addr, g_tls_image_size); + g_tls_start = vm::cast(Memory.MainMem.AllocAlign(Emu.GetTLSMemsz() * TLS_MAX, 4096)); // memory for up to TLS_MAX threads + sysPrxForUser->Notice("Thread Local Storage initialized (g_tls_start=0x%x, size = 0x%x)\n*** TLS segment addr: 0x%08x\n*** TLS segment size: 0x%08x", + g_tls_start, Emu.GetTLSMemsz(), Emu.GetTLSAddr(), Emu.GetTLSFilesz()); } for (u32 i = 0; i < TLS_MAX; i++) { if (g_tls_owners[i] == thread) { - return g_tls_start + i * g_tls_size; // if already initialized, return TLS address + return g_tls_start + i * Emu.GetTLSMemsz(); // if already initialized, return TLS address } } @@ -61,9 +56,9 @@ u32 ppu_get_tls(u32 thread) u32 old = 0; if (g_tls_owners[i].compare_exchange_strong(old, thread)) { - const u32 addr = g_tls_start + i * g_tls_size; // get TLS address - memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros - memcpy(vm::get_ptr(addr), vm::get_ptr(g_tls_image_addr), g_tls_image_size); // initialize from TLS image + const u32 addr = g_tls_start + i * Emu.GetTLSMemsz(); // get TLS address + memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros + memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image return addr; } } @@ -420,10 +415,7 @@ void sysPrxForUser_init(Module *pxThis) { sysPrxForUser = pxThis; - g_tls_size = 0; g_tls_start = 0; - g_tls_image_addr = 0; - g_tls_image_size = 0; for (auto& v : g_tls_owners) { v.store(0, std::memory_order_relaxed); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index a4901089b3..d9615e2613 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -28,9 +28,9 @@ struct VFS; struct EmuInfo { private: - u64 tls_addr; - u64 tls_filesz; - u64 tls_memsz; + u32 tls_addr; + u32 tls_filesz; + u32 tls_memsz; sys_process_param_info proc_param; @@ -50,16 +50,16 @@ public: proc_param.primary_prio = be_t::make(0x50); } - void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) + void SetTLSData(u32 addr, u32 filesz, u32 memsz) { tls_addr = addr; tls_filesz = filesz; tls_memsz = memsz; } - u64 GetTLSAddr() const { return tls_addr; } - u64 GetTLSFilesz() const { return tls_filesz; } - u64 GetTLSMemsz() const { return tls_memsz; } + u32 GetTLSAddr() const { return tls_addr; } + u32 GetTLSFilesz() const { return tls_filesz; } + u32 GetTLSMemsz() const { return tls_memsz; } }; class ModuleInitializer @@ -173,7 +173,7 @@ public: m_modules_init.push_back(std::move(m)); } - void SetTLSData(const u64 addr, const u64 filesz, const u64 memsz) + void SetTLSData(u32 addr, u32 filesz, u32 memsz) { m_info.SetTLSData(addr, filesz, memsz); } @@ -195,9 +195,9 @@ public: EmuInfo& GetInfo() { return m_info; } - u64 GetTLSAddr() const { return m_info.GetTLSAddr(); } - u64 GetTLSFilesz() const { return m_info.GetTLSFilesz(); } - u64 GetTLSMemsz() const { return m_info.GetTLSMemsz(); } + u32 GetTLSAddr() const { return m_info.GetTLSAddr(); } + u32 GetTLSFilesz() const { return m_info.GetTLSFilesz(); } + u32 GetTLSMemsz() const { return m_info.GetTLSMemsz(); } u32 GetMallocPageSize() { return m_info.GetProcParam().malloc_pagesize; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 01232eb579..9c7f19d0c2 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -11,6 +11,8 @@ #include "Emu/ARMv7/PSVFuncList.h" #include "Emu/System.h" +extern void armv7_init_tls(); + namespace loader { namespace handlers @@ -235,9 +237,13 @@ namespace loader } else if (!strcmp(name.c_str(), ".tbss")) { - LOG_NOTICE(LOADER, ".tbss analysis"); + LOG_NOTICE(LOADER, ".tbss analysis..."); + const u32 img_addr = shdr.data_le.sh_addr; // start address of TLS initialization image + const u32 img_size = (&shdr)[1].data_le.sh_addr - img_addr; // calculate its size as the difference between sections + const u32 tls_size = shdr.data_le.sh_size; // full size of TLS - LOG_ERROR(LOADER, "TLS: size=0x%08x", shdr.data_le.sh_size); + LOG_WARNING(LOADER, "TLS: img_addr=0x%08x, img_size=0x%x, tls_size=0x%x", img_addr, img_size, tls_size); + Emu.SetTLSData(img_addr, img_size, tls_size); } else if (!strcmp(name.c_str(), ".sceRefs.rodata")) { @@ -314,6 +320,7 @@ namespace loader } } + armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); arm7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index de2a78c0a6..ac64afc207 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -422,7 +422,10 @@ namespace loader break; case 0x00000007: //TLS - Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value()); + Emu.SetTLSData( + vm::cast(phdr.p_vaddr.addr(), "TLS: phdr.p_vaddr"), + vm::cast(phdr.p_filesz.value(), "TLS: phdr.p_filesz"), + vm::cast(phdr.p_memsz.value(), "TLS: phdr.p_memsz")); break; case 0x60000001: //LOOS+1 From 8a945a1a52b47b686871978de245b092d7d1a578 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Feb 2015 10:09:24 +0300 Subject: [PATCH 2/5] Fixes --- rpcs3/Emu/ARMv7/ARMv7Context.h | 35 +++++++++++--------- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 12 ++++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 6 ++-- rpcs3/Emu/Cell/SPUThread.cpp | 2 ++ rpcs3/Emu/Memory/Memory.cpp | 2 +- rpcs3/Emu/Memory/vm_ref.h | 2 ++ rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 7 +++- rpcs3/Emu/SysCalls/lv2/sys_spu.cpp | 6 ++-- 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 1316a26786..692592e5ec 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -37,6 +37,25 @@ struct ARMv7Context }; u32 LR; + + union + { + struct + { + u32 reserved0 : 16; + u32 GE : 4; + u32 reserved1 : 4; + u32 dummy : 3; + u32 Q : 1; // Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result + u32 V : 1; // Overflow condition code flag + u32 C : 1; // Carry condition code flag + u32 Z : 1; // Zero condition code flag + u32 N : 1; // Negative condition code flag + }; + + u32 APSR; + + } APSR; }; struct @@ -45,22 +64,6 @@ struct ARMv7Context }; }; - union - { - struct - { - u32 N : 1; //Negative condition code flag - u32 Z : 1; //Zero condition code flag - u32 C : 1; //Carry condition code flag - u32 V : 1; //Overflow condition code flag - u32 Q : 1; //Set to 1 if an SSAT or USAT instruction changes (saturates) the input value for the signed or unsigned range of the result - u32 dummy : 27; - }; - - u32 APSR; - - } APSR; - union { struct diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 78c17f4fda..6ea768832b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -316,10 +316,10 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 switch (type) { - case T1: - case A1: + case T1: case A1: + case T2: case A2: { - cond = context.ITSTATE.advance(); + cond = type == A1 ? code.data >> 28 : context.ITSTATE.advance(); t = (code.data & 0xf000) >> 12; cp = (code.data & 0xf00) >> 8; opc1 = (code.data & 0xe00000) >> 21; @@ -327,8 +327,8 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 cn = (code.data & 0xf0000) >> 16; cm = (code.data & 0xf); - reject(cp - 10 < 2, "Advanced SIMD and VFP"); - reject(t == 13 && type == T1, "UNPREDICTABLE"); + reject(cp - 10 < 2 && (type == T1 || type == A1), "Advanced SIMD and VFP"); + reject(t == 13 && (type == T1 || type == T2), "UNPREDICTABLE"); break; } default: throw __FUNCTION__; @@ -340,6 +340,8 @@ void ARMv7_instrs::MRC_(ARMv7Context& context, const ARMv7Code code, const ARMv7 if (t < 15 && cp == 15 && opc1 == 0 && cn == 13 && cm == 0 && opc2 == 3) { + // Read CP15 User Read-only Thread ID Register (seems used as TLS address) + if (!context.TLS) { throw "TLS not initialized"; diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 3495376c79..1a968dd858 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -48,7 +48,7 @@ void armv7_init_tls() u32 armv7_get_tls(u32 thread) { - if (!Emu.GetTLSMemsz()) + if (!Emu.GetTLSMemsz() || !thread) { return 0; } @@ -67,8 +67,8 @@ u32 armv7_get_tls(u32 thread) if (g_armv7_tls_owners[i].compare_exchange_strong(old, thread)) { const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address - memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros return addr; } } @@ -112,7 +112,7 @@ void ARMv7Thread::InitRegs() memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); context.APSR.APSR = 0; context.IPSR.IPSR = 0; - context.ISET = Thumb; + //context.ISET = Thumb; context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index c4cf028f8f..1c861da43c 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -99,6 +99,8 @@ void SPUThread::InitRegs() m_event_mask = 0; m_events = 0; + + R_ADDR = 0; } void SPUThread::DoRun() diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 84f75c6fff..502694ff93 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -131,7 +131,7 @@ void MemoryBase::Init(MemoryType type) case Memory_PSV: MemoryBlocks.push_back(PSV.RAM.SetRange(0x81000000, 0x10000000)); - MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x10000000)); + MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x2F000000)); break; case Memory_PSP: diff --git a/rpcs3/Emu/Memory/vm_ref.h b/rpcs3/Emu/Memory/vm_ref.h index 5788457c3b..f7256cedff 100644 --- a/rpcs3/Emu/Memory/vm_ref.h +++ b/rpcs3/Emu/Memory/vm_ref.h @@ -10,6 +10,8 @@ namespace vm public: typedef T type; + static_assert(!std::is_pointer::value, "vm::_ref_base<> error: invalid type (pointer)"); + static_assert(!std::is_reference::value, "vm::_ref_base<> error: invalid type (reference)"); typedef typename remove_be_t::type le_type; typedef typename to_be_t::type be_type; diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 2a8d3cc699..3fc79e4256 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -42,6 +42,11 @@ u32 ppu_get_tls(u32 thread) sysPrxForUser->Notice("Thread Local Storage initialized (g_tls_start=0x%x, size = 0x%x)\n*** TLS segment addr: 0x%08x\n*** TLS segment size: 0x%08x", g_tls_start, Emu.GetTLSMemsz(), Emu.GetTLSAddr(), Emu.GetTLSFilesz()); } + + if (!thread) + { + return 0; + } for (u32 i = 0; i < TLS_MAX; i++) { @@ -57,8 +62,8 @@ u32 ppu_get_tls(u32 thread) if (g_tls_owners[i].compare_exchange_strong(old, thread)) { const u32 addr = g_tls_start + i * Emu.GetTLSMemsz(); // get TLS address - memset(vm::get_ptr(addr), 0, Emu.GetTLSMemsz()); // fill TLS area with zeros memcpy(vm::get_ptr(addr), vm::get_ptr(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image + memset(vm::get_ptr(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros return addr; } } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index 29cdb9bd39..f3fb23b383 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -85,10 +85,10 @@ SPUThread* spu_thread_initialize(std::shared_ptr& group, u32 spu_n sys_spu.Todo("Unsupported SPU Thread options (0x%x)", option); } - u32 spu_ep = (u32)img.entry_point; + const u32 spu_ep = img.entry_point; // Copy SPU image: // TODO: use segment info - u32 spu_offset = (u32)Memory.Alloc(256 * 1024, 4096); + const u32 spu_offset = vm::cast(Memory.MainMem.AllocAlign(256 * 1024, 4096)); memcpy(vm::get_ptr(spu_offset), vm::get_ptr(img.addr), 256 * 1024); SPUThread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_SPU)); @@ -218,7 +218,7 @@ s32 sys_spu_thread_group_destroy(u32 id) std::shared_ptr t = Emu.GetCPU().GetThread(group_info->list[i]); if (t) { - Memory.Free(((SPUThread*)t.get())->GetOffset()); + Memory.MainMem.Free(((SPUThread*)t.get())->GetOffset()); Emu.GetCPU().RemoveThread(group_info->list[i]); } } From e5dd03dbcb042c93f00a112f4b5e0f661245cd81 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 1 Feb 2015 16:52:34 +0300 Subject: [PATCH 3/5] ARMv7: argc, argv setting, LDRSB_IMM, bugfixes --- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 3 +- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 61 ++++++++++++++++++++++++++-- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 61 ++++++++++++++++++++++++++-- rpcs3/Emu/ARMv7/ARMv7Thread.h | 56 ++++--------------------- rpcs3/Emu/CPU/CPUThread.cpp | 11 ----- rpcs3/Emu/CPU/CPUThread.h | 11 +++-- rpcs3/Emu/Cell/PPCThread.cpp | 15 ------- rpcs3/Emu/Cell/PPCThread.h | 3 -- rpcs3/Emu/Cell/PPUThread.cpp | 18 ++++++++ rpcs3/Emu/Cell/PPUThread.h | 6 ++- rpcs3/Emu/Cell/SPUThread.cpp | 11 +++++ rpcs3/Emu/Cell/SPUThread.h | 2 + rpcs3/Emu/Memory/vm.cpp | 22 ++++++++-- rpcs3/Loader/ELF32.cpp | 2 +- 14 files changed, 184 insertions(+), 98 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index fac6873a33..ce2dbb6914 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include #include "Utilities/Log.h" +#include "Emu/Memory/Memory.h" #include "ARMv7Thread.h" #include "ARMv7Interpreter.h" #include "ARMv7Opcodes.h" @@ -1262,7 +1263,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += 16; } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", g_opct.size()); + LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); } u32 ARMv7Decoder::DecodeMemory(const u32 address) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 6ea768832b..c204351616 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -191,7 +191,7 @@ namespace ARMv7_instrs template T AddWithCarry(T x, T y, bool carry_in, bool& carry_out, bool& overflow) { - const T sign_mask = (T)1 << (sizeof(T) - 1); + const T sign_mask = (T)1 << (sizeof(T) * 8 - 1); T result = x + y; carry_out = ((x & y) | ((x ^ y) & ~result)) & sign_mask; @@ -823,6 +823,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en if (ConditionPassed(context, cond)) { + //LOG_NOTICE(ARMv7, "Branch to 0x%x (cond=0x%x)", context.thread.PC + jump, cond); context.thread.SetBranch(context.thread.PC + jump); } } @@ -1174,6 +1175,7 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR } case T3: { + cond = context.ITSTATE.advance(); n = (code.data & 0xf0000) >> 16; m = (code.data & 0xf); shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n); @@ -1187,13 +1189,17 @@ void ARMv7_instrs::CMP_REG(ARMv7Context& context, const ARMv7Code code, const AR if (ConditionPassed(context, cond)) { + const u32 m_value = context.read_gpr(m); + const u32 n_value = context.read_gpr(n); bool carry, overflow; - const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true); - const u32 res = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); + const u32 shifted = Shift(m_value, shift_t, shift_n, true); + const u32 res = AddWithCarry(n_value, ~shifted, true, carry, overflow); context.APSR.N = res >> 31; context.APSR.Z = res == 0; context.APSR.C = carry; context.APSR.V = overflow; + + //LOG_NOTICE(ARMv7, "CMP: r%d=0x%08x <> r%d=0x%08x, shifted=0x%08x, res=0x%08x", n, n_value, m, m_value, shifted, res); } } @@ -1619,11 +1625,60 @@ void ARMv7_instrs::LDRH_REG(ARMv7Context& context, const ARMv7Code code, const A void ARMv7_instrs::LDRSB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) { + u32 cond, t, n, imm32; + bool index, add, wback; + switch (type) { + case T1: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xfff); + index = true; + add = true; + wback = false; + + reject(t == 15, "PLI"); + reject(n == 15, "LDRSB (literal)"); + reject(t == 13, "UNPREDICTABLE"); + break; + } + case T2: + { + cond = context.ITSTATE.advance(); + t = (code.data & 0xf000) >> 12; + n = (code.data & 0xf0000) >> 16; + imm32 = (code.data & 0xff); + index = (code.data & 0x400); + add = (code.data & 0x200); + wback = (code.data & 0x100); + + reject(t == 15 && index && !add && !wback, "PLI"); + reject(n == 15, "LDRSB (literal)"); + reject(index && add && !wback, "LDRSBT"); + reject(!index && !wback, "UNDEFINED"); + reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE"); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(context, cond)) + { + const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; + const u32 addr = index ? offset_addr : context.read_gpr(n); + const s8 value = vm::psv::read8(addr); + + context.write_gpr(t, value); // sign-extend + + if (wback) + { + context.write_gpr(n, offset_addr); + } + } } void ARMv7_instrs::LDRSB_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 1a968dd858..f58acfd0d3 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -120,10 +120,19 @@ void ARMv7Thread::InitRegs() void ARMv7Thread::InitStack() { - if(!m_stack_addr) + if (!m_stack_addr) { - m_stack_size = 0x10000; - m_stack_addr = (u32)Memory.Alloc(0x10000, 1); + assert(m_stack_size); + m_stack_addr = vm::cast(Memory.Alloc(m_stack_size, 4096)); + } +} + +void ARMv7Thread::CloseStack() +{ + if (m_stack_addr) + { + Memory.Free(m_stack_addr); + m_stack_addr = 0; } } @@ -218,7 +227,7 @@ void ARMv7Thread::FastStop() m_status = Stopped; } -arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) +armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); @@ -229,3 +238,47 @@ arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 argc = 0; } + +cpu_thread& armv7_thread::args(std::initializer_list values) +{ + assert(argc == 0); + + if (!values.size()) + { + return *this; + } + + std::vector argv_data; + u32 argv_size = 0; + + for (auto& arg : values) + { + const u32 arg_size = vm::cast(arg.size(), "arg.size()"); // get arg size + + for (char c : arg) + { + argv_data.push_back(c); // append characters + } + + argv_data.push_back('\0'); // append null terminator + + argv_size += arg_size + 1; + argc++; + } + + argv = vm::cast(Memory.PSV.RAM.AllocAlign(argv_size, 4096)); // allocate arg list + memcpy(vm::get_ptr(argv), argv_data.data(), argv_size); // copy arg list + + return *this; +} + +cpu_thread& armv7_thread::run() +{ + thread->Run(); + + // set arguments + static_cast(thread)->context.GPR[0] = argc; + static_cast(thread)->context.GPR[1] = argv; + + return *this; +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index c806f4b6c4..a8a0f75311 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -1,29 +1,19 @@ #pragma once #include "Emu/CPU/CPUThread.h" -#include "Emu/Memory/Memory.h" #include "ARMv7Context.h" class ARMv7Thread : public CPUThread { public: ARMv7Context context; - //u32 m_arg; - //u8 m_last_instr_size; - //const char* m_last_instr_name; ARMv7Thread(); ~ARMv7Thread(); - //void update_code(const u32 address) - //{ - // code.code0 = vm::psv::read16(address & ~1); - // code.code1 = vm::psv::read16(address + 2 & ~1); - // m_arg = address & 0x1 ? code.code1 << 16 | code.code0 : code.data; - //} - public: virtual void InitRegs(); virtual void InitStack(); + virtual void CloseStack(); u32 GetStackArg(u32 pos); void FastCall(u32 addr); void FastStop(); @@ -42,48 +32,16 @@ protected: virtual void DoCode(); }; -class arm7_thread : cpu_thread + +class armv7_thread : cpu_thread { - static const u32 stack_align = 0x10; - vm::ptr argv; + u32 argv; u32 argc; - vm::ptr envp; public: - arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0); + armv7_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; + cpu_thread& args(std::initializer_list values) override; - //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[0] = argc; - //static_cast(thread)->GPR[1] = argv.addr(); - //static_cast(thread)->GPR[2] = envp.addr(); - - return *this; - } + cpu_thread& run() override; }; diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index a69ec8338a..b2224af9c0 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -64,17 +64,6 @@ void CPUThread::Reset() DoReset(); } -void CPUThread::CloseStack() -{ - if(m_stack_addr) - { - Memory.StackMem.Free(m_stack_addr); - m_stack_addr = 0; - } - - m_stack_size = 0; -} - void CPUThread::SetId(const u32 id) { m_id = id; diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index dd79700c65..35010483cc 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -1,8 +1,7 @@ #pragma once - #include "Utilities/Thread.h" -enum CPUThreadType :unsigned char +enum CPUThreadType : unsigned char { CPU_THREAD_PPU, CPU_THREAD_SPU, @@ -46,10 +45,10 @@ protected: bool m_trace_call_stack; public: - virtual void InitRegs()=0; + virtual void InitRegs() = 0; - virtual void InitStack()=0; - virtual void CloseStack(); + virtual void InitStack() = 0; + virtual void CloseStack() = 0; u32 GetStackAddr() const { return m_stack_addr; } u32 GetStackSize() const { return m_stack_size; } @@ -271,4 +270,4 @@ public: { return thread->GetId(); } -}; \ No newline at end of file +}; diff --git a/rpcs3/Emu/Cell/PPCThread.cpp b/rpcs3/Emu/Cell/PPCThread.cpp index 4248fd58a8..4d77900d90 100644 --- a/rpcs3/Emu/Cell/PPCThread.cpp +++ b/rpcs3/Emu/Cell/PPCThread.cpp @@ -25,18 +25,3 @@ PPCThread::~PPCThread() void PPCThread::DoReset() { } - -void PPCThread::InitStack() -{ - if(m_stack_addr) return; - if(m_stack_size == 0) m_stack_size = 0x10000; - m_stack_addr = (u32)Memory.StackMem.AllocAlign(m_stack_size, 0x100); - /* - m_stack_point += m_stack_size - 0x10; - m_stack_point &= -0x10; - vm::write64(m_stack_point, 0); - m_stack_point -= 0x60; - vm::write64(m_stack_point, m_stack_point + 0x60); - */ -} - diff --git a/rpcs3/Emu/Cell/PPCThread.h b/rpcs3/Emu/Cell/PPCThread.h index 99471f7a80..2c3fa5c05b 100644 --- a/rpcs3/Emu/Cell/PPCThread.h +++ b/rpcs3/Emu/Cell/PPCThread.h @@ -4,9 +4,6 @@ class PPCThread : public CPUThread { public: - virtual void InitRegs()=0; - virtual void InitStack(); - virtual std::string GetThreadName() const { return fmt::format("%s[0x%08x]", GetFName(), PC); diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index e064a54feb..e6d229583a 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -80,6 +80,24 @@ void PPUThread::InitRegs() TB = 0; } +void PPUThread::InitStack() +{ + if (!m_stack_addr) + { + assert(m_stack_size); + m_stack_addr = vm::cast(Memory.StackMem.AllocAlign(m_stack_size, 4096)); + } +} + +void PPUThread::CloseStack() +{ + if (m_stack_addr) + { + Memory.StackMem.Free(m_stack_addr); + m_stack_addr = 0; + } +} + void PPUThread::DoRun() { switch(Ini.CPUDecoderMode.GetValue()) diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 51722f1645..820b244c2b 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -799,8 +799,10 @@ public: } public: - virtual void InitRegs(); - virtual void Task(); + virtual void InitRegs() override; + virtual void InitStack() override; + virtual void CloseStack() override; + virtual void Task() override; u64 GetStackArg(s32 i); u64 FastCall2(u32 addr, u32 rtoc); void FastStop(); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 1c861da43c..f5faf9fff1 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -103,6 +103,17 @@ void SPUThread::InitRegs() R_ADDR = 0; } +void SPUThread::InitStack() +{ + m_stack_size = 0x1000; // this value is wrong + m_stack_addr = m_offset + 0x40000 - m_stack_size; // stack is the part of SPU Local Storage +} + +void SPUThread::CloseStack() +{ + // nothing to do here +} + void SPUThread::DoRun() { switch(Ini.SPUDecoderMode.GetValue()) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 50d70b1c7f..c2e2cc2f03 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -568,6 +568,8 @@ public: public: virtual void InitRegs(); + virtual void InitStack(); + virtual void CloseStack(); virtual void Task(); void FastCall(u32 ls_addr); void FastStop(); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 2c23ecdb66..69e42e62cb 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -2,6 +2,7 @@ #include "Memory.h" #include "Emu/CPU/CPUThread.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/ARMv7/ARMv7Thread.h" namespace vm { @@ -167,13 +168,14 @@ namespace vm u32 stack_push(CPUThread& CPU, u32 size, u32 align_v, u32& old_pos) { + assert(align_v); + switch (CPU.GetType()) { case CPU_THREAD_PPU: { PPUThread& PPU = static_cast(CPU); - assert(align_v); old_pos = (u32)PPU.GPR[1]; PPU.GPR[1] -= align(size, 8); // room minimal possible size PPU.GPR[1] &= ~(align_v - 1); // fix stack alignment @@ -199,8 +201,22 @@ namespace vm case CPU_THREAD_ARMv7: { - assert(!"stack_push(): ARMv7 not supported"); - return 0; + ARMv7Context& context = static_cast(CPU).context; + + old_pos = context.SP; + context.SP -= align(size, 4); // room minimal possible size + context.SP &= ~(align_v - 1); // fix stack alignment + + if (context.SP < CPU.GetStackAddr()) + { + // stack overflow + context.SP = old_pos; + return 0; + } + else + { + return context.SP; + } } default: diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 9c7f19d0c2..c622308f3d 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -323,7 +323,7 @@ namespace loader armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); - arm7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); + armv7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "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; From dab80497bbbd39141914a4b918732129f52c7ae2 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 2 Feb 2015 00:12:40 +0300 Subject: [PATCH 4/5] ARMv7: bugfix, loader improved, scePerf --- rpcs3/Emu/ARMv7/ARMv7Context.h | 8 + rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 1 + rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 12 +- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 18 +- rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp | 9 +- rpcs3/Emu/ARMv7/Modules/scePerf.cpp | 222 +++++++++++++++++++++-- rpcs3/Loader/ELF32.cpp | 108 +++++++++-- 7 files changed, 330 insertions(+), 48 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index 692592e5ec..fa9e04c64d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -119,6 +119,14 @@ struct ARMv7Context u32 R_ADDR; u64 R_DATA; + struct perf_counter + { + u32 event; + u32 value; + }; + + std::array counters; + void write_gpr(u32 n, u32 value) { assert(n < 16); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index f58acfd0d3..6e1cec6fa8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -116,6 +116,7 @@ void ARMv7Thread::InitRegs() context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); + context.R_ADDR = 0; } void ARMv7Thread::InitStack() diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index f4705ab1d8..dbbce2e151 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -42,7 +42,7 @@ s32 sceKernelCreateThread( s32 cpuAffinityMask, vm::psv::ptr pOptParam) { - sceLibKernel.Error("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)", + sceLibKernel.Warning("sceKernelCreateThread(pName=0x%x, entry=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=0x%x)", pName, entry, initPriority, stackSize, attr, cpuAffinityMask, pOptParam); ARMv7Thread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7)); @@ -61,7 +61,7 @@ s32 sceKernelCreateThread( s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pArgBlock) { - sceLibKernel.Error("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock); + sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=0x%x)", threadId, argSize, pArgBlock); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); @@ -93,7 +93,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pAr s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus) { - sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus); // exit status is stored in r0 context.thread.Stop(); @@ -103,7 +103,7 @@ s32 sceKernelExitThread(ARMv7Context& context, s32 exitStatus) s32 sceKernelDeleteThread(s32 threadId) { - sceLibKernel.Error("sceKernelDeleteThread(threadId=0x%x)", threadId); + sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); @@ -125,7 +125,7 @@ s32 sceKernelDeleteThread(s32 threadId) s32 sceKernelExitDeleteThread(ARMv7Context& context, s32 exitStatus) { - sceLibKernel.Error("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); // exit status is stored in r0 context.thread.Stop(); @@ -261,7 +261,7 @@ s32 sceKernelDelayThreadCB(u32 usec) s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr pExitStatus, vm::psv::ptr pTimeout) { - sceLibKernel.Error("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout); + sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=0x%x, pTimeout=0x%x)", threadId, pExitStatus, pTimeout); std::shared_ptr t = Emu.GetCPU().GetThread(threadId, CPU_THREAD_ARMv7); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index b833a38c5f..d280e3dc24 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -16,7 +16,7 @@ namespace sce_libc_func { void __cxa_atexit(vm::psv::ptr func, vm::psv::ptr arg, vm::psv::ptr dso) { - sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso); + sceLibc.Warning("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso); LV2_LOCK(0); @@ -28,7 +28,7 @@ namespace sce_libc_func void __aeabi_atexit(vm::psv::ptr arg, vm::psv::ptr func, vm::psv::ptr dso) { - sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso); + sceLibc.Warning("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso); LV2_LOCK(0); @@ -40,7 +40,7 @@ namespace sce_libc_func void exit(ARMv7Context& context) { - sceLibc.Error("exit()"); + sceLibc.Warning("exit()"); LV2_LOCK(0); @@ -117,7 +117,7 @@ namespace sce_libc_func void printf(ARMv7Context& context, vm::psv::ptr fmt) // va_args... { - sceLibc.Error("printf(fmt=0x%x)", fmt); + sceLibc.Warning("printf(fmt=0x%x)", fmt); sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); @@ -126,7 +126,7 @@ namespace sce_libc_func void sprintf(ARMv7Context& context, vm::psv::ptr str, vm::psv::ptr fmt) // va_args... { - sceLibc.Error("sprintf(str=0x%x, fmt=0x%x)", str, fmt); + sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt); sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr()); @@ -139,28 +139,28 @@ namespace sce_libc_func void __cxa_set_dso_handle_main(vm::psv::ptr dso) { - sceLibc.Error("__cxa_set_dso_handle_main(dso=0x%x)", dso); + sceLibc.Warning("__cxa_set_dso_handle_main(dso=0x%x)", dso); g_dso = dso; } void memcpy(vm::psv::ptr dst, vm::psv::ptr src, u32 size) { - sceLibc.Error("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size); + sceLibc.Warning("memcpy(dst=0x%x, src=0x%x, size=0x%x)", dst, src, size); ::memcpy(dst.get_ptr(), src.get_ptr(), size); } void memset(vm::psv::ptr dst, s32 value, u32 size) { - sceLibc.Error("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size); + sceLibc.Warning("memset(dst=0x%x, value=%d, size=0x%x)", dst, value, size); ::memset(dst.get_ptr(), value, size); } void _Assert(vm::psv::ptr text, vm::psv::ptr func) { - sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func); + sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func); LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr()); Emu.Pause(); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp index f0f2674441..73260d9420 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibstdcxx.cpp @@ -8,20 +8,17 @@ namespace sce_libstdcxx_func { void __aeabi_unwind_cpp_pr0() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } void __aeabi_unwind_cpp_pr1() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } void __aeabi_unwind_cpp_pr2() { - sceLibstdcxx.Todo(__FUNCTION__); - Emu.Pause(); + throw __FUNCTION__; } } diff --git a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp index d83e6d5f22..e7939506bc 100644 --- a/rpcs3/Emu/ARMv7/Modules/scePerf.cpp +++ b/rpcs3/Emu/ARMv7/Modules/scePerf.cpp @@ -2,48 +2,242 @@ #include "Emu/System.h" #include "Emu/ARMv7/PSVFuncList.h" +#include "Emu/SysCalls/lv2/sys_time.h" + +#define RETURN_ERROR(code) { Emu.Pause(); scePerf.Error("%s() failed: %s", __FUNCTION__, #code); return code; } + extern psv_log_base scePerf; -s32 scePerfArmPmonReset(s32 threadId) +enum { - scePerf.Todo("scePerfArmPmonReset(threadId=0x%x)", threadId); + // Error Codes + SCE_PERF_ERROR_INVALID_ARGUMENT = 0x80580000, +}; + +enum : s32 +{ + // Thread IDs + SCE_PERF_ARM_PMON_THREAD_ID_ALL = -1, + SCE_PERF_ARM_PMON_THREAD_ID_SELF = 0, +}; + +enum : u32 +{ + // Counter Numbers + SCE_PERF_ARM_PMON_CYCLE_COUNTER = 31, + SCE_PERF_ARM_PMON_COUNTER_5 = 5, + SCE_PERF_ARM_PMON_COUNTER_4 = 4, + SCE_PERF_ARM_PMON_COUNTER_3 = 3, + SCE_PERF_ARM_PMON_COUNTER_2 = 2, + SCE_PERF_ARM_PMON_COUNTER_1 = 1, + SCE_PERF_ARM_PMON_COUNTER_0 = 0, + + // Counter Masks + SCE_PERF_ARM_PMON_COUNTER_MASK_5 = 0x20, + SCE_PERF_ARM_PMON_COUNTER_MASK_4 = 0x10, + SCE_PERF_ARM_PMON_COUNTER_MASK_3 = 0x08, + SCE_PERF_ARM_PMON_COUNTER_MASK_2 = 0x04, + SCE_PERF_ARM_PMON_COUNTER_MASK_1 = 0x02, + SCE_PERF_ARM_PMON_COUNTER_MASK_0 = 0x01, + SCE_PERF_ARM_PMON_COUNTER_MASK_ALL = 0x3f, +}; + +enum : u8 +{ + // Performance Counter Events + SCE_PERF_ARM_PMON_SOFT_INCREMENT = 0x00, + SCE_PERF_ARM_PMON_ICACHE_MISS = 0x01, + SCE_PERF_ARM_PMON_ITLB_MISS = 0x02, + SCE_PERF_ARM_PMON_DCACHE_MISS = 0x03, + SCE_PERF_ARM_PMON_DCACHE_ACCESS = 0x04, + SCE_PERF_ARM_PMON_DTLB_MISS = 0x05, + SCE_PERF_ARM_PMON_DATA_READ = 0x06, + SCE_PERF_ARM_PMON_DATA_WRITE = 0x07, + SCE_PERF_ARM_PMON_EXCEPTION_TAKEN = 0x09, + SCE_PERF_ARM_PMON_EXCEPTION_RETURN = 0x0A, + SCE_PERF_ARM_PMON_WRITE_CONTEXTID = 0x0B, + SCE_PERF_ARM_PMON_SOFT_CHANGEPC = 0x0C, + SCE_PERF_ARM_PMON_IMMEDIATE_BRANCH = 0x0D, + SCE_PERF_ARM_PMON_UNALIGNED = 0x0F, + SCE_PERF_ARM_PMON_BRANCH_MISPREDICT = 0x10, + SCE_PERF_ARM_PMON_PREDICT_BRANCH = 0x12, + SCE_PERF_ARM_PMON_COHERENT_LF_MISS = 0x50, + SCE_PERF_ARM_PMON_COHERENT_LF_HIT = 0x51, + SCE_PERF_ARM_PMON_ICACHE_STALL = 0x60, + SCE_PERF_ARM_PMON_DCACHE_STALL = 0x61, + SCE_PERF_ARM_PMON_MAINTLB_STALL = 0x62, + SCE_PERF_ARM_PMON_STREX_PASSED = 0x63, + SCE_PERF_ARM_PMON_STREX_FAILED = 0x64, + SCE_PERF_ARM_PMON_DATA_EVICTION = 0x65, + SCE_PERF_ARM_PMON_ISSUE_NO_DISPATCH = 0x66, + SCE_PERF_ARM_PMON_ISSUE_EMPTY = 0x67, + SCE_PERF_ARM_PMON_INST_RENAME = 0x68, + SCE_PERF_ARM_PMON_PREDICT_FUNC_RET = 0x6E, + SCE_PERF_ARM_PMON_MAIN_PIPE = 0x70, + SCE_PERF_ARM_PMON_SECOND_PIPE = 0x71, + SCE_PERF_ARM_PMON_LS_PIPE = 0x72, + SCE_PERF_ARM_PMON_FPU_RENAME = 0x73, + SCE_PERF_ARM_PMON_PLD_STALL = 0x80, + SCE_PERF_ARM_PMON_WRITE_STALL = 0x81, + SCE_PERF_ARM_PMON_INST_MAINTLB_STALL = 0x82, + SCE_PERF_ARM_PMON_DATA_MAINTLB_STALL = 0x83, + SCE_PERF_ARM_PMON_INST_UTLB_STALL = 0x84, + SCE_PERF_ARM_PMON_DATA_UTLB_STALL = 0x85, + SCE_PERF_ARM_PMON_DMB_STALL = 0x86, + SCE_PERF_ARM_PMON_INTEGER_CLOCK = 0x8A, + SCE_PERF_ARM_PMON_DATAENGINE_CLOCK = 0x8B, + SCE_PERF_ARM_PMON_ISB = 0x90, + SCE_PERF_ARM_PMON_DSB = 0x91, + SCE_PERF_ARM_PMON_DMB = 0x92, + SCE_PERF_ARM_PMON_EXT_INTERRUPT = 0x93, + SCE_PERF_ARM_PMON_PLE_LINE_REQ_COMPLETED = 0xA0, + SCE_PERF_ARM_PMON_PLE_CHANNEL_SKIPPED = 0xA1, + SCE_PERF_ARM_PMON_PLE_FIFO_FLUSH = 0xA2, + SCE_PERF_ARM_PMON_PLE_REQ_COMPLETED = 0xA3, + SCE_PERF_ARM_PMON_PLE_FIFO_OVERFLOW = 0xA4, + SCE_PERF_ARM_PMON_PLE_REQ_PROGRAMMED = 0xA5, +}; + +s32 scePerfArmPmonReset(ARMv7Context& context, s32 threadId) +{ + scePerf.Warning("scePerfArmPmonReset(threadId=0x%x)", threadId); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + context.counters = {}; return SCE_OK; } -s32 scePerfArmPmonSelectEvent(s32 threadId, u32 counter, u8 eventCode) +s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter, u8 eventCode) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonSelectEvent(threadId=0x%x, counter=0x%x, eventCode=0x%x)", threadId, counter, eventCode); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + if (counter >= 6) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + u32 value = 0; // initial value + + switch (eventCode) + { + case SCE_PERF_ARM_PMON_SOFT_INCREMENT: break; + + case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT: + case SCE_PERF_ARM_PMON_DCACHE_MISS: + case SCE_PERF_ARM_PMON_UNALIGNED: + { + value = 1; // these events will probably never be implemented + break; + } + + case SCE_PERF_ARM_PMON_PREDICT_BRANCH: + case SCE_PERF_ARM_PMON_DCACHE_ACCESS: + { + value = 1000; // these events will probably never be implemented + break; + } + + default: throw "scePerfArmPmonSelectEvent(): unknown event requested"; + } + + context.counters[counter].event = eventCode; + context.counters[counter].value = value; + + return SCE_OK; } -s32 scePerfArmPmonStart(s32 threadId) +s32 scePerfArmPmonStart(ARMv7Context& context, s32 threadId) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonStart(threadId=0x%x)", threadId); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + return SCE_OK; } -s32 scePerfArmPmonStop(s32 threadId) +s32 scePerfArmPmonStop(ARMv7Context& context, s32 threadId) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonStop(threadId=0x%x)"); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + return SCE_OK; } -s32 scePerfArmPmonGetCounterValue(s32 threadId, u32 counter, vm::psv::ptr pValue) +s32 scePerfArmPmonGetCounterValue(ARMv7Context& context, s32 threadId, u32 counter, vm::psv::ptr pValue) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=0x%x)", threadId, counter, pValue); + + if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF) + { + throw __FUNCTION__; + } + + if (counter >= 6 && counter != SCE_PERF_ARM_PMON_CYCLE_COUNTER) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + if (counter < 6) + { + *pValue = context.counters[counter].value; + } + else + { + throw "scePerfArmPmonGetCounterValue(): cycle counter requested"; + } + + return SCE_OK; } -s32 scePerfArmPmonSoftwareIncrement(u32 mask) +s32 scePerfArmPmonSoftwareIncrement(ARMv7Context& context, u32 mask) { - throw __FUNCTION__; + scePerf.Warning("scePerfArmPmonSoftwareIncrement(mask=0x%x)", mask); + + if (mask > SCE_PERF_ARM_PMON_COUNTER_MASK_ALL) + { + RETURN_ERROR(SCE_PERF_ERROR_INVALID_ARGUMENT); + } + + for (u32 i = 0; i < 6; i++, mask >>= 1) + { + if (mask & 1) + { + context.counters[i].value++; + } + } + + return SCE_OK; } u64 scePerfGetTimebaseValue() { - throw __FUNCTION__; + scePerf.Warning("scePerfGetTimebaseValue()"); + + return get_system_time(); } u32 scePerfGetTimebaseFrequency() { - throw __FUNCTION__; + scePerf.Warning("scePerfGetTimebaseFrequency()"); + + return 1; } s32 _sceRazorCpuInit(vm::psv::ptr pBufferBase, u32 bufferSize, u32 numPerfCounters, vm::psv::ptr> psceRazorVars) diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index c622308f3d..bf36001a51 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -93,6 +93,37 @@ namespace loader case MACHINE_MIPS: break; case MACHINE_ARM: { + struct psv_libc_param_t + { + u32 size; // 0x0000001c + u32 unk1; // 0x00000000 + + vm::psv::ptr sceLibcHeapSize; + vm::psv::ptr sceLibcHeapSizeDefault; + vm::psv::ptr sceLibcHeapExtendedAlloc; + vm::psv::ptr sceLibcHeapDelayedAlloc; + + u32 unk2; + }; + + struct psv_process_param_t + { + u32 size; // 0x00000030 + u32 unk1; // 'PSP2' + u32 unk2; // 0x00000005 + u32 unk3; + + vm::psv::ptr sceUserMainThreadName; + vm::psv::ptr sceUserMainThreadPriority; + vm::psv::ptr sceUserMainThreadStackSize; + vm::psv::ptr sceUserMainThreadAttribute; + vm::psv::ptr sceProcessName; + vm::psv::ptr sce_process_preload_disabled; + vm::psv::ptr sceUserMainThreadCpuAffinityMask; + + vm::psv::ptr __sce_libcparam; + }; + initialize_psv_modules(); auto armv7_thr_stop_data = vm::psv::ptr::make(Memory.PSV.RAM.AllocAlign(3 * 4)); @@ -104,10 +135,11 @@ namespace loader u32 fnid_addr = 0; u32 code_start = 0; u32 code_end = 0; - u32 vnid_addr = 0; std::unordered_map vnid_list; + auto proc_param = vm::psv::ptr::make(0); + for (auto& shdr : m_shdrs) { // get secton name @@ -130,24 +162,40 @@ namespace loader code_start = shdr.data_le.sh_addr; code_end = shdr.data_le.sh_size + code_start; } - else if (!strcmp(name.c_str(), ".sceModuleInfo.rodata")) + else if (!strcmp(name.c_str(), ".sceExport.rodata")) { - LOG_NOTICE(LOADER, ".sceModuleInfo.rodata analysis..."); + LOG_NOTICE(LOADER, ".sceExport.rodata analysis..."); - auto code = vm::psv::ptr::make(shdr.data_le.sh_addr); + auto enid = vm::psv::ptr::make(shdr.data_le.sh_addr); + auto edata = vm::psv::ptr::make(enid.addr() + shdr.data_le.sh_size / 2); - // very rough way to find the entry point - while (code[0] != 0xffffffffu) + for (u32 j = 0; j < shdr.data_le.sh_size / 8; j++) { - entry = code[0] + 0x81000000; - code++; - - if (code.addr() >= shdr.data_le.sh_addr + shdr.data_le.sh_size) + switch (const u32 nid = enid[j]) { - LOG_ERROR(LOADER, "Unable to find entry point in .sceModuleInfo.rodata"); - entry = 0; + case 0x935cd196: // set entry point + { + entry = edata[j]; break; } + + case 0x6c2224ba: // __sce_moduleinfo + { + // currently nothing, but it should theoretically be the root of analysis instead of section name comparison + break; + } + + case 0x70fba1e7: // __sce_process_param + { + proc_param.set(edata[j]); + break; + } + + default: + { + LOG_ERROR(LOADER, "Unknown export 0x%08x (addr=0x%08x)", nid, edata[j]); + } + } } } else if (!strcmp(name.c_str(), ".sceFNID.rodata")) @@ -320,10 +368,44 @@ namespace loader } } + LOG_NOTICE(LOADER, "__sce_process_param(addr=0x%x) analysis...", proc_param); + + if (proc_param->size != 0x30 || proc_param->unk1 != *(u32*)"PSP2" || proc_param->unk2 != 5) + { + LOG_ERROR(LOADER, "__sce_process_param: unexpected data found (size=0x%x, 0x%x, 0x%x, 0x%x)", proc_param->size, proc_param->unk1, proc_param->unk2, proc_param->unk3); + } + + LOG_NOTICE(LOADER, "*** &sceUserMainThreadName = 0x%x", proc_param->sceUserMainThreadName); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadPriority = 0x%x", proc_param->sceUserMainThreadPriority); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadStackSize = 0x%x", proc_param->sceUserMainThreadStackSize); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadAttribute = 0x%x", proc_param->sceUserMainThreadAttribute); + LOG_NOTICE(LOADER, "*** &sceProcessName = 0x%x", proc_param->sceProcessName); + LOG_NOTICE(LOADER, "*** &sce_process_preload_disabled = 0x%x", proc_param->sce_process_preload_disabled); + LOG_NOTICE(LOADER, "*** &sceUserMainThreadCpuAffinityMask = 0x%x", proc_param->sceUserMainThreadCpuAffinityMask); + + auto libc_param = proc_param->__sce_libcparam; + + LOG_NOTICE(LOADER, "__sce_libcparam(addr=0x%x) analysis...", libc_param); + + if (libc_param->size != 0x1c || libc_param->unk1) + { + LOG_ERROR(LOADER, "__sce_libcparam: unexpected data found (size=0x%x, 0x%x, 0x%x)", libc_param->size, libc_param->unk1, libc_param->unk2); + } + + LOG_NOTICE(LOADER, "*** &sceLibcHeapSize = 0x%x", libc_param->sceLibcHeapSize); + LOG_NOTICE(LOADER, "*** &sceLibcHeapSizeDefault = 0x%x", libc_param->sceLibcHeapSizeDefault); + LOG_NOTICE(LOADER, "*** &sceLibcHeapExtendedAlloc = 0x%x", libc_param->sceLibcHeapExtendedAlloc); + LOG_NOTICE(LOADER, "*** &sceLibcHeapDelayedAlloc = 0x%x", libc_param->sceLibcHeapDelayedAlloc); + armv7_init_tls(); armv7_decoder_initialize(code_start, code_end); - armv7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath(), "-emu" }).run(); + const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread"; + const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0; + const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0; + + /* TODO: Thumb/ARM encoding selection */ + armv7_thread(entry & ~1, thread_name, stack_size, priority).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; From 23c7028b2acf2bc18e657d6613e7ebfd42b6a6eb Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 2 Feb 2015 12:14:49 +0300 Subject: [PATCH 5/5] ARMv7: ARM encoding introduced; bugfixes --- Utilities/GNU.h | 6 + Utilities/Log.h | 2 +- Utilities/StrFmt.cpp | 3 +- Utilities/StrFmt.h | 11 +- rpcs3/Emu/ARMv7/ARMv7Context.h | 2 +- rpcs3/Emu/ARMv7/ARMv7Decoder.cpp | 132 ++++++++++++++------ rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 31 ++--- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 8 +- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 4 +- rpcs3/Emu/ARMv7/Modules/sceRtc.cpp | 4 +- rpcs3/Emu/Memory/vm.cpp | 7 +- rpcs3/Emu/SysCalls/LogBase.h | 14 +-- rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 12 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 13 +- rpcs3/Loader/ELF32.cpp | 17 ++- 16 files changed, 161 insertions(+), 109 deletions(-) diff --git a/Utilities/GNU.h b/Utilities/GNU.h index b1988b4dfa..a8db7f8703 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -14,6 +14,12 @@ #define __noinline __attribute__((noinline)) #endif +#ifdef _WIN32 +#define __safebuffers __declspec(safebuffers) +#else +#define __safebuffers +#endif + template void strcpy_trunc(char(&dst)[size], const std::string& src) { diff --git a/Utilities/Log.h b/Utilities/Log.h index d1710f05cf..5ff8504ce7 100644 --- a/Utilities/Log.h +++ b/Utilities/Log.h @@ -132,5 +132,5 @@ void log_message(Log::LogType type, Log::LogSeverity sev, std::string text); template __noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args) { - log_message(type, sev, fmt::detail::format(fmt, strlen(fmt), fmt::do_unveil(args)...)); + log_message(type, sev, fmt::detail::format(fmt, fmt::do_unveil(args)...)); } diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index 0b8410e2f4..2de4fc889f 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -144,8 +144,9 @@ size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len) return 1; } -std::string fmt::detail::format(const char* fmt, size_t len) +std::string fmt::detail::format(const char* fmt) { + const size_t len = strlen(fmt); const size_t fmt_start = get_fmt_start(fmt, len); if (fmt_start != len) { diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index 3bc464fcb8..f7474efa25 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -429,16 +429,17 @@ namespace fmt } }; - std::string format(const char* fmt, size_t len); // terminator + std::string format(const char* fmt); // terminator template - std::string format(const char* fmt, size_t len, const T& arg, Args... args) + std::string format(const char* fmt, const T& arg, Args... args) { + const size_t len = strlen(fmt); const size_t fmt_start = get_fmt_start(fmt, len); const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start); const size_t fmt_end = fmt_start + fmt_len; - return std::string(fmt, fmt_start) + get_fmt::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, len - fmt_end, args...); + return std::string(fmt, fmt_start) + get_fmt::text(fmt + fmt_start, fmt_len, arg) + format(fmt + fmt_end, args...); } }; @@ -551,9 +552,9 @@ namespace fmt Other features are not supported. */ template - __forceinline std::string format(const char* fmt, Args... args) + __forceinline __safebuffers std::string format(const char* fmt, Args... args) { - return detail::format(fmt, strlen(fmt), do_unveil(args)...); + return detail::format(fmt, do_unveil(args)...); } //convert a wxString to a std::string encoded in utf8 diff --git a/rpcs3/Emu/ARMv7/ARMv7Context.h b/rpcs3/Emu/ARMv7/ARMv7Context.h index fa9e04c64d..5ca662939f 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Context.h +++ b/rpcs3/Emu/ARMv7/ARMv7Context.h @@ -137,7 +137,7 @@ struct ARMv7Context } else { - write_pc(value & ~1); + write_pc(value); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp index ce2dbb6914..2c0c976697 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.cpp @@ -1159,9 +1159,44 @@ struct ARMv7_op4t_table_t } } } + + const ARMv7_opcode_t* HACK() + { + for (auto& opcode : table) + { + if (opcode->func == ARMv7_instrs::HACK) + { + return opcode; + } + } + + throw "HACK instruction not found"; + } } g_op4t; +struct ARMv7_op4arm_table_t +{ + std::vector table; + + ARMv7_op4arm_table_t() + { + for (auto& opcode : ARMv7_opcode_table) + { + if (opcode.type >= A1) + { + if (opcode.code & ~opcode.mask) + { + LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code); + } + + table.push_back(&opcode); + } + } + } + +} g_op4arm; + std::unordered_map g_opct; void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) @@ -1231,16 +1266,21 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1; const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1); - // possibly a call to imported function: - if (target >= end_addr && ((target - end_addr) % 16) == 0 && vm::psv::read16(target) == 0xf870) - { - const u32 instr = vm::psv::read32(target); + const u32 instr = vm::psv::read32(target); - // check if not "unimplemented" - if (instr >> 16) + // possibly a call to imported function: + if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090) + { + // check if implemented + if (const u32 func = (instr & 0xfff00) >> 4 | (instr & 0xf)) { - // replace BLX with "hack" instruction directly, it can help to see where it was called from - vm::psv::write32(addr, instr); + // replace BLX with "HACK" instruction directly (in Thumb form), it can help to see where it was called from + vm::psv::write32(addr, 0xf870 | func << 16); + g_opct[0xf8700000 | func] = g_op4t.HACK(); + } + else + { + // leave as is if unimplemented } } else @@ -1257,50 +1297,60 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) addr += found->length; } - while (vm::psv::read16(addr) == 0xf870) - { - g_opct[0xf8700000 | vm::psv::read16(addr + 2)] = g_op4t.table[0]; - addr += 16; - } - LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); } u32 ARMv7Decoder::DecodeMemory(const u32 address) { - if (address & 0x1) - { - throw "ARMv7Decoder::DecodeMemory() failed (something is wrong with instruction set)"; - } - ARMv7Code code = {}; - code.code0 = vm::psv::read16(address); - if (auto opcode = g_op2t.data[code.code0]) + if (m_ctx.ISET == Thumb) { - (*opcode->func)(m_ctx, code, opcode->type); - return 2; + code.code0 = vm::psv::read16(address); + + if (auto opcode = g_op2t.data[code.code0]) + { + (*opcode->func)(m_ctx, code, opcode->type); + return 2; + } + + code.code1 = code.code0; + code.code0 = vm::psv::read16(address + 2); + + auto op = g_opct.find(code.data); + if (op != g_opct.end()) + { + (*op->second->func)(m_ctx, code, op->second->type); + return 4; + } + + //for (auto opcode : g_op4t.table) + //{ + // if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) + // { + // (*opcode->func)(m_ctx, code, opcode->type); + // return 4; + // } + //} } - - code.code1 = code.code0; - code.code0 = vm::psv::read16(address + 2); - - auto op = g_opct.find(code.data); - if (op != g_opct.end()) + else if (m_ctx.ISET == ARM) { - (*op->second->func)(m_ctx, code, op->second->type); - return 4; + code.data = vm::psv::read32(address); + + for (auto opcode : g_op4arm.table) + { + if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) + { + (*opcode->func)(m_ctx, code, opcode->type); + return 4; + } + } } - - //for (auto opcode : g_op4t.table) - //{ - // if ((code.data & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(code.data))) - // { - // (*opcode->func)(m_ctx, code, opcode->type); - // return 4; - // } - //} - + else + { + throw "ARMv7Decoder::DecodeMemory() failed (invalid instruction set set)"; + } + ARMv7_instrs::UNK(m_ctx, code); return 4; diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index c204351616..d7b1c9adf8 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -280,7 +280,14 @@ namespace ARMv7_instrs void ARMv7_instrs::UNK(ARMv7Context& context, const ARMv7Code code) { - throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + if (context.ISET == Thumb) + { + throw fmt::format("Unknown/illegal opcode: 0x%04x 0x%04x", code.code1, code.code0); + } + else + { + throw fmt::format("Unknown/illegal opcode: 0x%08x", code.data); + } } void ARMv7_instrs::HACK(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) @@ -976,16 +983,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_ if (ConditionPassed(context, cond)) { context.LR = newLR; - if (target & 1) - { - context.ISET = Thumb; - context.thread.SetBranch(target & ~1); - } - else - { - context.ISET = ARM; - context.thread.SetBranch(target); - } + context.write_pc(target); } } @@ -1014,16 +1012,7 @@ void ARMv7_instrs::BX(ARMv7Context& context, const ARMv7Code code, const ARMv7_e if (ConditionPassed(context, cond)) { - if (target & 1) - { - context.ISET = Thumb; - context.thread.SetBranch(target & ~1); - } - else - { - context.ISET = ARM; - context.thread.SetBranch(target); - } + context.write_pc(target); } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 6e1cec6fa8..9fe72a3d49 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -12,7 +12,8 @@ void ARMv7Context::write_pc(u32 value) { - thread.SetBranch(value); + ISET = value & 1 ? Thumb : ARM; + thread.SetBranch(value & ~1); } u32 ARMv7Context::read_pc() @@ -109,10 +110,11 @@ ARMv7Thread::~ARMv7Thread() void ARMv7Thread::InitRegs() { - memset(context.GPR, 0, sizeof(context.GPR[0]) * 15); + memset(context.GPR, 0, sizeof(context.GPR)); context.APSR.APSR = 0; context.IPSR.IPSR = 0; - //context.ISET = Thumb; + context.ISET = PC & 1 ? Thumb : ARM; // select instruction set + context.thread.SetPc(PC & ~1); // and fix PC context.ITSTATE.IT = 0; context.SP = m_stack_addr + m_stack_size; context.TLS = armv7_get_tls(GetId()); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index dbbce2e151..d7bd58c79a 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -48,12 +48,12 @@ s32 sceKernelCreateThread( ARMv7Thread& new_thread = static_cast(Emu.GetCPU().AddThread(CPU_THREAD_ARMv7)); const auto id = new_thread.GetId(); - new_thread.SetEntry(entry.addr() ^ 1); + new_thread.SetEntry(entry.addr()); new_thread.SetPrio(initPriority); new_thread.SetStackSize(stackSize); new_thread.SetName(pName.get_ptr()); - sceLibKernel.Error("*** New ARMv7 Thread [%s] (entry=0x%x)^1: id -> 0x%x", pName.get_ptr(), entry, id); + sceLibKernel.Warning("*** New ARMv7 Thread [%s] (entry=0x%x): id -> 0x%x", pName.get_ptr(), entry, id); new_thread.Run(); return id; diff --git a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp index 96d44a3686..9b81d86072 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceRtc.cpp @@ -59,7 +59,7 @@ s32 sceRtcCheckValid(vm::psv::ptr pTime) throw __FUNCTION__; } -s32 sceRtcSetTime_t(vm::psv::ptr pTime, time_t iTime) +s32 sceRtcSetTime_t(vm::psv::ptr pTime, u32 iTime) { throw __FUNCTION__; } @@ -69,7 +69,7 @@ s32 sceRtcSetTime64_t(vm::psv::ptr pTime, u64 ullTime) throw __FUNCTION__; } -s32 sceRtcGetTime_t(vm::psv::ptr pTime, vm::psv::ptr piTime) +s32 sceRtcGetTime_t(vm::psv::ptr pTime, vm::psv::ptr piTime) { throw __FUNCTION__; } diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 69e42e62cb..04d3a0f90a 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -69,7 +69,7 @@ namespace vm void error(const u64 addr, const char* func) { - throw fmt::format("%s(): invalid address 0x%llx", func, addr); + throw fmt::format("%s(): failed to cast 0x%llx (too big value)", func, addr); } namespace ps3 @@ -249,7 +249,10 @@ namespace vm case CPU_THREAD_ARMv7: { - assert(!"stack_pop(): ARMv7 not supported"); + ARMv7Context& context = static_cast(CPU).context; + + assert(context.SP == addr); + context.SP = old_pos; return; } diff --git a/rpcs3/Emu/SysCalls/LogBase.h b/rpcs3/Emu/SysCalls/LogBase.h index 7f496d6c6e..82e569e808 100644 --- a/rpcs3/Emu/SysCalls/LogBase.h +++ b/rpcs3/Emu/SysCalls/LogBase.h @@ -17,9 +17,9 @@ class LogBase void LogOutput(LogType type, const std::string& text) const; template - __noinline void LogPrepare(LogType type, const char* fmt, size_t len, Targs... args) const + __noinline void LogPrepare(LogType type, const char* fmt, Targs... args) const { - LogOutput(type, fmt::detail::format(fmt, len, args...)); + LogOutput(type, fmt::detail::format(fmt, args...)); } public: @@ -38,7 +38,7 @@ public: template __forceinline void Notice(const char* fmt, Targs... args) const { - LogPrepare(LogNotice, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogNotice, fmt, fmt::do_unveil(args)...); } template @@ -53,25 +53,25 @@ public: template __forceinline void Success(const char* fmt, Targs... args) const { - LogPrepare(LogSuccess, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogSuccess, fmt, fmt::do_unveil(args)...); } template __forceinline void Warning(const char* fmt, Targs... args) const { - LogPrepare(LogWarning, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogWarning, fmt, fmt::do_unveil(args)...); } template __forceinline void Error(const char* fmt, Targs... args) const { - LogPrepare(LogError, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogError, fmt, fmt::do_unveil(args)...); } template __forceinline void Todo(const char* fmt, Targs... args) const { - LogPrepare(LogTodo, fmt, strlen(fmt), fmt::do_unveil(args)...); + LogPrepare(LogTodo, fmt, fmt::do_unveil(args)...); } }; diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index 18724020af..79ad2d72bc 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -372,7 +372,7 @@ s32 cellSaveDataListSave2( for (u32 i=0; iresult < 0) { @@ -629,7 +629,7 @@ s32 cellSaveDataFixedLoad2( for (u32 i = 0; iresult < 0) { @@ -826,7 +826,7 @@ s32 cellSaveDataListAutoSave( //for (u32 i = 0; i queue, vm::ptr buffer, u32 siz queue->m_depth = depth; queue->m_buffer = buffer; queue->m_direction = direction; - *queue->m_hs1 = {}; - *queue->m_hs2 = {}; + memset(queue->m_hs1, 0, sizeof(queue->m_hs1)); + memset(queue->m_hs2, 0, sizeof(queue->m_hs2)); queue->m_eaSignal = eaSignal; if (direction == CELL_SYNC_QUEUE_ANY2ANY) diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 99555c70cf..f38865db09 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -217,6 +217,7 @@ int cellVideoOutGetConfiguration(u32 videoOut, vm::ptrresolutionId = Emu.GetGSManager().GetInfo().mode.resolutionId; config->format = Emu.GetGSManager().GetInfo().mode.format; config->aspect = Emu.GetGSManager().GetInfo().mode.aspect; - *config->reserved = {}; config->pitch = Emu.GetGSManager().GetInfo().mode.pitch; return CELL_VIDEO_OUT_SUCCEEDED; case CELL_VIDEO_OUT_SECONDARY: - *config = {}; // ??? return CELL_VIDEO_OUT_SUCCEEDED; } @@ -478,22 +477,25 @@ int cellAudioOutGetState(u32 audioOut, u32 deviceIndex, vm::ptrWarning("cellAudioOutGetState(audioOut=0x%x, deviceIndex=0x%x, state_addr=0x%x)", audioOut, deviceIndex, state.addr()); + *state = {}; + switch(audioOut) { case CELL_AUDIO_OUT_PRIMARY: state->state = Emu.GetAudioManager().GetState(); state->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; - *state->reserved = {}; state->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; state->soundMode.type = Emu.GetAudioManager().GetInfo().mode.type; state->soundMode.channel = Emu.GetAudioManager().GetInfo().mode.channel; state->soundMode.fs = Emu.GetAudioManager().GetInfo().mode.fs; state->soundMode.reserved = 0; state->soundMode.layout = Emu.GetAudioManager().GetInfo().mode.layout; + return CELL_AUDIO_OUT_SUCCEEDED; case CELL_AUDIO_OUT_SECONDARY: - *state = { CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED }; + state->state = CELL_AUDIO_OUT_OUTPUT_STATE_DISABLED; + return CELL_AUDIO_OUT_SUCCEEDED; } @@ -534,19 +536,18 @@ int cellAudioOutGetConfiguration(u32 audioOut, vm::ptrWarning("cellAudioOutGetConfiguration(audioOut=%d, config_addr=0x%x, option_addr=0x%x)", audioOut, config.addr(), option.addr()); if (option) *option = {}; + *config = {}; switch(audioOut) { case CELL_AUDIO_OUT_PRIMARY: config->channel = Emu.GetAudioManager().GetInfo().mode.channel; config->encoder = Emu.GetAudioManager().GetInfo().mode.encoder; - *config->reserved = {}; config->downMixer = Emu.GetAudioManager().GetInfo().mode.downMixer; return CELL_AUDIO_OUT_SUCCEEDED; case CELL_AUDIO_OUT_SECONDARY: - *config = {}; return CELL_AUDIO_OUT_SUCCEEDED; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index bf36001a51..89112c8692 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -104,6 +104,10 @@ namespace loader vm::psv::ptr sceLibcHeapDelayedAlloc; u32 unk2; + u32 unk3; + + vm::psv::ptr __sce_libcmallocreplace; + vm::psv::ptr __sce_libcnewreplace; }; struct psv_process_param_t @@ -233,18 +237,14 @@ namespace loader LOG_NOTICE(LOADER, "Imported function %s (nid=0x%08x, addr=0x%x)", func->name, nid, addr); } - // writing Thumb code (temporarily, because it should be ARM) - vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) - vm::psv::write16(addr + 2, (u16)get_psv_func_index(func)); // function index - vm::psv::write16(addr + 4, 0x4770); // BX LR - vm::psv::write16(addr + 6, 0); // null + const u32 code = get_psv_func_index(func); + vm::psv::write32(addr + 0, 0xe0700090 | (code & 0xfff0) << 4 | (code & 0xf)); // HACK instruction (ARM) } else { LOG_ERROR(LOADER, "Unknown function 0x%08x (addr=0x%x)", nid, addr); - vm::psv::write16(addr + 0, 0xf870); // HACK instruction (Thumb) - vm::psv::write16(addr + 2, 0); // index 0 (unimplemented stub) + vm::psv::write32(addr + 0, 0xe0700090); // HACK instruction (ARM), unimplemented stub (code 0) vm::psv::write32(addr + 4, nid); // nid } @@ -404,8 +404,7 @@ namespace loader const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0; const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0; - /* TODO: Thumb/ARM encoding selection */ - armv7_thread(entry & ~1, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run(); + armv7_thread(entry, thread_name, stack_size, priority).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;