diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 5678d5f9d9..99203e1864 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -2463,25 +2463,27 @@ void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) { } void Compiler::LWARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; + + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); - auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false); + //auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); - resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); - resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); - SetGpr(rd, resv_val_i64); + //resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32); + //resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty()); + //SetGpr(rd, resv_val_i64); } void Compiler::LDX(u32 rd, u32 ra, u32 rb) { @@ -2739,23 +2741,25 @@ void Compiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) { } void Compiler::LDARX(u32 rd, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8); - resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); - SetGpr(rd, resv_val_i64); + //auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8); + + //resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64); + //SetGpr(rd, resv_val_i64); } void Compiler::DCBF(u32 ra, u32 rb) { @@ -2919,45 +2923,47 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) { } void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i32 = GetGpr(rs, 32); - rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); - auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i32 = GetGpr(rs, 32); + //rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo()); + //auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STWX(u32 rs, u32 ra, u32 rb) { @@ -3060,45 +3066,47 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) { } void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) { - auto addr_i64 = GetGpr(rb); - if (ra) { - auto ra_i64 = GetGpr(ra); - addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); - } + throw __FUNCTION__; - auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); - auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); - auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); + //auto addr_i64 = GetGpr(rb); + //if (ra) { + // auto ra_i64 = GetGpr(ra); + // addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); + //} - auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); - auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); - auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); - m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); + //auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR)); + //auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8); + //auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64); - m_ir_builder->SetInsertPoint(then_bb); - auto rs_i64 = GetGpr(rs, 64); - rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); - resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); - auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); - auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); - auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); + //auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then"); + //auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else"); + //auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge"); + //m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb); - auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); - auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); - auto cr_i32 = GetCr(); - cr_i32 = SetBit(cr_i32, 2, success_i1); - SetCr(cr_i32); - m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); - m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(then_bb); + //auto rs_i64 = GetGpr(rs, 64); + //rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64); + //resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr(0))); + //auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE)); + //auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo()); + //auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8); - m_ir_builder->SetInsertPoint(else_bb); - cr_i32 = GetCr(); - cr_i32 = ClrBit(cr_i32, 2); - SetCr(cr_i32); - m_ir_builder->CreateBr(merge_bb); - m_ir_builder->SetInsertPoint(merge_bb); + //auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic); + //auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1}); + //auto cr_i32 = GetCr(); + //cr_i32 = SetBit(cr_i32, 2, success_i1); + //SetCr(cr_i32); + //m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8); + //m_ir_builder->CreateBr(merge_bb); + + //m_ir_builder->SetInsertPoint(else_bb); + //cr_i32 = GetCr(); + //cr_i32 = ClrBit(cr_i32, 2); + //SetCr(cr_i32); + //m_ir_builder->CreateBr(merge_bb); + //m_ir_builder->SetInsertPoint(merge_bb); } void Compiler::STBX(u32 rs, u32 ra, u32 rb) { diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp index f30a713c09..e1054ecc89 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerTests.cpp @@ -59,10 +59,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp /// Time base register u64 TB; - /// Reservations - u64 R_ADDR; - u64 R_VALUE; - /// Memory block u32 address; u64 mem_block[64]; @@ -86,9 +82,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp CTR = ppu.CTR; TB = ppu.TB; - R_ADDR = ppu.R_ADDR; - R_VALUE = ppu.R_VALUE; - address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { mem_block[i] = vm::read64(address + (i * 8)); @@ -114,9 +107,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp ppu.CTR = CTR; ppu.TB = TB; - ppu.R_ADDR = R_ADDR; - ppu.R_VALUE = R_VALUE; - for (int i = 0; i < (sizeof(mem_block) / 8); i++) { vm::write64(address + (i * 8), mem_block[i]); } @@ -151,8 +141,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp LR = rng(); CTR = rng(); TB = rng(); - R_ADDR = rng(); - R_VALUE = rng(); address = addr; for (int i = 0; i < (sizeof(mem_block) / 8); i++) { @@ -187,7 +175,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp // fmt::by_value(FPSCR.VXZDZ), fmt::by_value(FPSCR.VXIDI), fmt::by_value(FPSCR.VXISI), fmt::by_value(FPSCR.VXSNAN), // fmt::by_value(FPSCR.XX), fmt::by_value(FPSCR.ZX), fmt::by_value(FPSCR.UX), fmt::by_value(FPSCR.OX), fmt::by_value(FPSCR.VX), fmt::by_value(FPSCR.FEX), fmt::by_value(FPSCR.FX)); //ret += fmt::Format("VSCR = 0x%08x [NJ=%d | SAT=%d]\n", VSCR.VSCR, fmt::by_value(VSCR.NJ), fmt::by_value(VSCR.SAT)); // TODO: Uncomment after implementing VSCR.SAT - ret += fmt::Format("R_ADDR = 0x%016llx R_VALUE = 0x%016llx\n", R_ADDR, R_VALUE); for (int i = 0; i < (sizeof(mem_block) / 8); i += 2) { ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]); @@ -724,8 +711,6 @@ void Compiler::RunAllTests() { input.GPR[14] = 10; input.GPR[21] = 15; input.GPR[23] = 0x10000; - input.R_ADDR = 0x10000; - input.R_VALUE = 0x1122334455667788; input.mem_block[0] = 0x8877665544332211; VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000); diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 71033cbd9d..2bd0e0f629 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -435,10 +435,20 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs) if (op == MFC_GETLLAR_CMD) // get reservation { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]() { + //std::shared_ptr t = Emu.GetCPU().GetThread(tid); + + //if (t && (t->GetType() == CPU_THREAD_SPU || t->GetType() == CPU_THREAD_RAW_SPU)) + //{ + // SPUThread& spu = static_cast(*t); + + // spu.m_events |= SPU_EVENT_LR; // TODO: atomic op + // spu.Notify(); + //} + m_events |= SPU_EVENT_LR; // TODO: atomic op Notify(); }); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index b892bff2b8..ecd4961d82 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -232,21 +232,13 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) : MemInfo(_addr, PAGE_4K(_size)) { void* real_addr = vm::get_ptr(vm::cast(_addr)); -#ifdef _WIN32 void* priv_addr = vm::get_priv_ptr(vm::cast(_addr)); - void* priv_mem = VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE); - mem = priv_mem == priv_addr ? VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE) : priv_mem; + +#ifdef _WIN32 + if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE)) #else - if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE)) - { - mem = nullptr; - } - else - { - mem = real_addr; - } + if (!::mprotect(real_addr, size, PROT_READ | PROT_WRITE) || !::mprotect(priv_addr, size, PROT_READ | PROT_WRITE)) #endif - if (mem != real_addr) { LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size); Emu.Pause(); @@ -254,7 +246,9 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size) else { Memory.RegisterPages(_addr, PAGE_4K(_size)); - memset(mem, 0, size); + + mem = real_addr; + memset(mem, 0, size); // ??? } } @@ -269,7 +263,7 @@ void MemBlockInfo::Free() if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old)) //if (!VirtualFree(mem, size, MEM_DECOMMIT)) #else - if (::mprotect(mem, size, PROT_NONE)) + if (::mprotect(mem, size, PROT_NONE) || !::mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE)) #endif { LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size); diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index a32d176b2e..55564a371f 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -23,6 +23,8 @@ namespace vm { #ifdef _WIN32 HANDLE g_memory_handle; +#else + int g_memory_handle; #endif void* g_priv_addr; @@ -36,9 +38,17 @@ namespace vm g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access return base_addr; + //return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS); #else - return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + g_memory_handle = shm_open("/rpcs3_vm", O_RDWR, 0); + + void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE, g_memory_handle, 0); + + return base_addr; + + //return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); #endif } @@ -50,32 +60,112 @@ namespace vm CloseHandle(g_memory_handle); #else munmap(g_base_addr, 0x100000000); + munmap(g_priv_addr, 0x100000000); + + shm_unlink("/rpcs3_vm"); #endif } void* const g_base_addr = (atexit(finalize), initialize()); - void* g_reservation_owner = nullptr; - u32 g_reservation_addr = 0; + class reservation_mutex_t + { + std::atomic m_owner; + std::condition_variable m_cv; + std::atomic test; + std::mutex m_cv_mutex; + + public: + reservation_mutex_t() + : m_owner(nullptr) + , test(0) + { + } + + bool do_notify; + + __noinline void lock() + { + NamedThreadBase* owner = GetCurrentNamedThread(); + NamedThreadBase* old = nullptr; + + while (!m_owner.compare_exchange_strong(old, owner)) + { + std::unique_lock cv_lock(m_cv_mutex); + + m_cv.wait_for(cv_lock, std::chrono::milliseconds(1)); + + if (old == owner) + { + throw __FUNCTION__; + } + + old = nullptr; + } + + do_notify = true; + + test++; + assert(test == 1); + } + + __noinline void unlock() + { + assert(test == 1); + test--; + + NamedThreadBase* owner = GetCurrentNamedThread(); + + if (!m_owner.compare_exchange_strong(owner, nullptr)) + { + throw __FUNCTION__; + } + + if (do_notify) + { + m_cv.notify_one(); + } + } + + }; std::function g_reservation_cb = nullptr; + NamedThreadBase* g_reservation_owner = nullptr; - // break the reservation, return true if it was successfully broken - bool reservation_break(u32 addr) + u32 g_reservation_addr = 0; + + reservation_mutex_t g_reservation_mutex; + + void _reservation_set(u32 addr) { - LV2_LOCK(0); + //const auto stamp0 = get_time(); +#ifdef _WIN32 + DWORD old; + if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) +#else + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ)) +#endif + { + throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr); + } + + //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); + } + + bool _reservation_break(u32 addr) + { if (g_reservation_addr >> 12 == addr >> 12) { - const auto stamp0 = get_time(); + //const auto stamp0 = get_time(); #ifdef _WIN32 if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE)) #else - + if (!::mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE)) #endif { - throw fmt::format("vm::reservation_break() failed (addr=0x%x)", addr); + throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr); } //LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f); @@ -95,8 +185,14 @@ namespace vm return false; } - // read memory and reserve it for further atomic update, return true if the previous reservation was broken - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback) + bool reservation_break(u32 addr) + { + std::lock_guard lock(g_reservation_mutex); + + return _reservation_break(addr); + } + + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback) { const auto stamp0 = get_time(); @@ -106,28 +202,21 @@ namespace vm assert((addr + size & ~0xfff) == (addr & ~0xfff)); { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); + + // silent unlocking to prevent priority boost for threads going to break reservation + g_reservation_mutex.do_notify = false; // break previous reservation if (g_reservation_addr) { - broken = reservation_break(g_reservation_addr); + broken = _reservation_break(g_reservation_addr); } // change memory protection to read-only -#ifdef _WIN32 - DWORD old; - if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old)) -#else + _reservation_set(addr); -#endif - { - throw fmt::format("vm::reservation_acquire() failed (addr=0x%x, size=%d)", addr, size); - } - - //LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f); - - // set the new reservation + // set additional information g_reservation_addr = addr; g_reservation_owner = GetCurrentNamedThread(); g_reservation_cb = callback; @@ -139,13 +228,12 @@ namespace vm return broken; } - // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size) { assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); assert((addr + size & ~0xfff) == (addr & ~0xfff)); - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread()) { @@ -157,39 +245,69 @@ namespace vm memcpy(vm::get_priv_ptr(addr), data, size); // free the reservation and restore memory protection - reservation_break(addr); + _reservation_break(addr); // atomic update succeeded return true; } - // for internal use bool reservation_query(u32 addr) { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); - if (!Memory.IsGoodAddr(addr)) { - return false; + LV2_LOCK(0); + + if (!Memory.IsGoodAddr(addr)) + { + return false; + } } // break the reservation - reservation_break(addr); + _reservation_break(addr); return true; } - // for internal use void reservation_free() { - LV2_LOCK(0); + std::lock_guard lock(g_reservation_mutex); if (g_reservation_owner == GetCurrentNamedThread()) { - reservation_break(g_reservation_addr); + _reservation_break(g_reservation_addr); } } + void reservation_op(u32 addr, u32 size, std::function proc) + { + assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128); + assert((addr + size & ~0xfff) == (addr & ~0xfff)); + + std::lock_guard lock(g_reservation_mutex); + + // break previous reservation + if (g_reservation_addr) + { + _reservation_break(g_reservation_addr); + } + + // change memory protection to read-only + _reservation_set(addr); + + // set additional information + g_reservation_addr = addr; + g_reservation_owner = GetCurrentNamedThread(); + g_reservation_cb = nullptr; + + // do the operation + proc(); + + // remove the reservation + _reservation_break(addr); + } + bool check_addr(u32 addr) { // Checking address before using it is unsafe. diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index 32bcf17859..559ccb15e6 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -28,11 +28,16 @@ namespace vm extern void* g_priv_addr; extern void* const g_base_addr; + // break the reservation, return true if it was successfully broken bool reservation_break(u32 addr); - bool reservation_acquire(void* data, u32 addr, u32 size, std::function callback = nullptr); + // read memory and reserve it for further atomic update, return true if the previous reservation was broken + bool reservation_acquire(void* data, u32 addr, u32 size, const std::function& callback = nullptr); + // attempt to atomically update reserved memory bool reservation_update(u32 addr, const void* data, u32 size); bool reservation_query(u32 addr); void reservation_free(); + // perform complete operation + void reservation_op(u32 addr, u32 size, std::function proc); bool map(u32 addr, u32 size, u32 flags); bool unmap(u32 addr, u32 size = 0, u32 flags = 0); diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 0c588cd7ee..68d940ea6b 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -213,6 +213,11 @@ namespace vm { return vm::get_ptr(vm::cast(m_addr)); } + + T* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } static const _ptr_base make(const AT& addr) { @@ -243,6 +248,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator void*() const { return get_ptr(); @@ -301,6 +311,11 @@ namespace vm return vm::get_ptr(vm::cast(m_addr)); } + const void* get_priv_ptr() const + { + return vm::get_priv_ptr(vm::cast(m_addr)); + } + explicit operator const void*() const { return get_ptr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp index 69445ccb17..28828c9d38 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysmodule.cpp @@ -136,7 +136,7 @@ const char *getModuleName(int id) { } } - return 0; + return "UNKNOWN MODULE"; } int cellSysmoduleInitialize() @@ -159,11 +159,12 @@ int cellSysmoduleSetMemcontainer(u32 ct_id) int cellSysmoduleLoadModule(u16 id) { + cellSysmodule->Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, getModuleName(id)); + if (id == 0xf054) { cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI"); } - cellSysmodule->Warning("cellSysmoduleLoadModule(%s)", getModuleName(id)); if (Module* m = Emu.GetModuleManager().GetModuleById(id)) { @@ -180,7 +181,8 @@ int cellSysmoduleLoadModule(u16 id) int cellSysmoduleUnloadModule(u16 id) { - cellSysmodule->Warning("cellSysmoduleUnloadModule(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) @@ -199,7 +201,8 @@ int cellSysmoduleUnloadModule(u16 id) int cellSysmoduleIsLoaded(u16 id) { - cellSysmodule->Warning("cellSysmoduleIsLoaded(%s)", getModuleName(id)); + cellSysmodule->Warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, getModuleName(id)); + Module* m = Emu.GetModuleManager().GetModuleById(id); if(!m) diff --git a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp index 38ea4fc729..ca72b045ac 100644 --- a/rpcs3/Emu/SysCalls/lv2/cellFs.cpp +++ b/rpcs3/Emu/SysCalls/lv2/cellFs.cpp @@ -395,7 +395,7 @@ s32 cellFsFsync(u32 fd) s32 cellFsRmdir(vm::ptr path) { - sys_fs->Warning("cellFsRmdir(path=0x%x)", path.get_ptr()); + sys_fs->Warning("cellFsRmdir(path=0x%x)", path); std::string _path = path.get_ptr();