diff --git a/Core/MIPS/ARM64/Arm64CompVFPU.cpp b/Core/MIPS/ARM64/Arm64CompVFPU.cpp index 93ad88b910..4cf488f10d 100644 --- a/Core/MIPS/ARM64/Arm64CompVFPU.cpp +++ b/Core/MIPS/ARM64/Arm64CompVFPU.cpp @@ -929,9 +929,14 @@ namespace MIPSComp { // rt = 0, imm = 255 appears to be used as a CPU interlock by some games. if (rt != 0) { if (imm < 128) { //R(rt) = VI(imm); - fpr.MapRegV(imm, 0); - gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); - fp.FMOV(gpr.R(rt), fpr.V(imm)); + if (!fpr.IsInRAMV(imm)) { + fpr.MapRegV(imm, 0); + gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); + fp.FMOV(gpr.R(rt), fpr.V(imm)); + } else { + gpr.MapReg(rt, MAP_NOINIT | MAP_DIRTY); + LDR(INDEX_UNSIGNED, gpr.R(rt), CTXREG, fpr.GetMipsRegOffsetV(imm)); + } } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc if (imm - 128 == VFPU_CTRL_CC) { if (gpr.IsImm(MIPS_REG_VFPUCC)) { @@ -955,9 +960,17 @@ namespace MIPSComp { case 7: // mtv if (imm < 128) { - gpr.MapReg(rt); - fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); - fp.FMOV(fpr.V(imm), gpr.R(rt)); + if (rt == MIPS_REG_ZERO) { + fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); + fp.MOVI2F(fpr.V(imm), 0.0f, SCRATCH1); + } else if (!gpr.IsInRAM(rt)) { + gpr.MapReg(rt); + fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); + fp.FMOV(fpr.V(imm), gpr.R(rt)); + } else { + fpr.MapRegV(imm, MAP_DIRTY | MAP_NOINIT); + fp.LDR(32, INDEX_UNSIGNED, fpr.V(imm), CTXREG, gpr.GetMipsRegOffset(rt)); + } } else if (imm < 128 + VFPU_CTRL_MAX) { //mtvc //currentMIPS->vfpuCtrl[imm - 128] = R(rt); if (imm - 128 == VFPU_CTRL_CC) { if (gpr.IsImm(rt)) { diff --git a/Core/MIPS/ARM64/Arm64RegCache.cpp b/Core/MIPS/ARM64/Arm64RegCache.cpp index fd888ac5f8..f20cdf8918 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.cpp +++ b/Core/MIPS/ARM64/Arm64RegCache.cpp @@ -134,6 +134,10 @@ void Arm64RegCache::FlushBeforeCall() { FlushArmReg(W30); } +bool Arm64RegCache::IsInRAM(MIPSGPReg reg) { + return mr[reg].loc == ML_MEM; +} + bool Arm64RegCache::IsMapped(MIPSGPReg mipsReg) { return mr[mipsReg].loc == ML_ARMREG || mr[mipsReg].loc == ML_ARMREG_IMM; } diff --git a/Core/MIPS/ARM64/Arm64RegCache.h b/Core/MIPS/ARM64/Arm64RegCache.h index ff3efe20de..5225c8bfb0 100644 --- a/Core/MIPS/ARM64/Arm64RegCache.h +++ b/Core/MIPS/ARM64/Arm64RegCache.h @@ -109,6 +109,7 @@ public: bool IsMapped(MIPSGPReg reg); bool IsMappedAsPointer(MIPSGPReg reg); + bool IsInRAM(MIPSGPReg reg); void MarkDirty(Arm64Gen::ARM64Reg reg); void MapIn(MIPSGPReg rs); diff --git a/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp b/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp index acc10229e6..6ff80d5c8f 100644 --- a/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp +++ b/Core/MIPS/ARM64/Arm64RegCacheFPU.cpp @@ -110,6 +110,10 @@ bool Arm64RegCacheFPU::IsMapped(MIPSReg r) { return mr[r].loc == ML_ARMREG; } +bool Arm64RegCacheFPU::IsInRAM(MIPSReg r) { + return mr[r].loc == ML_MEM; +} + ARM64Reg Arm64RegCacheFPU::MapReg(MIPSReg mipsReg, int mapFlags) { // INFO_LOG(JIT, "FPR MapReg: %i flags=%i", mipsReg, mapFlags); if (jo_->useASIMDVFPU && mipsReg >= 32) { diff --git a/Core/MIPS/ARM64/Arm64RegCacheFPU.h b/Core/MIPS/ARM64/Arm64RegCacheFPU.h index 4822b32363..aa162a1c55 100644 --- a/Core/MIPS/ARM64/Arm64RegCacheFPU.h +++ b/Core/MIPS/ARM64/Arm64RegCacheFPU.h @@ -114,6 +114,9 @@ public: void MapDirtyIn(MIPSReg rd, MIPSReg rs, bool avoidLoad = true); void MapDirtyInIn(MIPSReg rd, MIPSReg rs, MIPSReg rt, bool avoidLoad = true); bool IsMapped(MIPSReg r); + bool IsMappedV(MIPSReg r) { return IsMapped((MIPSReg)(r + 32)); } + bool IsInRAM(MIPSReg r); + bool IsInRAMV(MIPSReg r) { return IsInRAM((MIPSReg)(r + 32)); } void FlushArmReg(Arm64Gen::ARM64Reg r); void FlushR(MIPSReg r); void DiscardR(MIPSReg r); @@ -145,14 +148,14 @@ public: void SetEmitter(Arm64Gen::ARM64XEmitter *emitter, Arm64Gen::ARM64FloatEmitter *fp) { emit_ = emitter; fp_ = fp; } int GetMipsRegOffset(MIPSReg r); + int GetMipsRegOffsetV(MIPSReg r) { + return GetMipsRegOffset(r + 32); + } private: Arm64Gen::ARM64Reg ARM64RegForFlush(int r); MIPSReg GetTempR(); const Arm64Gen::ARM64Reg *GetMIPSAllocationOrder(int &count); - int GetMipsRegOffsetV(MIPSReg r) { - return GetMipsRegOffset(r + 32); - } void SetupInitialRegs();