diff --git a/Core/MIPS/x86/X64IRCompLoadStore.cpp b/Core/MIPS/x86/X64IRCompLoadStore.cpp index d80e5c40cb..1576c63706 100644 --- a/Core/MIPS/x86/X64IRCompLoadStore.cpp +++ b/Core/MIPS/x86/X64IRCompLoadStore.cpp @@ -82,14 +82,54 @@ void X64JitBackend::CompIR_FStore(IRInst inst) { void X64JitBackend::CompIR_Load(IRInst inst) { CONDITIONAL_DISABLE; + regs_.SpillLockGPR(inst.dest, inst.src1); + OpArg addrArg; + if (inst.src1 == MIPS_REG_ZERO) { +#ifdef MASKED_PSP_MEMORY + inst.constant &= Memory::MEMVIEW32_MASK; +#endif +#if PPSSPP_ARCH(AMD64) + addrArg = MDisp(MEMBASEREG, inst.constant & 0x7FFFFFFF); +#else + addrArg = M(Memory::base + inst.constant); +#endif + } else if (jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) { + X64Reg src1 = regs_.MapGPRAsPointer(inst.src1); + addrArg = MDisp(src1, inst.constant & 0x7FFFFFFF); + } else { + regs_.MapGPR(inst.src1); + addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, inst.constant & 0x7FFFFFFF); + } + // With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1. + regs_.MapGPR(inst.dest, MIPSMap::NOINIT); + + // TODO: Safe memory? Or enough to have crash handler + validate? + switch (inst.op) { case IROp::Load8: + MOVZX(32, 8, regs_.RX(inst.dest), addrArg); + break; + case IROp::Load8Ext: + MOVSX(32, 8, regs_.RX(inst.dest), addrArg); + break; + case IROp::Load16: + MOVZX(32, 16, regs_.RX(inst.dest), addrArg); + break; + case IROp::Load16Ext: + MOVSX(32, 16, regs_.RX(inst.dest), addrArg); + break; + case IROp::Load32: + MOV(32, regs_.R(inst.dest), addrArg); + break; + case IROp::Load32Linked: - CompIR_Generic(inst); + if (inst.dest != MIPS_REG_ZERO) + MOV(32, regs_.R(inst.dest), addrArg); + regs_.SetGPRImm(IRREG_LLBIT, 1); break; default: @@ -117,11 +157,56 @@ void X64JitBackend::CompIR_LoadShift(IRInst inst) { void X64JitBackend::CompIR_Store(IRInst inst) { CONDITIONAL_DISABLE; + regs_.SpillLockGPR(inst.src3, inst.src1); + OpArg addrArg; + if (inst.src1 == MIPS_REG_ZERO) { +#ifdef MASKED_PSP_MEMORY + inst.constant &= Memory::MEMVIEW32_MASK; +#endif +#if PPSSPP_ARCH(AMD64) + addrArg = MDisp(MEMBASEREG, inst.constant & 0x7FFFFFFF); +#else + addrArg = M(Memory::base + inst.constant); +#endif + } else if ((jo.cachePointers || regs_.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { + X64Reg src1 = regs_.MapGPRAsPointer(inst.src1); + addrArg = MDisp(src1, inst.constant & 0x7FFFFFFF); + } else { + regs_.MapGPR(inst.src1); + addrArg = MComplex(MEMBASEREG, regs_.RX(inst.src1), SCALE_1, inst.constant & 0x7FFFFFFF); + } + + OpArg valueArg; + X64Reg valueReg = regs_.TryMapTempImm(inst.src3); + if (valueReg != INVALID_REG) { + valueArg = R(valueReg); + } else if (regs_.IsGPRImm(inst.src3)) { + u32 imm = regs_.GetGPRImm(inst.src3); + switch (inst.op) { + case IROp::Store8: valueArg = Imm8((u8)imm); break; + case IROp::Store16: valueArg = Imm16((u16)imm); break; + case IROp::Store32: valueArg = Imm32(imm); break; + default: + INVALIDOP; + break; + } + } else { + valueArg = R(regs_.MapGPR(inst.src3)); + } + + // TODO: Safe memory? Or enough to have crash handler + validate? + switch (inst.op) { case IROp::Store8: + MOV(8, addrArg, valueArg); + break; + case IROp::Store16: + MOV(16, addrArg, valueArg); + break; + case IROp::Store32: - CompIR_Generic(inst); + MOV(32, addrArg, valueArg); break; default: diff --git a/Core/MIPS/x86/X64IRJit.h b/Core/MIPS/x86/X64IRJit.h index 4144ece248..afccf2bd5d 100644 --- a/Core/MIPS/x86/X64IRJit.h +++ b/Core/MIPS/x86/X64IRJit.h @@ -106,10 +106,6 @@ private: void CompIR_VecStore(IRInst inst) override; void CompIR_ValidateAddress(IRInst inst) override; - void SetScratch1ToSrc1Address(IRReg src1); - // Modifies SCRATCH regs. - int32_t AdjustForAddressOffset(Gen::X64Reg *reg, int32_t constant, int32_t range = 0); - JitOptions &jo; X64IRRegCache regs_; diff --git a/Core/MIPS/x86/X64IRRegCache.cpp b/Core/MIPS/x86/X64IRRegCache.cpp index d79e1de69e..dfd7d62294 100644 --- a/Core/MIPS/x86/X64IRRegCache.cpp +++ b/Core/MIPS/x86/X64IRRegCache.cpp @@ -126,7 +126,7 @@ X64Reg X64IRRegCache::TryMapTempImm(IRReg r) { _dbg_assert_(IsValidGPR(r)); // If already mapped, no need for a temporary. if (IsGPRMapped(r)) { - return R(r); + return RX(r); } if (mr[r].loc == MIPSLoc::IMM) { @@ -282,7 +282,15 @@ void X64IRRegCache::StoreRegValue(IRReg mreg, uint32_t imm) { emit_->MOV(32, MDisp(CTXREG, -128 + GetMipsRegOffset(mreg)), ::R(storeReg)); } -X64Reg X64IRRegCache::R(IRReg mipsReg) { +OpArg X64IRRegCache::R(IRReg mipsReg) { + return ::R(RX(mipsReg)); +} + +OpArg X64IRRegCache::F(IRReg mipsReg) { + return ::R(FX(mipsReg)); +} + +X64Reg X64IRRegCache::RX(IRReg mipsReg) { _dbg_assert_(IsValidGPR(mipsReg)); _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM); if (mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM) { @@ -293,7 +301,7 @@ X64Reg X64IRRegCache::R(IRReg mipsReg) { } } -X64Reg X64IRRegCache::RPtr(IRReg mipsReg) { +X64Reg X64IRRegCache::RXPtr(IRReg mipsReg) { _dbg_assert_(IsValidGPR(mipsReg)); _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM || mr[mipsReg].loc == MIPSLoc::REG_AS_PTR); if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) { @@ -313,7 +321,7 @@ X64Reg X64IRRegCache::RPtr(IRReg mipsReg) { } } -X64Reg X64IRRegCache::F(IRReg mipsReg) { +X64Reg X64IRRegCache::FX(IRReg mipsReg) { _dbg_assert_(IsValidFPR(mipsReg)); _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG); if (mr[mipsReg + 32].loc == MIPSLoc::FREG) { diff --git a/Core/MIPS/x86/X64IRRegCache.h b/Core/MIPS/x86/X64IRRegCache.h index 5054caeaf3..2c644275ff 100644 --- a/Core/MIPS/x86/X64IRRegCache.h +++ b/Core/MIPS/x86/X64IRRegCache.h @@ -58,9 +58,11 @@ public: Gen::X64Reg GetAndLockTempR(); - Gen::X64Reg R(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer - Gen::X64Reg RPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer - Gen::X64Reg F(IRReg preg); + Gen::OpArg R(IRReg preg); + Gen::OpArg F(IRReg preg); + Gen::X64Reg RX(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer + Gen::X64Reg RXPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer + Gen::X64Reg FX(IRReg preg); protected: const int *GetAllocationOrder(MIPSLoc type, int &count, int &base) const override;