diff --git a/Core/MIPS/IR/IRRegCache.cpp b/Core/MIPS/IR/IRRegCache.cpp index 90f677fc94..8d9a0a74d0 100644 --- a/Core/MIPS/IR/IRRegCache.cpp +++ b/Core/MIPS/IR/IRRegCache.cpp @@ -22,6 +22,7 @@ #include #include "Common/Log.h" #include "Common/LogReporting.h" +#include "Core/MemMap.h" #include "Core/MIPS/IR/IRAnalysis.h" #include "Core/MIPS/IR/IRRegCache.h" #include "Core/MIPS/IR/IRInst.h" @@ -282,6 +283,40 @@ void IRNativeRegCacheBase::SetSpillLockIRIndex(IRReg r1, IRReg r2, IRReg r3, IRR mr[r4 + offset].spillLockIRIndex = index; } +void IRNativeRegCacheBase::MarkGPRDirty(IRReg gpr, bool andNormalized32) { + _assert_(IsGPRMapped(gpr)); + if (!IsGPRMapped(gpr)) + return; + + IRNativeReg nreg = mr[gpr].nReg; + nr[nreg].isDirty = true; + nr[nreg].normalized32 = andNormalized32; + // If reg is written to, pointerification is assumed lost. + nr[nreg].pointerified = false; + if (mr[gpr].loc == MIPSLoc::REG_AS_PTR || mr[gpr].loc == MIPSLoc::REG_IMM) { + mr[gpr].loc = MIPSLoc::REG; + mr[gpr].imm = -1; + } + _dbg_assert_(mr[gpr].loc == MIPSLoc::REG); +} + +void IRNativeRegCacheBase::MarkGPRAsPointerDirty(IRReg gpr) { + _assert_(IsGPRMappedAsPointer(gpr)); + if (!IsGPRMappedAsPointer(gpr)) + return; + +#ifdef MASKED_PSP_MEMORY + if (mr[gpr].loc == MIPSLoc::REG_AS_PTR) { + _assert_msg_(false, "MarkGPRAsPointerDirty is not possible when using MASKED_PSP_MEMORY"); + } +#endif + + IRNativeReg nreg = mr[gpr].nReg; + _dbg_assert_(!nr[nreg].normalized32); + nr[nreg].isDirty = true; + // Stays pointerified or REG_AS_PTR. +} + IRNativeReg IRNativeRegCacheBase::AllocateReg(MIPSLoc type) { _dbg_assert_(type == MIPSLoc::REG || type == MIPSLoc::FREG || type == MIPSLoc::VREG); diff --git a/Core/MIPS/IR/IRRegCache.h b/Core/MIPS/IR/IRRegCache.h index 0e9e41acf9..f5301f8197 100644 --- a/Core/MIPS/IR/IRRegCache.h +++ b/Core/MIPS/IR/IRRegCache.h @@ -166,6 +166,9 @@ public: void ReleaseSpillLockGPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); void ReleaseSpillLockFPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); + void MarkGPRDirty(IRReg gpr, bool andNormalized32 = false); + void MarkGPRAsPointerDirty(IRReg gpr); + protected: virtual void SetupInitialRegs(); virtual const int *GetAllocationOrder(MIPSLoc type, int &count, int &base) const = 0; diff --git a/Core/MIPS/RiscV/RiscVCompALU.cpp b/Core/MIPS/RiscV/RiscVCompALU.cpp index e00beab181..69e4a47ee5 100644 --- a/Core/MIPS/RiscV/RiscVCompALU.cpp +++ b/Core/MIPS/RiscV/RiscVCompALU.cpp @@ -65,8 +65,8 @@ void RiscVJitBackend::CompIR_Arith(IRInst inst) { case IROp::AddConst: if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { // Typical of stack pointer updates. - if (gpr.IsGPRMappedAsPointer(inst.src1) && inst.dest == inst.src1 && allowPtrMath) { - gpr.MarkPtrDirty(gpr.RPtr(inst.dest)); + if (gpr.IsGPRMappedAsPointer(inst.dest) && inst.dest == inst.src1 && allowPtrMath) { + gpr.MarkGPRAsPointerDirty(inst.dest); ADDI(gpr.RPtr(inst.dest), gpr.RPtr(inst.dest), inst.constant); } else { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); @@ -107,7 +107,7 @@ void RiscVJitBackend::CompIR_Logic(IRInst inst) { } else if (inst.src1 != inst.dest) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } break; @@ -117,11 +117,11 @@ void RiscVJitBackend::CompIR_Logic(IRInst inst) { OR(gpr.R(inst.dest), gpr.R(inst.src1), gpr.R(inst.src2)); // If both were normalized before, the result is normalized. if (gpr.IsNormalized32(inst.src1) && gpr.IsNormalized32(inst.src2)) - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); } else if (inst.src1 != inst.dest) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } break; @@ -145,10 +145,10 @@ void RiscVJitBackend::CompIR_Logic(IRInst inst) { } // If the sign bits aren't cleared, and it was normalized before - it still is. if ((inst.constant & 0x80000000) != 0 && gpr.IsNormalized32(inst.src1)) - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); // Otherwise, if we cleared the sign bits, it's naturally normalized. else if ((inst.constant & 0x80000000) == 0) - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); break; case IROp::OrConst: @@ -162,7 +162,7 @@ void RiscVJitBackend::CompIR_Logic(IRInst inst) { } // Since our constant is normalized, oring its bits in won't hurt normalization. if (gpr.IsNormalized32(inst.src1)) - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); break; case IROp::XorConst: @@ -195,7 +195,7 @@ void RiscVJitBackend::CompIR_Assign(IRInst inst) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } break; @@ -280,7 +280,7 @@ void RiscVJitBackend::CompIR_Bits(IRInst inst) { if (XLEN >= 64) { // REV8 swaps the entire register, so get the 32 highest bits. SRAI(gpr.R(inst.dest), gpr.R(inst.dest), XLEN - 32); - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); } } else { CompIR_Generic(inst); @@ -339,7 +339,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } } else { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); @@ -355,7 +355,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } } else { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); @@ -372,7 +372,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } } else { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); @@ -385,7 +385,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } } else if (cpu_info.RiscV_Zbb) { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); @@ -434,7 +434,7 @@ void RiscVJitBackend::CompIR_Compare(IRInst inst) { LI(SCRATCH2, (int32_t)inst.constant); SLT(gpr.R(inst.dest), lhs, SCRATCH2); } - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); } break; @@ -514,14 +514,14 @@ void RiscVJitBackend::CompIR_CondAssign(IRInst inst) { NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); MAX(gpr.R(inst.dest), lhs, rhs); // Because we had to normalize the inputs, the output is normalized. - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); } else { CompIR_Generic(inst); } } else if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } break; @@ -532,14 +532,14 @@ void RiscVJitBackend::CompIR_CondAssign(IRInst inst) { NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); MIN(gpr.R(inst.dest), lhs, rhs); // Because we had to normalize the inputs, the output is normalized. - gpr.MarkDirty(gpr.R(inst.dest), true); + gpr.MarkGPRDirty(inst.dest, true); } else { CompIR_Generic(inst); } } else if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); MV(gpr.R(inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(inst.src1)); } break; @@ -556,25 +556,25 @@ void RiscVJitBackend::CompIR_HiLo(IRInst inst) { case IROp::MtLo: gpr.MapDirtyIn(IRREG_LO, inst.src1); MV(gpr.R(IRREG_LO), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(IRREG_LO), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(IRREG_LO, gpr.IsNormalized32(inst.src1)); break; case IROp::MtHi: gpr.MapDirtyIn(IRREG_HI, inst.src1); MV(gpr.R(IRREG_HI), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(IRREG_HI), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(IRREG_HI, gpr.IsNormalized32(inst.src1)); break; case IROp::MfLo: gpr.MapDirtyIn(inst.dest, IRREG_LO); MV(gpr.R(inst.dest), gpr.R(IRREG_LO)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(IRREG_LO)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(IRREG_LO)); break; case IROp::MfHi: gpr.MapDirtyIn(inst.dest, IRREG_HI); MV(gpr.R(inst.dest), gpr.R(IRREG_HI)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(IRREG_HI)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(IRREG_HI)); break; default: @@ -612,7 +612,7 @@ void RiscVJitBackend::CompIR_Mult(IRInst inst) { }; auto splitMulResult = [&] { SRAI(gpr.R(IRREG_HI), gpr.R(IRREG_LO), 32); - gpr.MarkDirty(gpr.R(IRREG_HI), true); + gpr.MarkGPRDirty(IRREG_HI, true); }; RiscVReg lhs = INVALID_REG; diff --git a/Core/MIPS/RiscV/RiscVCompSystem.cpp b/Core/MIPS/RiscV/RiscVCompSystem.cpp index f727979b53..ce41e6faf0 100644 --- a/Core/MIPS/RiscV/RiscVCompSystem.cpp +++ b/Core/MIPS/RiscV/RiscVCompSystem.cpp @@ -96,7 +96,7 @@ void RiscVJitBackend::CompIR_Transfer(IRInst inst) { case IROp::SetCtrlVFPUReg: gpr.MapDirtyIn(IRREG_VFPU_CTRL_BASE + inst.dest, inst.src1); MV(gpr.R(IRREG_VFPU_CTRL_BASE + inst.dest), gpr.R(inst.src1)); - gpr.MarkDirty(gpr.R(IRREG_VFPU_CTRL_BASE + inst.dest), gpr.IsNormalized32(inst.src1)); + gpr.MarkGPRDirty(IRREG_VFPU_CTRL_BASE + inst.dest, gpr.IsNormalized32(inst.src1)); break; case IROp::SetCtrlVFPUFReg: @@ -113,7 +113,7 @@ void RiscVJitBackend::CompIR_Transfer(IRInst inst) { case IROp::FpCondToReg: gpr.MapDirtyIn(inst.dest, IRREG_FPCOND); MV(gpr.R(inst.dest), gpr.R(IRREG_FPCOND)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(IRREG_FPCOND)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(IRREG_FPCOND)); break; case IROp::FpCtrlFromReg: @@ -153,7 +153,7 @@ void RiscVJitBackend::CompIR_Transfer(IRInst inst) { case IROp::VfpuCtrlToReg: gpr.MapDirtyIn(inst.dest, IRREG_VFPU_CTRL_BASE + inst.src1); MV(gpr.R(inst.dest), gpr.R(IRREG_VFPU_CTRL_BASE + inst.src1)); - gpr.MarkDirty(gpr.R(inst.dest), gpr.IsNormalized32(IRREG_VFPU_CTRL_BASE + inst.src1)); + gpr.MarkGPRDirty(inst.dest, gpr.IsNormalized32(IRREG_VFPU_CTRL_BASE + inst.src1)); break; case IROp::FMovFromGPR: diff --git a/Core/MIPS/RiscV/RiscVRegCache.cpp b/Core/MIPS/RiscV/RiscVRegCache.cpp index b836e1dd81..484628e84d 100644 --- a/Core/MIPS/RiscV/RiscVRegCache.cpp +++ b/Core/MIPS/RiscV/RiscVRegCache.cpp @@ -137,35 +137,6 @@ bool RiscVRegCache::IsNormalized32(IRReg mipsReg) { return false; } -void RiscVRegCache::MarkDirty(RiscVReg reg, bool andNormalized32) { - // Can't mark X0 dirty. - _dbg_assert_(reg > X0 && reg <= X31); - nr[reg].isDirty = true; - nr[reg].normalized32 = andNormalized32; - // If reg is written to, pointerification is lost. - nr[reg].pointerified = false; - if (nr[reg].mipsReg != IRREG_INVALID) { - RegStatusMIPS &m = mr[nr[reg].mipsReg]; - if (m.loc == MIPSLoc::REG_AS_PTR || m.loc == MIPSLoc::REG_IMM) { - m.loc = MIPSLoc::REG; - m.imm = -1; - } - _dbg_assert_(m.loc == MIPSLoc::REG); - } -} - -void RiscVRegCache::MarkPtrDirty(RiscVReg reg) { - // Can't mark X0 dirty. - _dbg_assert_(reg > X0 && reg <= X31); - _dbg_assert_(!nr[reg].normalized32); - nr[reg].isDirty = true; - if (nr[reg].mipsReg != IRREG_INVALID) { - _dbg_assert_(mr[nr[reg].mipsReg].loc == MIPSLoc::REG_AS_PTR); - } else { - _dbg_assert_(nr[reg].pointerified); - } -} - RiscVGen::RiscVReg RiscVRegCache::Normalize32(IRReg mipsReg, RiscVGen::RiscVReg destReg) { _dbg_assert_(IsValidGPR(mipsReg)); _dbg_assert_(destReg == INVALID_REG || (destReg > X0 && destReg <= X31)); diff --git a/Core/MIPS/RiscV/RiscVRegCache.h b/Core/MIPS/RiscV/RiscVRegCache.h index 28618e040d..960bd607aa 100644 --- a/Core/MIPS/RiscV/RiscVRegCache.h +++ b/Core/MIPS/RiscV/RiscVRegCache.h @@ -72,8 +72,6 @@ public: bool IsNormalized32(IRReg reg); - void MarkDirty(RiscVGen::RiscVReg reg, bool andNormalized32 = false); - void MarkPtrDirty(RiscVGen::RiscVReg reg); // Copies to another reg if specified, otherwise same reg. RiscVGen::RiscVReg Normalize32(IRReg reg, RiscVGen::RiscVReg destReg = RiscVGen::INVALID_REG); void MapIn(IRReg rs);