diff --git a/Utilities/GNU.h b/Utilities/GNU.h index c0286b0491..89cb3a1cfa 100644 --- a/Utilities/GNU.h +++ b/Utilities/GNU.h @@ -6,6 +6,12 @@ #define thread_local __thread #endif +#ifdef _WIN32 +#define noinline __declspec(noinline) +#else +#define noinline __attribute__((noinline)) +#endif + template void strcpy_trunc(char (&dst)[size], const std::string& src) { diff --git a/asmjit b/asmjit index a66efd5460..3363e4138b 160000 --- a/asmjit +++ b/asmjit @@ -1 +1 @@ -Subproject commit a66efd54609aab7dd98e34c069937f34aa7c8f95 +Subproject commit 3363e4138b003be36dfb63cf8c63cf360f04276f diff --git a/asmjitsrc/asmjit.vcxproj b/asmjitsrc/asmjit.vcxproj index 04f30a8e35..92a1201431 100644 --- a/asmjitsrc/asmjit.vcxproj +++ b/asmjitsrc/asmjit.vcxproj @@ -23,31 +23,55 @@ + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + {AC40FF01-426E-4838-A317-66354CEFAE88} diff --git a/asmjitsrc/asmjit.vcxproj.filters b/asmjitsrc/asmjit.vcxproj.filters index b82be7b1a7..705a68121c 100644 --- a/asmjitsrc/asmjit.vcxproj.filters +++ b/asmjitsrc/asmjit.vcxproj.filters @@ -1,34 +1,58 @@  - - - - - - + + + - + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rpcs3/Emu/ARMv7/ARMv7Decoder.h b/rpcs3/Emu/ARMv7/ARMv7Decoder.h index b19bf94cd3..2d63602941 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Decoder.h +++ b/rpcs3/Emu/ARMv7/ARMv7Decoder.h @@ -21,8 +21,8 @@ public: virtual u8 DecodeMemory(const u64 address) { using namespace ARMv7_opcodes; - const u16 code0 = Memory.Read16(address); - const u16 code1 = Memory.Read16(address + 2); + const u16 code0 = Memory.PSV.Read16(address); + const u16 code1 = Memory.PSV.Read16(address + 2); switch(code0 >> 12) //15 - 12 { diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index 71aecf535d..477f09b18f 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -275,7 +275,7 @@ protected: if(regs_list & mask) { CPU.SP -= 4; - Memory.Write32(CPU.SP, CPU.read_gpr(i)); + Memory.PSV.Write32(CPU.SP, CPU.read_gpr(i)); } } } @@ -286,7 +286,7 @@ protected: { if(regs_list & mask) { - CPU.write_gpr(i, Memory.Read32(CPU.SP)); + CPU.write_gpr(i, Memory.PSV.Read32(CPU.SP)); CPU.SP += 4; } } diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 406721651a..577fcf9c5f 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -285,7 +285,7 @@ void CPUThread::ExecOnce() void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp) { const u64 addr = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr(); - if (addr < 0x100000000 && u == EXCEPTION_ACCESS_VIOLATION) + if (u == EXCEPTION_ACCESS_VIOLATION && addr < 0x100000000) { // TODO: allow recovering from a page fault //GetCurrentPPUThread().Stop(); @@ -317,6 +317,8 @@ void CPUThread::Task() } } + std::vector trace; + #ifdef _WIN32 _set_se_translator(_se_translator); #else @@ -339,6 +341,7 @@ void CPUThread::Task() } Step(); + //if (PC - 0x13ED4 < 0x288) trace.push_back(PC); NextPc(m_dec->DecodeMemory(PC + m_offset)); if (status == CPUThread_Step) @@ -357,6 +360,8 @@ void CPUThread::Task() } } + for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%llx", v); + if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str()); } diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 7e4501feec..7b019ac5ca 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -148,7 +148,7 @@ public: if (#a1[0] == 'r') XmmInvalidate(a1); \ if (#a2[0] == 'r') XmmInvalidate(a2); \ if (#a3[0] == 'r') XmmInvalidate(a3); \ - X86X64CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ + X86CallNode* call##a0 = c.call(imm_ptr(reinterpret_cast(&opwr_##a0::opcode)), kFuncConvHost, FuncBuilder4()); \ call##a0->setArg(0, imm_u(a0)); \ call##a0->setArg(1, imm_u(a1)); \ call##a0->setArg(2, imm_u(a2)); \ @@ -163,24 +163,24 @@ private: SPURecompilerCore& rec; public: - Compiler* compiler; + X86Compiler* compiler; bool do_finalize; // input: - GpVar* cpu_var; - GpVar* ls_var; - GpVar* imm_var; - GpVar* g_imm_var; + X86GpVar* cpu_var; + X86GpVar* ls_var; + X86GpVar* imm_var; + X86GpVar* g_imm_var; // output: - GpVar* pos_var; + X86GpVar* pos_var; // temporary: - GpVar* addr; - GpVar* qw0; - GpVar* qw1; - GpVar* qw2; + X86GpVar* addr; + X86GpVar* qw0; + X86GpVar* qw1; + X86GpVar* qw2; struct XmmLink { - XmmVar* data; + X86XmmVar* data; s8 reg; bool taken; mutable bool got; @@ -443,7 +443,7 @@ private: } }; c.mov(cpu_qword(PC), (u32)CPU.PC); - X86X64CallNode* call = c.call(imm_ptr(reinterpret_cast(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); + X86CallNode* call = c.call(imm_ptr(reinterpret_cast(&STOP_wrapper::STOP)), kFuncConvHost, FuncBuilder1()); call->setArg(0, imm_u(code)); c.mov(*pos_var, (CPU.PC >> 2) + 1); do_finalize = true; @@ -1114,7 +1114,7 @@ private: /*XmmInvalidate(rt); - GpVar v(c, kVarTypeUInt32); + X86GpVar v(c, kVarTypeUInt32); c.mov(v, cpu_dword(GPR[rt]._u32[3])); switch (ra) { diff --git a/rpcs3/Emu/Cell/SPURecompilerCore.cpp b/rpcs3/Emu/Cell/SPURecompilerCore.cpp index d38911b110..52563b2e0d 100644 --- a/rpcs3/Emu/Cell/SPURecompilerCore.cpp +++ b/rpcs3/Emu/Cell/SPURecompilerCore.cpp @@ -13,12 +13,19 @@ static const g_imm_table_struct g_imm_table; SPURecompilerCore::SPURecompilerCore(SPUThread& cpu) -: m_enc(new SPURecompiler(cpu, *this)) -, inter(new SPUInterpreter(cpu)) -, CPU(cpu) -, first(true) + : m_enc(new SPURecompiler(cpu, *this)) + , inter(new SPUInterpreter(cpu)) + , CPU(cpu) + , first(true) { memset(entry, 0, sizeof(entry)); + X86CpuInfo inf; + X86CpuUtil::detect(&inf); + if (!inf.hasFeature(kX86CpuFeatureSse41)) + { + LOG_ERROR(SPU, "SPU Recompiler requires SSE4.1 instruction set support"); + Emu.Pause(); + } } SPURecompilerCore::~SPURecompilerCore() @@ -42,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos) StringLogger stringLogger; stringLogger.setOption(kLoggerOptionBinaryForm, true); - Compiler compiler(&runtime); + X86Compiler compiler(&runtime); m_enc->compiler = &compiler; compiler.setLogger(&stringLogger); @@ -51,40 +58,40 @@ void SPURecompilerCore::Compile(u16 pos) u32 excess = 0; entry[start].count = 0; - GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu"); + X86GpVar cpu_var(compiler, kVarTypeIntPtr, "cpu"); compiler.setArg(0, cpu_var); compiler.alloc(cpu_var); m_enc->cpu_var = &cpu_var; - GpVar ls_var(compiler, kVarTypeIntPtr, "ls"); + X86GpVar ls_var(compiler, kVarTypeIntPtr, "ls"); compiler.setArg(1, ls_var); compiler.alloc(ls_var); m_enc->ls_var = &ls_var; - GpVar imm_var(compiler, kVarTypeIntPtr, "imm"); + X86GpVar imm_var(compiler, kVarTypeIntPtr, "imm"); compiler.setArg(2, imm_var); compiler.alloc(imm_var); m_enc->imm_var = &imm_var; - GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm"); + X86GpVar g_imm_var(compiler, kVarTypeIntPtr, "g_imm"); compiler.setArg(3, g_imm_var); compiler.alloc(g_imm_var); m_enc->g_imm_var = &g_imm_var; - GpVar pos_var(compiler, kVarTypeUInt32, "pos"); + X86GpVar pos_var(compiler, kVarTypeUInt32, "pos"); m_enc->pos_var = &pos_var; - GpVar addr_var(compiler, kVarTypeUInt32, "addr"); + X86GpVar addr_var(compiler, kVarTypeUInt32, "addr"); m_enc->addr = &addr_var; - GpVar qw0_var(compiler, kVarTypeUInt64, "qw0"); + X86GpVar qw0_var(compiler, kVarTypeUInt64, "qw0"); m_enc->qw0 = &qw0_var; - GpVar qw1_var(compiler, kVarTypeUInt64, "qw1"); + X86GpVar qw1_var(compiler, kVarTypeUInt64, "qw1"); m_enc->qw1 = &qw1_var; - GpVar qw2_var(compiler, kVarTypeUInt64, "qw2"); + X86GpVar qw2_var(compiler, kVarTypeUInt64, "qw2"); m_enc->qw2 = &qw2_var; for (u32 i = 0; i < 16; i++) { - m_enc->xmm_var[i].data = new XmmVar(compiler, kVarTypeXmm, fmt::Format("reg_%d", i).c_str()); + m_enc->xmm_var[i].data = new X86XmmVar(compiler, kX86VarTypeXmm, fmt::Format("reg_%d", i).c_str()); } compiler.xor_(pos_var, pos_var); diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index a5f848ce65..a56751bbe8 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -362,7 +362,7 @@ public: void Init() { - m_index = 0; + m_indval = 0; } __forceinline bool Pop(u32& res) diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 00afc33ede..c69afb5a9a 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -364,193 +364,7 @@ bool MemoryBlockLE::Write128(const u64 addr, const u128 value) return true; } -//MemoryBase -void MemoryBase::Write8(u64 addr, const u8 data) -{ - if ((u32)addr == addr) - { - *(u8*)((u64)GetBaseAddr() + addr) = data; - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - } -} - -void MemoryBase::Write16(u64 addr, const u16 data) -{ - if ((u32)addr == addr) - { - *(u16*)((u64)GetBaseAddr() + addr) = re16(data); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - } -} - -void MemoryBase::Write32(u64 addr, const u32 data) -{ - if ((u32)addr == addr) - { - if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]) - { - *(u32*)((u64)GetBaseAddr() + addr) = re32(data); - } - else - { - RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data); - } - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - } -} - -void MemoryBase::Write64(u64 addr, const u64 data) -{ - if ((u32)addr == addr) - { - *(u64*)((u64)GetBaseAddr() + addr) = re64(data); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - } -} - -void MemoryBase::Write128(u64 addr, const u128 data) -{ - if ((u32)addr == addr) - { - *(u128*)((u64)GetBaseAddr() + addr) = re128(data); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - } -} - -bool MemoryBase::Write8NN(u64 addr, const u8 data) -{ - if(!IsGoodAddr(addr)) return false; - Write8(addr, data); - return true; -} - -bool MemoryBase::Write16NN(u64 addr, const u16 data) -{ - if(!IsGoodAddr(addr, 2)) return false; - Write16(addr, data); - return true; -} - -bool MemoryBase::Write32NN(u64 addr, const u32 data) -{ - if(!IsGoodAddr(addr, 4)) return false; - Write32(addr, data); - return true; -} - -bool MemoryBase::Write64NN(u64 addr, const u64 data) -{ - if(!IsGoodAddr(addr, 8)) return false; - Write64(addr, data); - return true; -} - -bool MemoryBase::Write128NN(u64 addr, const u128 data) -{ - if(!IsGoodAddr(addr, 16)) return false; - Write128(addr, data); - return true; -} - -u8 MemoryBase::Read8(u64 addr) -{ - if ((u32)addr == addr) - { - return *(u8*)((u64)GetBaseAddr() + addr); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - return 0; - } -} - -u16 MemoryBase::Read16(u64 addr) -{ - if ((u32)addr == addr) - { - return re16(*(u16*)((u64)GetBaseAddr() + addr)); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - return 0; - } -} - -u32 MemoryBase::Read32(u64 addr) -{ - if ((u32)addr == addr) - { - if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]) - { - return re32(*(u32*)((u64)GetBaseAddr() + addr)); - } - else - { - u32 res; - RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res); - return res; - } - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - return 0; - } -} - -u64 MemoryBase::Read64(u64 addr) -{ - if ((u32)addr == addr) - { - return re64(*(u64*)((u64)GetBaseAddr() + addr)); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - return 0; - } -} - -u128 MemoryBase::Read128(u64 addr) -{ - if ((u32)addr == addr) - { - return re128(*(u128*)((u64)GetBaseAddr() + addr)); - } - else - { - LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", __FUNCTION__, addr); - Emu.Pause(); - return u128::From128(0, 0); - } -} - +// MemoryBase template<> __forceinline u64 MemoryBase::ReverseData<1>(u64 val) { return val; } template<> __forceinline u64 MemoryBase::ReverseData<2>(u64 val) { return Reverse16(val); } template<> __forceinline u64 MemoryBase::ReverseData<4>(u64 val) { return Reverse32(val); } diff --git a/rpcs3/Emu/Memory/Memory.h b/rpcs3/Emu/Memory/Memory.h index effa1b88f7..6430e27d80 100644 --- a/rpcs3/Emu/Memory/Memory.h +++ b/rpcs3/Emu/Memory/Memory.h @@ -52,20 +52,43 @@ public: MemoryBlock* RawSPUMem[(0x100000000 - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]; VirtualMemoryBlock RSXIOMem; - struct + struct Wrapper32LE + { + private: + void* m_base_addr; + + public: + Wrapper32LE() : m_base_addr(nullptr) {} + + void Write8(const u32 addr, const u8 data) { *(u8*)((u8*)m_base_addr + addr) = data; } + void Write16(const u32 addr, const u16 data) { *(u16*)((u8*)m_base_addr + addr) = data; } + void Write32(const u32 addr, const u32 data) { *(u32*)((u8*)m_base_addr + addr) = data; } + void Write64(const u32 addr, const u64 data) { *(u64*)((u8*)m_base_addr + addr) = data; } + void Write128(const u32 addr, const u128 data) { *(u128*)((u8*)m_base_addr + addr) = data; } + + u8 Read8(const u32 addr) { return *(u8*)((u8*)m_base_addr + addr); } + u16 Read16(const u32 addr) { return *(u16*)((u8*)m_base_addr + addr); } + u32 Read32(const u32 addr) { return *(u32*)((u8*)m_base_addr + addr); } + u64 Read64(const u32 addr) { return *(u64*)((u8*)m_base_addr + addr); } + u128 Read128(const u32 addr) { return *(u128*)((u8*)m_base_addr + addr); } + + void Init(void* real_addr) { m_base_addr = real_addr; } + }; + + struct : Wrapper32LE { DynamicMemoryBlockLE RAM; DynamicMemoryBlockLE Userspace; - } PSVMemory; + } PSV; - struct + struct : Wrapper32LE { DynamicMemoryBlockLE Scratchpad; DynamicMemoryBlockLE VRAM; DynamicMemoryBlockLE RAM; DynamicMemoryBlockLE Kernel; DynamicMemoryBlockLE Userspace; - } PSPMemory; + } PSP; bool m_inited; @@ -84,17 +107,26 @@ public: return m_base_addr; } + noinline void InvalidAddress(const char* func, const u64 addr) + { + LOG_ERROR(MEMORY, "%s(): invalid address (0x%llx)", func, addr); + } + void RegisterPages(u64 addr, u32 size) { std::lock_guard lock(m_mutex); //LOG_NOTICE(MEMORY, "RegisterPages(addr=0x%llx, size=0x%x)", addr, size); - for (u32 i = addr / 4096; i < (addr + size) / 4096; i++) + for (u64 i = addr / 4096; i < (addr + size) / 4096; i++) { - if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break; + if (i >= sizeof(m_pages) / sizeof(m_pages[0])) + { + InvalidAddress(__FUNCTION__, i * 4096); + break; + } if (m_pages[i]) { - LOG_ERROR(MEMORY, "Page already registered (page=0x%x)", i * 4096); + LOG_ERROR(MEMORY, "Page already registered (addr=0x%llx)", i * 4096); } m_pages[i] = 1; // TODO: define page parameters } @@ -105,12 +137,16 @@ public: std::lock_guard lock(m_mutex); //LOG_NOTICE(MEMORY, "UnregisterPages(addr=0x%llx, size=0x%x)", addr, size); - for (u32 i = addr / 4096; i < (addr + size) / 4096; i++) + for (u64 i = addr / 4096; i < (addr + size) / 4096; i++) { - if (i >= sizeof(m_pages) / sizeof(m_pages[0])) break; + if (i >= sizeof(m_pages) / sizeof(m_pages[0])) + { + InvalidAddress(__FUNCTION__, i * 4096); + break; + } if (!m_pages[i]) { - LOG_ERROR(MEMORY, "Page not registered (page=0x%x)", i * 4096); + LOG_ERROR(MEMORY, "Page not registered (addr=0x%llx)", i * 4096); } m_pages[i] = 0; // TODO: define page parameters } @@ -146,17 +182,25 @@ public: return (T)ReverseData(val); }; - u8* GetMemFromAddr(const u64 addr) + template u8* GetMemFromAddr(const T addr) { - return (u8*)GetBaseAddr() + addr; + if ((u32)addr == addr) + { + return (u8*)GetBaseAddr() + addr; + } + else + { + InvalidAddress(__FUNCTION__, addr); + return (u8*)GetBaseAddr(); + } } - void* VirtualToRealAddr(const u64 vaddr) + template void* VirtualToRealAddr(const T vaddr) { - return GetMemFromAddr(vaddr); + return GetMemFromAddr(vaddr); } - u64 RealToVirtualAddr(const void* addr) + u32 RealToVirtualAddr(const void* addr) { const u64 res = (u64)addr - (u64)GetBaseAddr(); @@ -233,25 +277,27 @@ public: break; case Memory_PSV: - MemoryBlocks.push_back(PSVMemory.RAM.SetRange(0x81000000, 0x10000000)); - MemoryBlocks.push_back(UserMemory = PSVMemory.Userspace.SetRange(0x91000000, 0x10000000)); + MemoryBlocks.push_back(PSV.RAM.SetRange(0x81000000, 0x10000000)); + MemoryBlocks.push_back(UserMemory = PSV.Userspace.SetRange(0x91000000, 0x10000000)); + PSV.Init(GetBaseAddr()); break; case Memory_PSP: - MemoryBlocks.push_back(PSPMemory.Scratchpad.SetRange(0x00010000, 0x00004000)); - MemoryBlocks.push_back(PSPMemory.VRAM.SetRange(0x04000000, 0x00200000)); - MemoryBlocks.push_back(PSPMemory.RAM.SetRange(0x08000000, 0x02000000)); - MemoryBlocks.push_back(PSPMemory.Kernel.SetRange(0x88000000, 0x00800000)); - MemoryBlocks.push_back(UserMemory = PSPMemory.Userspace.SetRange(0x08800000, 0x01800000)); + MemoryBlocks.push_back(PSP.Scratchpad.SetRange(0x00010000, 0x00004000)); + MemoryBlocks.push_back(PSP.VRAM.SetRange(0x04000000, 0x00200000)); + MemoryBlocks.push_back(PSP.RAM.SetRange(0x08000000, 0x02000000)); + MemoryBlocks.push_back(PSP.Kernel.SetRange(0x88000000, 0x00800000)); + MemoryBlocks.push_back(UserMemory = PSP.Userspace.SetRange(0x08800000, 0x01800000)); + PSP.Init(GetBaseAddr()); break; } LOG_NOTICE(MEMORY, "Memory initialized."); } - bool IsGoodAddr(const u64 addr) + template bool IsGoodAddr(const T addr) { - if (addr >= 0x100000000 || !m_pages[addr / 4096]) // TODO: define page parameters + if ((u32)addr != addr || !m_pages[addr / 4096]) // TODO: define page parameters { return false; } @@ -261,9 +307,9 @@ public: } } - bool IsGoodAddr(const u64 addr, const u32 size) + template bool IsGoodAddr(const T addr, const u32 size) { - if (addr + size > 0x100000000) + if ((u32)addr != addr || (u64)addr + (u64)size > 0x100000000ull) { return false; } @@ -308,23 +354,152 @@ public: #endif } - void Write8(const u64 addr, const u8 data); - void Write16(const u64 addr, const u16 data); - void Write32(const u64 addr, const u32 data); - void Write64(const u64 addr, const u64 data); - void Write128(const u64 addr, const u128 data); + //MemoryBase + template void Write8(T addr, const u8 data) + { + if ((u32)addr == addr) + { + *(u8*)((u8*)GetBaseAddr() + addr) = data; + } + else + { + InvalidAddress(__FUNCTION__, addr); + *(u8*)GetBaseAddr() = data; + } + } - bool Write8NN(const u64 addr, const u8 data); - bool Write16NN(const u64 addr, const u16 data); - bool Write32NN(const u64 addr, const u32 data); - bool Write64NN(const u64 addr, const u64 data); - bool Write128NN(const u64 addr, const u128 data); + template void Write16(T addr, const u16 data) + { + if ((u32)addr == addr) + { + *(u16*)((u8*)GetBaseAddr() + addr) = re16(data); + } + else + { + InvalidAddress(__FUNCTION__, addr); + *(u16*)GetBaseAddr() = data; + } + } - u8 Read8(const u64 addr); - u16 Read16(const u64 addr); - u32 Read32(const u64 addr); - u64 Read64(const u64 addr); - u128 Read128(const u64 addr); + template void Write32(T addr, const u32 data) + { + if ((u32)addr == addr) + { + if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]) + { + *(u32*)((u8*)GetBaseAddr() + addr) = re32(data); + } + else + { + RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Write32(addr, data); + } + } + else + { + InvalidAddress(__FUNCTION__, addr); + *(u32*)GetBaseAddr() = data; + } + } + + template void Write64(T addr, const u64 data) + { + if ((u32)addr == addr) + { + *(u64*)((u8*)GetBaseAddr() + addr) = re64(data); + } + else + { + InvalidAddress(__FUNCTION__, addr); + *(u64*)GetBaseAddr() = data; + } + } + + template void Write128(T addr, const u128 data) + { + if ((u32)addr == addr) + { + *(u128*)((u8*)GetBaseAddr() + addr) = re128(data); + } + else + { + InvalidAddress(__FUNCTION__, addr); + *(u128*)GetBaseAddr() = data; + } + } + + template u8 Read8(T addr) + { + if ((u32)addr == addr) + { + return *(u8*)((u8*)GetBaseAddr() + addr); + } + else + { + InvalidAddress(__FUNCTION__, addr); + return *(u8*)GetBaseAddr(); + } + } + + template u16 Read16(T addr) + { + if ((u32)addr == addr) + { + return re16(*(u16*)((u8*)GetBaseAddr() + addr)); + } + else + { + InvalidAddress(__FUNCTION__, addr); + return *(u16*)GetBaseAddr(); + } + } + + template u32 Read32(T addr) + { + if ((u32)addr == addr) + { + if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET || !RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]) + { + return re32(*(u32*)((u8*)GetBaseAddr() + addr)); + } + else + { + u32 res; + RawSPUMem[(addr - RAW_SPU_BASE_ADDR) / RAW_SPU_OFFSET]->Read32(addr, &res); + return res; + } + } + else + { + InvalidAddress(__FUNCTION__, addr); + return *(u32*)GetBaseAddr(); + } + } + + template u64 Read64(T addr) + { + if ((u32)addr == addr) + { + return re64(*(u64*)((u8*)GetBaseAddr() + addr)); + } + else + { + InvalidAddress(__FUNCTION__, addr); + return *(u64*)GetBaseAddr(); + } + } + + template u128 Read128(T addr) + { + if ((u32)addr == addr) + { + return re128(*(u128*)((u8*)GetBaseAddr() + addr)); + } + else + { + InvalidAddress(__FUNCTION__, addr); + return *(u128*)GetBaseAddr(); + } + } bool CopyToReal(void* real, u64 from, u32 count) { @@ -469,13 +644,13 @@ public: return false; } - u8* operator + (const u64 vaddr) + template u8* operator + (const T vaddr) { - u8* ret = GetMemFromAddr(vaddr); + u8* ret = GetMemFromAddr(vaddr); return ret; } - u8& operator[] (const u64 vaddr) + template u8& operator[] (const T vaddr) { return *(*this + vaddr); } diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 378830875f..69fa0e8033 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -4,6 +4,7 @@ #include "Emu/System.h" #include "Callback.h" +#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPCThread.h" Callback::Callback(u32 slot, u64 addr) @@ -13,6 +14,7 @@ Callback::Callback(u32 slot, u64 addr) , a2(0) , a3(0) , a4(0) + , a5(0) , m_has_data(false) , m_name("Callback") { @@ -43,12 +45,13 @@ bool Callback::HasData() const return m_has_data; } -void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4) +void Callback::Handle(u64 _a1, u64 _a2, u64 _a3, u64 _a4, u64 _a5) { a1 = _a1; a2 = _a2; a3 = _a3; a4 = _a4; + a5 = _a5; m_has_data = true; } @@ -97,6 +100,7 @@ again: thr.SetArg(2, a3); thr.SetArg(3, a4); thr.Run(); + ((PPUThread&)thr).GPR[7] = a5; thr.Exec(); diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index ce9023b1b0..faf3b79e99 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -15,6 +15,7 @@ public: u64 a2; u64 a3; u64 a4; + u64 a5; u32 GetSlot() const; u64 GetAddr() const; @@ -23,7 +24,7 @@ public: bool HasData() const; Callback(u32 slot = 0, u64 addr = 0); - void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0); + void Handle(u64 a1 = 0, u64 a2 = 0, u64 a3 = 0, u64 a4 = 0, u64 a5 = 0); u64 Branch(bool wait); void SetName(const std::string& name); diff --git a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp index ea34d10566..d918962343 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellL10n.cpp @@ -44,7 +44,7 @@ int UTF16stoUTF8s(mem16_ptr_t utf16, mem64_t utf16_len, mem8_ptr_t utf8, mem64_t if (!utf16.IsGood() || !utf16_len.IsGood() || !utf8_len.IsGood()) return SRCIllegal; - std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16); + std::u16string wstr =(char16_t*)Memory.VirtualToRealAddr(utf16.GetAddr()); wstr.resize(utf16_len.GetValue()); // TODO: Is this really the role of utf16_len in this function? #ifdef _MSC_VER std::wstring_convert,char16_t> convert; diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index 0685b0e90c..147e37c812 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -361,7 +361,7 @@ int cellSurMixerCreate(const mem_ptr_t config) break; } - if (mixcount > (port.tag + 14)) // preemptive buffer filling (probably hack) + if (mixcount > (port.tag + 0)) // adding positive value (1-15): preemptive buffer filling (hack) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); continue; @@ -531,7 +531,8 @@ int cellSurMixerStart() int cellSurMixerSetParameter(u32 param, float value) { - libmixer->Error("cellSurMixerSetParameter(param=0x%x, value=%f)", param, value); + declCPU(); + libmixer->Error("cellSurMixerSetParameter(param=0x%x, value=%f, FPR[1]=%f, FPR[2]=%f)", param, value, (float&)CPU.FPR[1], (float&)CPU.FPR[2]); return CELL_OK; } @@ -559,8 +560,7 @@ int cellSurMixerSurBusAddData(u32 busNo, u32 offset, u32 addr, u32 samples) } else { - libmixer->Error("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d)", busNo, offset, addr, samples); - Emu.Pause(); + libmixer->Error("cellSurMixerSurBusAddData(busNo=%d, offset=0x%x, addr=0x%x, samples=%d): unknown parameters", busNo, offset, addr, samples); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index f42444ee12..ad51e004a0 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -205,20 +205,19 @@ s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 s return CELL_OK; } -void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry) +void sys_ppu_thread_once(mem_ptr_t>> once_ctrl, u32 entry) { - sysPrxForUser->Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl_addr, entry); + sysPrxForUser->Warning("sys_ppu_thread_once(once_ctrl_addr=0x%x, entry=0x%x)", once_ctrl.GetAddr(), entry); - if(Memory.IsGoodAddr(once_ctrl_addr, 4) && Memory.Read32(once_ctrl_addr) == SYS_PPU_THREAD_ONCE_INIT) + be_t old = SYS_PPU_THREAD_ONCE_INIT; + if (once_ctrl->compare_exchange_weak(old, SYS_PPU_THREAD_DONE_INIT)) { - Memory.Write32(once_ctrl_addr, SYS_PPU_THREAD_DONE_INIT); - CPUThread& new_thread = Emu.GetCPU().AddThread(CPU_THREAD_PPU); new_thread.SetEntry(entry); new_thread.Run(); new_thread.Exec(); - //GetCurrentPPUThread().Wait(new_thread); + while (new_thread.IsAlive()) SM_Sleep(); } } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h index 5256a9a5dc..ef99ca6012 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.h @@ -24,5 +24,5 @@ s32 sys_ppu_thread_get_stack_information(u32 info_addr); s32 sys_ppu_thread_stop(u64 thread_id); s32 sys_ppu_thread_restart(u64 thread_id); s32 sys_ppu_thread_create(mem64_t thread_id, u32 entry, u64 arg, s32 prio, u32 stacksize, u64 flags, u32 threadname_addr); -void sys_ppu_thread_once(u32 once_ctrl_addr, u32 entry); +void sys_ppu_thread_once(mem_ptr_t>> once_ctrl, u32 entry); s32 sys_ppu_thread_get_id(const u32 id_addr); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp index b7dae66aec..4a88fb9c48 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.cpp @@ -597,7 +597,7 @@ s32 sys_spu_thread_connect_event(u32 id, u32 eq_id, u32 et, u8 spup) return CELL_EINVAL; } - // TODO: check if can receive this events + // TODO: check if can receive these events SPUThread& spu = *(SPUThread*)thr; @@ -706,51 +706,82 @@ s32 sys_spu_thread_unbind_queue(u32 id, u32 spuq_num) return CELL_OK; } -s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr) +s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, mem8_t spup) { - sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(id=%d, eq=%d, req=0x%llx, spup_addr=0x%x)", - id, eq, req, spup_addr); + sc_spu.Warning("sys_spu_thread_group_connect_event_all_threads(id=%d, eq_id=%d, req=0x%llx, spup_addr=0x%x)", + id, eq_id, req, spup.GetAddr()); - EventQueue* equeue; - if(!sys_event.CheckId(eq, equeue)) + if (!spup.IsGood()) + { + return CELL_EFAULT; + } + + EventQueue* eq; + if (!Emu.GetIdManager().GetIDData(eq_id, eq)) { return CELL_ESRCH; } - if(!req) + if (!req) { return CELL_EINVAL; } SpuGroupInfo* group; - if(!Emu.GetIdManager().GetIDData(id, group)) + if (!Emu.GetIdManager().GetIDData(id, group)) { return CELL_ESRCH; } - - /* - for(u32 i=0; ilist.size(); ++i) + + std::vector threads; + for (auto& v : group->list) { - CPUThread* t; - if(t = Emu.GetCPU().GetThread(group->list[i])) + if (!v) continue; + CPUThread* thr = Emu.GetCPU().GetThread(v); + if (thr->GetType() != CPU_THREAD_SPU) { - bool finded_port = false; - for(int j=0; jpos; ++j) + sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (wrong thread type)"); + return CELL_ESTAT; + } + threads.push_back((SPUThread*)thr); + } + + if (threads.size() != group->m_count) + { + sc_spu.Error("sys_spu_thread_group_connect_event_all_threads(): CELL_ESTAT (%d from %d)", (u32)threads.size(), group->m_count); + return CELL_ESTAT; + } + + for (u32 i = 0; i < 64; i++) // port number + { + bool found = true; + if (req & (1ull << i)) + { + for (auto& t : threads) t->SPUPs[i].m_mutex.lock(); + + for (auto& t : threads) if (t->SPUPs[i].eq) found = false; + + if (found) { - if(!equeue->ports[j]->thread) + for (auto& t : threads) { - finded_port = true; - equeue->ports[j]->thread = t; + eq->ports.add(&(t->SPUPs[i])); + t->SPUPs[i].eq = eq; } + spup = (u8)i; } - if(!finded_port) - { - return CELL_EISCONN; - } + for (auto& t : threads) t->SPUPs[i].m_mutex.unlock(); } - }*/ - return CELL_OK; + else + { + found = false; + } + + if (found) return CELL_OK; + } + + return CELL_EISCONN; } s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup) diff --git a/rpcs3/Emu/SysCalls/lv2/sys_spu.h b/rpcs3/Emu/SysCalls/lv2/sys_spu.h index 72821054b3..3750f151a4 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_spu.h +++ b/rpcs3/Emu/SysCalls/lv2/sys_spu.h @@ -64,6 +64,7 @@ struct SpuGroupInfo int m_prio; int m_type; int m_ct; + u32 m_count; SpuGroupInfo(const std::string& name, u32 num, int prio, int type, u32 ct) : m_name(name) @@ -71,13 +72,10 @@ struct SpuGroupInfo , m_type(type) , m_ct(ct) , lock(0) + , m_count(num) { - num = 256; - list.resize(num); - for (u32 i = 0; i < num; i++) - { - list[i] = 0; - } + list.resize(256); + for (auto& v : list) v = 0; } }; @@ -95,7 +93,7 @@ s32 sys_spu_thread_create(mem32_t thread_id, mem32_t entry, u64 arg, int prio, u s32 sys_spu_thread_group_join(u32 id, mem32_t cause, mem32_t status); s32 sys_spu_thread_group_connect_event(u32 id, u32 eq, u32 et); s32 sys_spu_thread_group_disconnect_event(u32 id, u32 et); -s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq, u64 req, u32 spup_addr); +s32 sys_spu_thread_group_connect_event_all_threads(u32 id, u32 eq_id, u64 req, mem8_t spup); s32 sys_spu_thread_group_disconnect_event_all_threads(u32 id, u8 spup); s32 sys_spu_thread_write_ls(u32 id, u32 address, u64 value, u32 type); s32 sys_spu_thread_read_ls(u32 id, u32 address, mem64_t value, u32 type); diff --git a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp index 7ff925b368..3aa176e46a 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_timer.cpp @@ -103,8 +103,16 @@ s32 sys_timer_disconnect_event_queue(u32 timer_id) s32 sys_timer_sleep(u32 sleep_time) { - sys_timer.Warning("sys_timer_sleep(sleep_time=%d)", sleep_time); - std::this_thread::sleep_for(std::chrono::seconds(sleep_time)); + sys_timer.Log("sys_timer_sleep(sleep_time=%d)", sleep_time); + for (u32 i = 0; i < sleep_time; i++) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + if (Emu.IsStopped()) + { + sys_timer.Warning("sys_timer_sleep(sleep_time=%d) aborted", sleep_time); + return CELL_OK; + } + } return CELL_OK; } @@ -112,6 +120,15 @@ s32 sys_timer_usleep(u64 sleep_time) { sys_timer.Log("sys_timer_usleep(sleep_time=%lld)", sleep_time); if (sleep_time > 0xFFFFFFFFFFFF) sleep_time = 0xFFFFFFFFFFFF; //2^48-1 - std::this_thread::sleep_for(std::chrono::microseconds(sleep_time)); + for (u32 i = 0; i < sleep_time / 1000000; i++) + { + std::this_thread::sleep_for(std::chrono::seconds(1)); + if (Emu.IsStopped()) + { + sys_timer.Warning("sys_timer_usleep(sleep_time=%lld) aborted", sleep_time); + return CELL_OK; + } + } + std::this_thread::sleep_for(std::chrono::microseconds(sleep_time % 1000000)); return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/lv2/sys_tty.cpp b/rpcs3/Emu/SysCalls/lv2/sys_tty.cpp index 630f00a959..073e1a0176 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_tty.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_tty.cpp @@ -9,7 +9,7 @@ s32 sys_tty_read(u32 ch, u64 buf_addr, u32 len, u64 preadlen_addr) { // We currently do not support reading from the Console LOG_WARNING(HLE, "sys_tty_read: ch: %d, buf addr: %llx, len: %d", ch, buf_addr, len); - Memory.Write32NN(preadlen_addr, len); + Memory.Write32(preadlen_addr, len); Emu.Pause(); return CELL_OK; diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 4e736e34e2..49d56f56ee 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -237,8 +237,8 @@ bool ELF32Loader::LoadPhdrData(u64 _offset) switch(machine) { case MACHINE_SPU: break; - case MACHINE_MIPS: Memory.PSPMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); break; - case MACHINE_ARM: Memory.PSVMemory.RAM.AllocFixed(phdr_arr[i].p_vaddr + offset, phdr_arr[i].p_memsz); 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;