diff --git a/Core/MIPS/IR/IRRegCache.cpp b/Core/MIPS/IR/IRRegCache.cpp index 001ec77400..90f677fc94 100644 --- a/Core/MIPS/IR/IRRegCache.cpp +++ b/Core/MIPS/IR/IRRegCache.cpp @@ -130,6 +130,158 @@ void IRNativeRegCacheBase::SetupInitialRegs() { mrInitial_[MIPS_REG_ZERO].imm = 0; } +bool IRNativeRegCacheBase::IsGPRInRAM(IRReg gpr) { + _dbg_assert_(IsValidGPR(gpr)); + return mr[gpr].loc == MIPSLoc::MEM; +} + +bool IRNativeRegCacheBase::IsFPRInRAM(IRReg fpr) { + _dbg_assert_(IsValidFPR(fpr)); + return mr[fpr + 32].loc == MIPSLoc::MEM; +} + +bool IRNativeRegCacheBase::IsGPRMapped(IRReg gpr) { + _dbg_assert_(IsValidGPR(gpr)); + return mr[gpr].loc == MIPSLoc::REG || mr[gpr].loc == MIPSLoc::REG_IMM; +} + +bool IRNativeRegCacheBase::IsFPRMapped(IRReg fpr) { + _dbg_assert_(IsValidFPR(fpr)); + return mr[fpr + 32].loc == MIPSLoc::FREG || mr[fpr + 32].loc == MIPSLoc::VREG; +} + +bool IRNativeRegCacheBase::IsGPRMappedAsPointer(IRReg gpr) { + _dbg_assert_(IsValidGPR(gpr)); + if (mr[gpr].loc == MIPSLoc::REG) { + return nr[mr[gpr].nReg].pointerified; + } else if (mr[gpr].loc == MIPSLoc::REG_IMM) { + _assert_msg_(!nr[mr[gpr].nReg].pointerified, "Really shouldn't be pointerified here"); + } else if (mr[gpr].loc == MIPSLoc::REG_AS_PTR) { + return true; + } + return false; +} + +bool IRNativeRegCacheBase::IsGPRMappedAsStaticPointer(IRReg gpr) { + if (IsGPRMappedAsPointer(gpr)) { + return mr[gpr].isStatic; + } + return false; +} + +bool IRNativeRegCacheBase::IsGPRImm(IRReg gpr) { + _dbg_assert_(IsValidGPR(gpr)); + if (gpr == MIPS_REG_ZERO) + return true; + return mr[gpr].loc == MIPSLoc::IMM || mr[gpr].loc == MIPSLoc::REG_IMM; +} + +bool IRNativeRegCacheBase::IsGPR2Imm(IRReg base) { + return IsGPRImm(base) && IsGPRImm(base + 1); +} + +uint32_t IRNativeRegCacheBase::GetGPRImm(IRReg gpr) { + _dbg_assert_(IsValidGPR(gpr)); + if (gpr == MIPS_REG_ZERO) + return 0; + if (mr[gpr].loc != MIPSLoc::IMM && mr[gpr].loc != MIPSLoc::REG_IMM) { + _assert_msg_(mr[gpr].loc == MIPSLoc::IMM || mr[gpr].loc == MIPSLoc::REG_IMM, "GPR %d not in an imm", gpr); + } + return mr[gpr].imm; +} + +uint64_t IRNativeRegCacheBase::GetGPR2Imm(IRReg base) { + return (uint64_t)GetGPRImm(base) | ((uint64_t)GetGPRImm(base + 1) << 32); +} + +void IRNativeRegCacheBase::SetGPRImm(IRReg gpr, uint32_t immVal) { + _dbg_assert_(IsValidGPR(gpr)); + if (gpr == MIPS_REG_ZERO && immVal != 0) { + ERROR_LOG_REPORT(JIT, "Trying to set immediate %08x to r0", immVal); + return; + } + + if (mr[gpr].loc == MIPSLoc::REG_IMM && mr[gpr].imm == immVal) { + // Already have that value, let's keep it in the reg. + return; + } + + if (mr[gpr].nReg != -1) { + // Zap existing value if cached in a reg. + _assert_msg_(mr[gpr].lane == -1, "Should not be a multilane reg"); + DiscardNativeReg(mr[gpr].nReg); + } + + mr[gpr].loc = MIPSLoc::IMM; + mr[gpr].imm = immVal; +} + +void IRNativeRegCacheBase::SetGPR2Imm(IRReg base, uint64_t immVal) { + _dbg_assert_(IsValidGPRNoZero(base)); + uint32_t imm0 = (uint32_t)(immVal & 0xFFFFFFFF); + uint32_t imm1 = (uint32_t)(immVal >> 32); + + if (IsGPRImm(base) && IsGPRImm(base + 1) && GetGPRImm(base) == imm0 && GetGPRImm(base + 1) == imm1) { + // Already set to this, don't bother. + return; + } + + if (mr[base].nReg != -1) { + // Zap existing value if cached in a reg. + DiscardNativeReg(mr[base].nReg); + if (mr[base + 1].nReg != -1) + DiscardNativeReg(mr[base + 1].nReg); + } + + mr[base].loc = MIPSLoc::IMM; + mr[base].imm = imm0; + mr[base + 1].loc = MIPSLoc::IMM; + mr[base + 1].imm = imm1; +} + +void IRNativeRegCacheBase::SpillLockGPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { + _dbg_assert_(IsValidGPR(r1)); + _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); + _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); + _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); + SetSpillLockIRIndex(r1, r2, r3, r4, 0, irIndex_); +} + +void IRNativeRegCacheBase::SpillLockFPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { + _dbg_assert_(IsValidFPR(r1)); + _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); + _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); + _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); + SetSpillLockIRIndex(r1, r2, r3, r4, 32, irIndex_); +} + +void IRNativeRegCacheBase::ReleaseSpillLockGPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { + _dbg_assert_(IsValidGPR(r1)); + _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); + _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); + _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); + SetSpillLockIRIndex(r1, r2, r3, r4, 0, -1); +} + +void IRNativeRegCacheBase::ReleaseSpillLockFPR(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { + _dbg_assert_(IsValidFPR(r1)); + _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); + _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); + _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); + SetSpillLockIRIndex(r1, r2, r3, r4, 32, -1); +} + +void IRNativeRegCacheBase::SetSpillLockIRIndex(IRReg r1, IRReg r2, IRReg r3, IRReg r4, int offset, int index) { + if (!mr[r1 + offset].isStatic) + mr[r1 + offset].spillLockIRIndex = index; + if (r2 != IRREG_INVALID && !mr[r2 + offset].isStatic) + mr[r2 + offset].spillLockIRIndex = index; + if (r3 != IRREG_INVALID && !mr[r3 + offset].isStatic) + mr[r3 + offset].spillLockIRIndex = index; + if (r4 != IRREG_INVALID && !mr[r4 + offset].isStatic) + mr[r4 + offset].spillLockIRIndex = index; +} + IRNativeReg IRNativeRegCacheBase::AllocateReg(MIPSLoc type) { _dbg_assert_(type == MIPSLoc::REG || type == MIPSLoc::FREG || type == MIPSLoc::VREG); @@ -248,7 +400,7 @@ void IRNativeRegCacheBase::DiscardNativeReg(IRNativeReg nreg) { // If it's not currently marked as in a reg, throw it away. for (IRReg m = nr[nreg].mipsReg; m < nr[nreg].mipsReg + lanes; ++m) { - _assert_msg_(!mr[m].isStatic, "Reg in lane %d mismatched static status", m - nr[nreg].mipsReg); + _assert_msg_(mr[m].isStatic, "Reg in lane %d mismatched static status", m - nr[nreg].mipsReg); for (int i = 0; i < numStatics; i++) { if (m == statics[i].mr) mr[m].loc = statics[i].loc; @@ -259,6 +411,7 @@ void IRNativeRegCacheBase::DiscardNativeReg(IRNativeReg nreg) { mr[m].loc = MIPSLoc::MEM; mr[m].nReg = -1; mr[m].imm = 0; + mr[m].lane = -1; _assert_msg_(!mr[m].isStatic, "Reg in lane %d mismatched static status", m - nr[nreg].mipsReg); } @@ -289,7 +442,9 @@ void IRNativeRegCacheBase::FlushNativeReg(IRNativeReg nreg) { bool isDirty = nr[nreg].isDirty; int8_t lanes = 0; for (IRReg m = nr[nreg].mipsReg; mr[m].nReg == nreg && m < IRREG_INVALID; ++m) { - _dbg_assert_(!mr[m].isStatic); + _assert_(!mr[m].isStatic); + // If we're flushing a native reg, better not be partially in mem or an imm. + _assert_(mr[m].loc != MIPSLoc::MEM && mr[m].loc != MIPSLoc::IMM); lanes++; } @@ -310,6 +465,7 @@ void IRNativeRegCacheBase::FlushNativeReg(IRNativeReg nreg) { // Note that it loses its imm status, because imms are always dirty. mreg.loc = MIPSLoc::MEM; mreg.imm = 0; + mreg.lane = -1; } nr[nreg].mipsReg = IRREG_INVALID; diff --git a/Core/MIPS/IR/IRRegCache.h b/Core/MIPS/IR/IRRegCache.h index 82d79f418e..0e9e41acf9 100644 --- a/Core/MIPS/IR/IRRegCache.h +++ b/Core/MIPS/IR/IRRegCache.h @@ -102,7 +102,7 @@ protected: // If in a register, what index (into nr array)? IRNativeReg nReg = -1; // If a known immediate value, what value? - uint64_t imm = 0; + uint32_t imm = 0; // Locked from spilling (i.e. used by current instruction) as of what IR instruction? int spillLockIRIndex = -1; // If in a multipart reg (vector or HI/LO), which lane? @@ -145,6 +145,27 @@ public: irIndex_ = index; } + bool IsGPRInRAM(IRReg gpr); + bool IsFPRInRAM(IRReg fpr); + bool IsGPRMapped(IRReg gpr); + bool IsFPRMapped(IRReg fpr); + bool IsGPRMappedAsPointer(IRReg gpr); + bool IsGPRMappedAsStaticPointer(IRReg gpr); + + bool IsGPRImm(IRReg gpr); + bool IsGPR2Imm(IRReg base); + uint32_t GetGPRImm(IRReg gpr); + uint64_t GetGPR2Imm(IRReg first); + void SetGPRImm(IRReg gpr, uint32_t immval); + void SetGPR2Imm(IRReg first, uint64_t immval); + + // Protect the native registers containing register froms spilling, to ensure that + // it's being kept allocated. + void SpillLockGPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); + void SpillLockFPR(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); + 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); + protected: virtual void SetupInitialRegs(); virtual const int *GetAllocationOrder(MIPSLoc type, int &count, int &base) const = 0; @@ -161,6 +182,8 @@ protected: virtual void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state); virtual void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) = 0; + void SetSpillLockIRIndex(IRReg reg, IRReg reg2, IRReg reg3, IRReg reg4, int offset, int index); + bool IsValidGPR(IRReg r) const; bool IsValidGPRNoZero(IRReg r) const; bool IsValidFPR(IRReg r) const; diff --git a/Core/MIPS/RiscV/RiscVCompALU.cpp b/Core/MIPS/RiscV/RiscVCompALU.cpp index c1939e9867..e00beab181 100644 --- a/Core/MIPS/RiscV/RiscVCompALU.cpp +++ b/Core/MIPS/RiscV/RiscVCompALU.cpp @@ -65,7 +65,7 @@ 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.IsMappedAsPointer(inst.src1) && inst.dest == inst.src1 && allowPtrMath) { + if (gpr.IsGPRMappedAsPointer(inst.src1) && inst.dest == inst.src1 && allowPtrMath) { gpr.MarkPtrDirty(gpr.RPtr(inst.dest)); ADDI(gpr.RPtr(inst.dest), gpr.RPtr(inst.dest), inst.constant); } else { @@ -127,7 +127,7 @@ void RiscVJitBackend::CompIR_Logic(IRInst inst) { case IROp::Xor: if (inst.src1 == inst.src2) { - gpr.SetImm(inst.dest, 0); + gpr.SetGPRImm(inst.dest, 0); } else { gpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2); XOR(gpr.R(inst.dest), gpr.R(inst.src1), gpr.R(inst.src2)); @@ -334,7 +334,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { case IROp::ShlImm: // Shouldn't happen, but let's be safe of any passes that modify the ops. if (inst.src2 >= 32) { - gpr.SetImm(inst.dest, 0); + gpr.SetGPRImm(inst.dest, 0); } else if (inst.src2 == 0) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); @@ -350,7 +350,7 @@ void RiscVJitBackend::CompIR_Shift(IRInst inst) { case IROp::ShrImm: // Shouldn't happen, but let's be safe of any passes that modify the ops. if (inst.src2 >= 32) { - gpr.SetImm(inst.dest, 0); + gpr.SetGPRImm(inst.dest, 0); } else if (inst.src2 == 0) { if (inst.dest != inst.src1) { gpr.MapDirtyIn(inst.dest, inst.src1); @@ -408,12 +408,11 @@ void RiscVJitBackend::CompIR_Compare(IRInst inst) { RiscVReg rhs = INVALID_REG; switch (inst.op) { case IROp::Slt: - gpr.SpillLock(inst.dest, inst.src1, inst.src2); + gpr.SpillLockGPR(inst.dest, inst.src1, inst.src2); gpr.MapReg(inst.src1); gpr.MapReg(inst.src2); NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); gpr.MapReg(inst.dest, MIPSMap::NOINIT | MIPSMap::MARK_NORM32); - gpr.ReleaseSpillLock(inst.dest, inst.src1, inst.src2); SLT(gpr.R(inst.dest), lhs, rhs); break; @@ -424,11 +423,10 @@ void RiscVJitBackend::CompIR_Compare(IRInst inst) { gpr.MapDirtyIn(inst.dest, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); SRLIW(gpr.R(inst.dest), gpr.R(inst.src1), 31); } else { - gpr.SpillLock(inst.dest, inst.src1); + gpr.SpillLockGPR(inst.dest, inst.src1); gpr.MapReg(inst.src1); NormalizeSrc1(inst, &lhs, SCRATCH1, false); gpr.MapReg(inst.dest, MIPSMap::NOINIT | MIPSMap::MARK_NORM32); - gpr.ReleaseSpillLock(inst.dest, inst.src1); if ((int32_t)inst.constant >= -2048 && (int32_t)inst.constant <= 2047) { SLTI(gpr.R(inst.dest), lhs, (int32_t)inst.constant); @@ -441,26 +439,24 @@ void RiscVJitBackend::CompIR_Compare(IRInst inst) { break; case IROp::SltU: - gpr.SpillLock(inst.dest, inst.src1, inst.src2); + gpr.SpillLockGPR(inst.dest, inst.src1, inst.src2); gpr.MapReg(inst.src1); gpr.MapReg(inst.src2); // It's still fine to sign extend, the biggest just get even bigger. NormalizeSrc12(inst, &lhs, &rhs, SCRATCH1, SCRATCH2, true); gpr.MapReg(inst.dest, MIPSMap::NOINIT | MIPSMap::MARK_NORM32); - gpr.ReleaseSpillLock(inst.dest, inst.src1, inst.src2); SLTU(gpr.R(inst.dest), lhs, rhs); break; case IROp::SltUConst: if (inst.constant == 0) { - gpr.SetImm(inst.dest, 0); + gpr.SetGPRImm(inst.dest, 0); } else { - gpr.SpillLock(inst.dest, inst.src1); + gpr.SpillLockGPR(inst.dest, inst.src1); gpr.MapReg(inst.src1); NormalizeSrc1(inst, &lhs, SCRATCH1, false); gpr.MapReg(inst.dest, MIPSMap::NOINIT | MIPSMap::MARK_NORM32); - gpr.ReleaseSpillLock(inst.dest, inst.src1); // We sign extend because we're comparing against something normalized. // It's also the most efficient to set. diff --git a/Core/MIPS/RiscV/RiscVCompFPU.cpp b/Core/MIPS/RiscV/RiscVCompFPU.cpp index bbad21f9cc..7b92468713 100644 --- a/Core/MIPS/RiscV/RiscVCompFPU.cpp +++ b/Core/MIPS/RiscV/RiscVCompFPU.cpp @@ -346,7 +346,7 @@ void RiscVJitBackend::CompIR_FCompare(IRInst inst) { case IROp::FCmp: switch (inst.dest) { case IRFpCompareMode::False: - gpr.SetImm(IRREG_FPCOND, 0); + gpr.SetGPRImm(IRREG_FPCOND, 0); break; case IRFpCompareMode::EitherUnordered: @@ -584,7 +584,7 @@ void RiscVJitBackend::CompIR_FSpecial(IRInst inst) { gpr.FlushBeforeCall(); fpr.FlushBeforeCall(); // It might be in a non-volatile register. - if (fpr.IsMapped(inst.src1)) { + if (fpr.IsFPRMapped(inst.src1)) { FMV(32, F10, fpr.R(inst.src1)); } else { int offset = offsetof(MIPSState, f) + inst.src1 * 4; diff --git a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp index 09ac714519..348221ef4b 100644 --- a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp +++ b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp @@ -66,7 +66,7 @@ int32_t RiscVJitBackend::AdjustForAddressOffset(RiscVGen::RiscVReg *reg, int32_t void RiscVJitBackend::CompIR_Load(IRInst inst) { CONDITIONAL_DISABLE; - gpr.SpillLock(inst.dest, inst.src1); + gpr.SpillLockGPR(inst.dest, inst.src1); RiscVReg addrReg = INVALID_REG; if (inst.src1 == MIPS_REG_ZERO) { // This will get changed by AdjustForAddressOffset. @@ -74,7 +74,7 @@ void RiscVJitBackend::CompIR_Load(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if (jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) { + } else if (jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -82,7 +82,6 @@ void RiscVJitBackend::CompIR_Load(IRInst inst) { } // With NOINIT, MapReg won't subtract MEMBASEREG even if dest == src1. gpr.MapReg(inst.dest, MIPSMap::NOINIT | MIPSMap::MARK_NORM32); - gpr.ReleaseSpillLock(inst.dest, inst.src1); s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); @@ -112,7 +111,7 @@ void RiscVJitBackend::CompIR_Load(IRInst inst) { case IROp::Load32Linked: if (inst.dest != MIPS_REG_ZERO) LW(gpr.R(inst.dest), addrReg, imm); - gpr.SetImm(IRREG_LLBIT, 1); + gpr.SetGPRImm(IRREG_LLBIT, 1); break; default: @@ -147,7 +146,7 @@ void RiscVJitBackend::CompIR_FLoad(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if (jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) { + } else if (jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -180,7 +179,7 @@ void RiscVJitBackend::CompIR_VecLoad(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if (jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) { + } else if (jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -210,7 +209,7 @@ void RiscVJitBackend::CompIR_VecLoad(IRInst inst) { void RiscVJitBackend::CompIR_Store(IRInst inst) { CONDITIONAL_DISABLE; - gpr.SpillLock(inst.src3, inst.src1); + gpr.SpillLockGPR(inst.src3, inst.src1); RiscVReg addrReg = INVALID_REG; if (inst.src1 == MIPS_REG_ZERO) { // This will get changed by AdjustForAddressOffset. @@ -218,7 +217,7 @@ void RiscVJitBackend::CompIR_Store(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if ((jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { + } else if ((jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -227,7 +226,6 @@ void RiscVJitBackend::CompIR_Store(IRInst inst) { RiscVReg valueReg = gpr.TryMapTempImm(inst.src3); if (valueReg == INVALID_REG) valueReg = gpr.MapReg(inst.src3); - gpr.ReleaseSpillLock(inst.src3, inst.src1); s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); @@ -257,7 +255,7 @@ void RiscVJitBackend::CompIR_CondStore(IRInst inst) { if (inst.op != IROp::Store32Conditional) INVALIDOP; - gpr.SpillLock(IRREG_LLBIT, inst.src3, inst.src1); + gpr.SpillLockGPR(IRREG_LLBIT, inst.src3, inst.src1); RiscVReg addrReg = INVALID_REG; if (inst.src1 == MIPS_REG_ZERO) { // This will get changed by AdjustForAddressOffset. @@ -265,7 +263,7 @@ void RiscVJitBackend::CompIR_CondStore(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if ((jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { + } else if ((jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -273,7 +271,6 @@ void RiscVJitBackend::CompIR_CondStore(IRInst inst) { } gpr.MapReg(inst.src3, inst.dest == MIPS_REG_ZERO ? MIPSMap::INIT : MIPSMap::DIRTY); gpr.MapReg(IRREG_LLBIT); - gpr.ReleaseSpillLock(IRREG_LLBIT, inst.src3, inst.src1); s32 imm = AdjustForAddressOffset(&addrReg, inst.constant); @@ -320,7 +317,7 @@ void RiscVJitBackend::CompIR_FStore(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if (jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) { + } else if (jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); @@ -353,7 +350,7 @@ void RiscVJitBackend::CompIR_VecStore(IRInst inst) { #ifdef MASKED_PSP_MEMORY inst.constant &= Memory::MEMVIEW32_MASK; #endif - } else if (jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) { + } else if (jo.cachePointers || gpr.IsGPRMappedAsPointer(inst.src1)) { addrReg = gpr.MapRegAsPointer(inst.src1); } else { SetScratch1ToSrc1Address(inst.src1); diff --git a/Core/MIPS/RiscV/RiscVCompSystem.cpp b/Core/MIPS/RiscV/RiscVCompSystem.cpp index dbfa392a2b..f727979b53 100644 --- a/Core/MIPS/RiscV/RiscVCompSystem.cpp +++ b/Core/MIPS/RiscV/RiscVCompSystem.cpp @@ -45,7 +45,7 @@ void RiscVJitBackend::CompIR_Basic(IRInst inst) { case IROp::SetConst: // Sign extend all constants. We get 0xFFFFFFFF sometimes, and it's more work to truncate. // The register only holds 32 bits in the end anyway. - gpr.SetImm(inst.dest, (int32_t)inst.constant); + gpr.SetGPRImm(inst.dest, (int32_t)inst.constant); break; case IROp::SetConstF: @@ -90,7 +90,7 @@ void RiscVJitBackend::CompIR_Transfer(IRInst inst) { switch (inst.op) { case IROp::SetCtrlVFPU: - gpr.SetImm(IRREG_VFPU_CTRL_BASE + inst.dest, (int32_t)inst.constant); + gpr.SetGPRImm(IRREG_VFPU_CTRL_BASE + inst.dest, (int32_t)inst.constant); break; case IROp::SetCtrlVFPUReg: @@ -158,7 +158,7 @@ void RiscVJitBackend::CompIR_Transfer(IRInst inst) { case IROp::FMovFromGPR: fpr.MapReg(inst.dest, MIPSMap::NOINIT); - if (gpr.IsImm(inst.src1) && gpr.GetImm(inst.src1) == 0) { + if (gpr.IsGPRImm(inst.src1) && gpr.GetGPRImm(inst.src1) == 0) { FCVT(FConv::S, FConv::W, fpr.R(inst.dest), R_ZERO); } else { gpr.MapReg(inst.src1); diff --git a/Core/MIPS/RiscV/RiscVCompVec.cpp b/Core/MIPS/RiscV/RiscVCompVec.cpp index 52e9e5d118..3e0f5c1d34 100644 --- a/Core/MIPS/RiscV/RiscVCompVec.cpp +++ b/Core/MIPS/RiscV/RiscVCompVec.cpp @@ -41,11 +41,9 @@ void RiscVJitBackend::CompIR_VecAssign(IRInst inst) { switch (inst.op) { case IROp::Vec4Init: for (int i = 0; i < 4; ++i) - fpr.SpillLock(inst.dest + i); + fpr.SpillLockFPR(inst.dest + i); for (int i = 0; i < 4; ++i) fpr.MapReg(inst.dest + i, MIPSMap::NOINIT); - for (int i = 0; i < 4; ++i) - fpr.ReleaseSpillLock(inst.dest + i); // TODO: Check if FCVT/FMV/FL is better. switch ((Vec4Init)inst.src1) { @@ -220,10 +218,9 @@ void RiscVJitBackend::CompIR_VecArith(IRInst inst) { break; case IROp::Vec4Scale: - fpr.SpillLock(inst.src2); + fpr.SpillLockFPR(inst.src2); fpr.MapReg(inst.src2); fpr.Map4DirtyIn(inst.dest, inst.src1); - fpr.ReleaseSpillLock(inst.src2); for (int i = 0; i < 4; ++i) FMUL(32, fpr.R(inst.dest + i), fpr.R(inst.src1 + i), fpr.R(inst.src2)); break; @@ -252,21 +249,16 @@ void RiscVJitBackend::CompIR_VecHoriz(IRInst inst) { switch (inst.op) { case IROp::Vec4Dot: // TODO: Maybe some option to call the slow accurate mode? - fpr.SpillLock(inst.dest); + fpr.SpillLockFPR(inst.dest); for (int i = 0; i < 4; ++i) { - fpr.SpillLock(inst.src1 + i); - fpr.SpillLock(inst.src2 + i); + fpr.SpillLockFPR(inst.src1 + i); + fpr.SpillLockFPR(inst.src2 + i); } for (int i = 0; i < 4; ++i) { fpr.MapReg(inst.src1 + i); fpr.MapReg(inst.src2 + i); } fpr.MapReg(inst.dest, MIPSMap::NOINIT); - for (int i = 0; i < 4; ++i) { - fpr.ReleaseSpillLock(inst.src1 + i); - fpr.ReleaseSpillLock(inst.src2 + i); - } - fpr.ReleaseSpillLock(inst.dest); if ((inst.dest < inst.src1 + 4 && inst.dest >= inst.src1) || (inst.dest < inst.src2 + 4 && inst.dest >= inst.src2)) { // This means inst.dest overlaps one of src1 or src2. We have to do that one first. @@ -303,9 +295,9 @@ void RiscVJitBackend::CompIR_VecPack(IRInst inst) { break; case IROp::Vec4Unpack8To32: - fpr.SpillLock(inst.src1); + fpr.SpillLockFPR(inst.src1); for (int i = 0; i < 4; ++i) - fpr.SpillLock(inst.dest + i); + fpr.SpillLockFPR(inst.dest + i); fpr.MapReg(inst.src1); for (int i = 0; i < 4; ++i) fpr.MapReg(inst.dest + i, MIPSMap::NOINIT); @@ -324,9 +316,9 @@ void RiscVJitBackend::CompIR_VecPack(IRInst inst) { break; case IROp::Vec2Unpack16To32: - fpr.SpillLock(inst.src1); + fpr.SpillLockFPR(inst.src1); for (int i = 0; i < 2; ++i) - fpr.SpillLock(inst.dest + i); + fpr.SpillLockFPR(inst.dest + i); fpr.MapReg(inst.src1); for (int i = 0; i < 2; ++i) fpr.MapReg(inst.dest + i, MIPSMap::NOINIT); @@ -353,9 +345,9 @@ void RiscVJitBackend::CompIR_VecPack(IRInst inst) { break; case IROp::Vec4Pack31To8: - fpr.SpillLock(inst.dest); + fpr.SpillLockFPR(inst.dest); for (int i = 0; i < 4; ++i) { - fpr.SpillLock(inst.src1 + i); + fpr.SpillLockFPR(inst.src1 + i); fpr.MapReg(inst.src1 + i); } fpr.MapReg(inst.dest, MIPSMap::NOINIT); diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index d7663484b0..b31e762d39 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -355,9 +355,9 @@ void RiscVJitBackend::NormalizeSrc12(IRInst inst, RiscVReg *lhs, RiscVReg *rhs, RiscVReg RiscVJitBackend::NormalizeR(IRReg rs, IRReg rd, RiscVReg tempReg) { // For proper compare, we must sign extend so they both match or don't match. // But don't change pointers, in case one is SP (happens in LittleBigPlanet.) - if (gpr.IsImm(rs) && gpr.GetImm(rs) == 0) { + if (gpr.IsGPRImm(rs) && gpr.GetGPRImm(rs) == 0) { return R_ZERO; - } else if (gpr.IsMappedAsPointer(rs) || rs == rd) { + } else if (gpr.IsGPRMappedAsPointer(rs) || rs == rd) { return gpr.Normalize32(rs, tempReg); } else { return gpr.Normalize32(rs); diff --git a/Core/MIPS/RiscV/RiscVRegCache.cpp b/Core/MIPS/RiscV/RiscVRegCache.cpp index 913fdb8969..b836e1dd81 100644 --- a/Core/MIPS/RiscV/RiscVRegCache.cpp +++ b/Core/MIPS/RiscV/RiscVRegCache.cpp @@ -127,37 +127,6 @@ void RiscVRegCache::FlushBeforeCall() { } } -bool RiscVRegCache::IsInRAM(IRReg reg) { - _dbg_assert_(IsValidGPR(reg)); - return mr[reg].loc == MIPSLoc::MEM; -} - -bool RiscVRegCache::IsMapped(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - return mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM; -} - -bool RiscVRegCache::IsMappedAsPointer(IRReg mipsReg) { - _dbg_assert_(IsValidGPR(mipsReg)); - if (mr[mipsReg].loc == MIPSLoc::REG) { - return nr[mr[mipsReg].nReg].pointerified; - } else if (mr[mipsReg].loc == MIPSLoc::REG_IMM) { - if (nr[mr[mipsReg].nReg].pointerified) { - ERROR_LOG(JIT, "Really shouldn't be pointerified here"); - } - } else if (mr[mipsReg].loc == MIPSLoc::REG_AS_PTR) { - return true; - } - return false; -} - -bool RiscVRegCache::IsMappedAsStaticPointer(IRReg reg) { - if (IsMappedAsPointer(reg)) { - return mr[reg].isStatic; - } - return false; -} - bool RiscVRegCache::IsNormalized32(IRReg mipsReg) { _dbg_assert_(IsValidGPR(mipsReg)); if (XLEN == 32) @@ -321,7 +290,7 @@ void RiscVRegCache::MapRegTo(RiscVReg reg, IRReg mipsReg, MIPSMap mapFlags) { RiscVReg RiscVRegCache::TryMapTempImm(IRReg r) { _dbg_assert_(IsValidGPR(r)); // If already mapped, no need for a temporary. - if (IsMapped(r)) { + if (IsGPRMapped(r)) { return R(r); } @@ -513,44 +482,44 @@ void RiscVRegCache::MapIn(IRReg rs) { } void RiscVRegCache::MapInIn(IRReg rd, IRReg rs) { - SpillLock(rd, rs); + SpillLockGPR(rd, rs); MapReg(rd); MapReg(rs); - ReleaseSpillLock(rd, rs); + ReleaseSpillLockGPR(rd, rs); } void RiscVRegCache::MapDirtyIn(IRReg rd, IRReg rs, MapType type) { - SpillLock(rd, rs); + SpillLockGPR(rd, rs); bool load = type == MapType::ALWAYS_LOAD || rd == rs; MIPSMap norm32 = type == MapType::AVOID_LOAD_MARK_NORM32 ? MIPSMap::MARK_NORM32 : MIPSMap::INIT; MapReg(rd, (load ? MIPSMap::DIRTY : MIPSMap::NOINIT) | norm32); MapReg(rs); - ReleaseSpillLock(rd, rs); + ReleaseSpillLockGPR(rd, rs); } void RiscVRegCache::MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt, MapType type) { - SpillLock(rd, rs, rt); + SpillLockGPR(rd, rs, rt); bool load = type == MapType::ALWAYS_LOAD || (rd == rs || rd == rt); MIPSMap norm32 = type == MapType::AVOID_LOAD_MARK_NORM32 ? MIPSMap::MARK_NORM32 : MIPSMap::INIT; MapReg(rd, (load ? MIPSMap::DIRTY : MIPSMap::NOINIT) | norm32); MapReg(rt); MapReg(rs); - ReleaseSpillLock(rd, rs, rt); + ReleaseSpillLockGPR(rd, rs, rt); } void RiscVRegCache::MapDirtyDirtyIn(IRReg rd1, IRReg rd2, IRReg rs, MapType type) { - SpillLock(rd1, rd2, rs); + SpillLockGPR(rd1, rd2, rs); bool load1 = type == MapType::ALWAYS_LOAD || rd1 == rs; bool load2 = type == MapType::ALWAYS_LOAD || rd2 == rs; MIPSMap norm32 = type == MapType::AVOID_LOAD_MARK_NORM32 ? MIPSMap::MARK_NORM32 : MIPSMap::INIT; MapReg(rd1, (load1 ? MIPSMap::DIRTY : MIPSMap::NOINIT) | norm32); MapReg(rd2, (load2 ? MIPSMap::DIRTY : MIPSMap::NOINIT) | norm32); MapReg(rs); - ReleaseSpillLock(rd1, rd2, rs); + ReleaseSpillLockGPR(rd1, rd2, rs); } void RiscVRegCache::MapDirtyDirtyInIn(IRReg rd1, IRReg rd2, IRReg rs, IRReg rt, MapType type) { - SpillLock(rd1, rd2, rs, rt); + SpillLockGPR(rd1, rd2, rs, rt); bool load1 = type == MapType::ALWAYS_LOAD || (rd1 == rs || rd1 == rt); bool load2 = type == MapType::ALWAYS_LOAD || (rd2 == rs || rd2 == rt); MIPSMap norm32 = type == MapType::AVOID_LOAD_MARK_NORM32 ? MIPSMap::MARK_NORM32 : MIPSMap::INIT; @@ -558,7 +527,7 @@ void RiscVRegCache::MapDirtyDirtyInIn(IRReg rd1, IRReg rd2, IRReg rs, IRReg rt, MapReg(rd2, (load2 ? MIPSMap::DIRTY : MIPSMap::NOINIT) | norm32); MapReg(rt); MapReg(rs); - ReleaseSpillLock(rd1, rd2, rs, rt); + ReleaseSpillLockGPR(rd1, rd2, rs, rt); } void RiscVRegCache::AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) { @@ -579,9 +548,14 @@ void RiscVRegCache::StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) { _dbg_assert_(r > X0 && r <= X31); _dbg_assert_(first != MIPS_REG_ZERO); // Multilane not yet supported. - _assert_(lanes == 1); + _assert_(lanes == 1 || (lanes == 2 && first == IRREG_LO)); _assert_(mr[first].loc == MIPSLoc::REG || mr[first].loc == MIPSLoc::REG_IMM); - emit_->SW(r, CTXREG, GetMipsRegOffset(first)); + if (lanes == 1) + emit_->SW(r, CTXREG, GetMipsRegOffset(first)); + else if (lanes == 2) + emit_->SD(r, CTXREG, GetMipsRegOffset(first)); + else + _assert_(false); } void RiscVRegCache::DiscardR(IRReg mipsReg) { @@ -625,20 +599,7 @@ RiscVReg RiscVRegCache::RiscVRegForFlush(IRReg r) { case MIPSLoc::REG: case MIPSLoc::REG_IMM: - if (mr[r].nReg == INVALID_REG) { - ERROR_LOG_REPORT(JIT, "RiscVRegForFlush: MipsReg %d had bad riscvReg", r); - return INVALID_REG; - } - // No need to flush if it's zero or not dirty. - if (r == MIPS_REG_ZERO || !nr[mr[r].nReg].isDirty) { - return INVALID_REG; - } - // TODO: Lo/hi optimization? - return (RiscVReg)mr[r].nReg; - case MIPSLoc::REG_AS_PTR: - return INVALID_REG; - case MIPSLoc::MEM: return INVALID_REG; @@ -667,28 +628,21 @@ void RiscVRegCache::FlushR(IRReg r) { storeReg = SCRATCH1; } emit_->SW(storeReg, CTXREG, GetMipsRegOffset(r)); + mr[r].loc = MIPSLoc::MEM; + mr[r].nReg = (int)INVALID_REG; + mr[r].imm = -1; + } else { + mr[r].loc = MIPSLoc::REG_IMM; + mr[r].nReg = R_ZERO; + mr[r].imm = 0; } break; case MIPSLoc::REG: case MIPSLoc::REG_IMM: - if (nr[mr[r].nReg].isDirty) { - StoreNativeReg(mr[r].nReg, r, 1); - nr[mr[r].nReg].isDirty = false; - } - nr[mr[r].nReg].mipsReg = IRREG_INVALID; - nr[mr[r].nReg].pointerified = false; - break; - case MIPSLoc::REG_AS_PTR: - if (nr[mr[r].nReg].isDirty) { - AdjustNativeRegAsPtr(mr[r].nReg, false); - // We set this so StoreNativeReg knows it's no longer a pointer. - mr[r].loc = MIPSLoc::REG; - StoreNativeReg(mr[r].nReg, r, 1); - nr[mr[r].nReg].isDirty = false; - } - nr[mr[r].nReg].mipsReg = IRREG_INVALID; + // Might be in a native reg with multiple IR regs, flush together. + FlushNativeReg(mr[r].nReg); break; case MIPSLoc::MEM: @@ -699,15 +653,6 @@ void RiscVRegCache::FlushR(IRReg r) { ERROR_LOG_REPORT(JIT, "FlushR: MipsReg %d with invalid location %d", r, (int)mr[r].loc); break; } - if (r == MIPS_REG_ZERO) { - mr[r].loc = MIPSLoc::REG_IMM; - mr[r].nReg = R_ZERO; - mr[r].imm = 0; - } else { - mr[r].loc = MIPSLoc::MEM; - mr[r].nReg = (int)INVALID_REG; - mr[r].imm = -1; - } } void RiscVRegCache::FlushAll() { @@ -772,91 +717,11 @@ void RiscVRegCache::FlushAll() { } } -void RiscVRegCache::SetImm(IRReg r, u64 immVal) { - _dbg_assert_(IsValidGPR(r)); - if (r == MIPS_REG_ZERO && immVal != 0) { - ERROR_LOG_REPORT(JIT, "Trying to set immediate %08x to r0", (u32)immVal); - return; - } - - if (mr[r].loc == MIPSLoc::REG_IMM && mr[r].imm == immVal) { - // Already have that value, let's keep it in the reg. - return; - } - - // TODO: HI/LO optimization? - // All regs on the PSP are 32 bit, but LO we treat as HI:LO so is 64 full bits. - immVal = immVal & 0xFFFFFFFF; - - if (mr[r].isStatic) { - mr[r].loc = MIPSLoc::IMM; - mr[r].imm = immVal; - nr[mr[r].nReg].pointerified = false; - nr[mr[r].nReg].normalized32 = false; - // We do not change reg to INVALID_REG for obvious reasons.. - } else { - // Zap existing value if cached in a reg - if (mr[r].nReg != INVALID_REG) { - nr[mr[r].nReg].mipsReg = IRREG_INVALID; - nr[mr[r].nReg].isDirty = false; - nr[mr[r].nReg].pointerified = false; - nr[mr[r].nReg].normalized32 = false; - } - mr[r].loc = MIPSLoc::IMM; - mr[r].imm = immVal; - mr[r].nReg = (int)INVALID_REG; - } -} - -bool RiscVRegCache::IsImm(IRReg r) const { - _dbg_assert_(IsValidGPR(r)); - if (r == MIPS_REG_ZERO) - return true; - else - return mr[r].loc == MIPSLoc::IMM || mr[r].loc == MIPSLoc::REG_IMM; -} - -u64 RiscVRegCache::GetImm(IRReg r) const { - _dbg_assert_(IsValidGPR(r)); - if (r == MIPS_REG_ZERO) - return 0; - if (mr[r].loc != MIPSLoc::IMM && mr[r].loc != MIPSLoc::REG_IMM) { - ERROR_LOG_REPORT(JIT, "Trying to get imm from non-imm register %i", r); - } - return mr[r].imm; -} - int RiscVRegCache::GetMipsRegOffset(IRReg r) { _dbg_assert_(IsValidGPR(r)); return r * 4; } -void RiscVRegCache::SpillLock(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidGPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); - mr[r1].spillLockIRIndex = irIndex_; - if (r2 != IRREG_INVALID) mr[r2].spillLockIRIndex = irIndex_; - if (r3 != IRREG_INVALID) mr[r3].spillLockIRIndex = irIndex_; - if (r4 != IRREG_INVALID) mr[r4].spillLockIRIndex = irIndex_; -} - -void RiscVRegCache::ReleaseSpillLock(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidGPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidGPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidGPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidGPR(r4)); - if (!mr[r1].isStatic) - mr[r1].spillLockIRIndex = -1; - if (r2 != IRREG_INVALID && !mr[r2].isStatic) - mr[r2].spillLockIRIndex = -1; - if (r3 != IRREG_INVALID && !mr[r3].isStatic) - mr[r3].spillLockIRIndex = -1; - if (r4 != IRREG_INVALID && !mr[r4].isStatic) - mr[r4].spillLockIRIndex = -1; -} - RiscVReg RiscVRegCache::R(IRReg mipsReg) { _dbg_assert_(IsValidGPR(mipsReg)); _dbg_assert_(mr[mipsReg].loc == MIPSLoc::REG || mr[mipsReg].loc == MIPSLoc::REG_IMM); diff --git a/Core/MIPS/RiscV/RiscVRegCache.h b/Core/MIPS/RiscV/RiscVRegCache.h index 8fd24bc4db..28618e040d 100644 --- a/Core/MIPS/RiscV/RiscVRegCache.h +++ b/Core/MIPS/RiscV/RiscVRegCache.h @@ -63,15 +63,6 @@ public: void Init(RiscVGen::RiscVEmitter *emitter); - // Protect the arm register containing a MIPS register from spilling, to ensure that - // it's being kept allocated. - void SpillLock(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - void ReleaseSpillLock(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - - void SetImm(IRReg reg, u64 immVal); - bool IsImm(IRReg reg) const; - u64 GetImm(IRReg reg) const; - // May fail and return INVALID_REG if it needs flushing. RiscVGen::RiscVReg TryMapTempImm(IRReg); @@ -79,10 +70,6 @@ public: RiscVGen::RiscVReg MapReg(IRReg reg, RiscVJitConstants::MIPSMap mapFlags = RiscVJitConstants::MIPSMap::INIT); RiscVGen::RiscVReg MapRegAsPointer(IRReg reg); - bool IsMapped(IRReg reg); - bool IsMappedAsPointer(IRReg reg); - bool IsMappedAsStaticPointer(IRReg reg); - bool IsInRAM(IRReg reg); bool IsNormalized32(IRReg reg); void MarkDirty(RiscVGen::RiscVReg reg, bool andNormalized32 = false); diff --git a/Core/MIPS/RiscV/RiscVRegCacheFPU.cpp b/Core/MIPS/RiscV/RiscVRegCacheFPU.cpp index c33a4f22d5..48653f9fcf 100644 --- a/Core/MIPS/RiscV/RiscVRegCacheFPU.cpp +++ b/Core/MIPS/RiscV/RiscVRegCacheFPU.cpp @@ -53,16 +53,6 @@ const int *RiscVRegCacheFPU::GetAllocationOrder(MIPSLoc type, int &count, int &b return allocationOrder; } -bool RiscVRegCacheFPU::IsInRAM(IRReg reg) { - _dbg_assert_(IsValidFPR(reg)); - return mr[reg + 32].loc == MIPSLoc::MEM; -} - -bool RiscVRegCacheFPU::IsMapped(IRReg mipsReg) { - _dbg_assert_(IsValidFPR(mipsReg)); - return mr[mipsReg + 32].loc == MIPSLoc::FREG; -} - RiscVReg RiscVRegCacheFPU::MapReg(IRReg mipsReg, MIPSMap mapFlags) { _dbg_assert_(IsValidFPR(mipsReg)); _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::MEM || mr[mipsReg + 32].loc == MIPSLoc::FREG); @@ -100,54 +90,54 @@ RiscVReg RiscVRegCacheFPU::MapReg(IRReg mipsReg, MIPSMap mapFlags) { } void RiscVRegCacheFPU::MapInIn(IRReg rd, IRReg rs) { - SpillLock(rd, rs); + SpillLockFPR(rd, rs); MapReg(rd); MapReg(rs); - ReleaseSpillLock(rd, rs); + ReleaseSpillLockFPR(rd, rs); } void RiscVRegCacheFPU::MapDirtyIn(IRReg rd, IRReg rs, bool avoidLoad) { - SpillLock(rd, rs); + SpillLockFPR(rd, rs); bool load = !avoidLoad || rd == rs; MapReg(rd, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); MapReg(rs); - ReleaseSpillLock(rd, rs); + ReleaseSpillLockFPR(rd, rs); } void RiscVRegCacheFPU::MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt, bool avoidLoad) { - SpillLock(rd, rs, rt); + SpillLockFPR(rd, rs, rt); bool load = !avoidLoad || (rd == rs || rd == rt); MapReg(rd, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); MapReg(rt); MapReg(rs); - ReleaseSpillLock(rd, rs, rt); + ReleaseSpillLockFPR(rd, rs, rt); } RiscVReg RiscVRegCacheFPU::MapDirtyInTemp(IRReg rd, IRReg rs, bool avoidLoad) { - SpillLock(rd, rs); + SpillLockFPR(rd, rs); bool load = !avoidLoad || rd == rs; MapReg(rd, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); MapReg(rs); RiscVReg temp = (RiscVReg)(F0 + AllocateReg(MIPSLoc::FREG)); - ReleaseSpillLock(rd, rs); + ReleaseSpillLockFPR(rd, rs); return temp; } void RiscVRegCacheFPU::Map4DirtyIn(IRReg rdbase, IRReg rsbase, bool avoidLoad) { for (int i = 0; i < 4; ++i) - SpillLock(rdbase + i, rsbase + i); + SpillLockFPR(rdbase + i, rsbase + i); bool load = !avoidLoad || (rdbase < rsbase + 4 && rdbase + 4 > rsbase); for (int i = 0; i < 4; ++i) MapReg(rdbase + i, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); for (int i = 0; i < 4; ++i) MapReg(rsbase + i); for (int i = 0; i < 4; ++i) - ReleaseSpillLock(rdbase + i, rsbase + i); + ReleaseSpillLockFPR(rdbase + i, rsbase + i); } void RiscVRegCacheFPU::Map4DirtyInIn(IRReg rdbase, IRReg rsbase, IRReg rtbase, bool avoidLoad) { for (int i = 0; i < 4; ++i) - SpillLock(rdbase + i, rsbase + i, rtbase + i); + SpillLockFPR(rdbase + i, rsbase + i, rtbase + i); bool load = !avoidLoad || (rdbase < rsbase + 4 && rdbase + 4 > rsbase) || (rdbase < rtbase + 4 && rdbase + 4 > rtbase); for (int i = 0; i < 4; ++i) MapReg(rdbase + i, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); @@ -156,12 +146,12 @@ void RiscVRegCacheFPU::Map4DirtyInIn(IRReg rdbase, IRReg rsbase, IRReg rtbase, b for (int i = 0; i < 4; ++i) MapReg(rtbase + i); for (int i = 0; i < 4; ++i) - ReleaseSpillLock(rdbase + i, rsbase + i, rtbase + i); + ReleaseSpillLockFPR(rdbase + i, rsbase + i, rtbase + i); } RiscVReg RiscVRegCacheFPU::Map4DirtyInTemp(IRReg rdbase, IRReg rsbase, bool avoidLoad) { for (int i = 0; i < 4; ++i) - SpillLock(rdbase + i, rsbase + i); + SpillLockFPR(rdbase + i, rsbase + i); bool load = !avoidLoad || (rdbase < rsbase + 4 && rdbase + 4 > rsbase); for (int i = 0; i < 4; ++i) MapReg(rdbase + i, load ? MIPSMap::DIRTY : MIPSMap::NOINIT); @@ -169,7 +159,7 @@ RiscVReg RiscVRegCacheFPU::Map4DirtyInTemp(IRReg rdbase, IRReg rsbase, bool avoi MapReg(rsbase + i); RiscVReg temp = (RiscVReg)(F0 + AllocateReg(MIPSLoc::FREG)); for (int i = 0; i < 4; ++i) - ReleaseSpillLock(rdbase + i, rsbase + i); + ReleaseSpillLockFPR(rdbase + i, rsbase + i); return temp; } @@ -186,28 +176,20 @@ void RiscVRegCacheFPU::StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) } void RiscVRegCacheFPU::FlushR(IRReg r) { - _dbg_assert_(IsValidFPR(r)); - RiscVReg reg = RiscVRegForFlush(r); - if (reg != INVALID_REG) - FlushNativeReg((IRNativeReg)(reg - F0)); -} - -RiscVReg RiscVRegCacheFPU::RiscVRegForFlush(IRReg r) { _dbg_assert_(IsValidFPR(r)); switch (mr[r + 32].loc) { case MIPSLoc::FREG: - _assert_msg_(mr[r + 32].nReg != INVALID_REG, "RiscVRegForFlush: IR %d had bad RiscVReg", r + 32); - if (mr[r + 32].nReg == INVALID_REG) { - return INVALID_REG; - } - return (RiscVReg)(F0 + mr[r + 32].nReg); + case MIPSLoc::VREG: + _assert_msg_(mr[r + 32].nReg != INVALID_REG, "FlushR: IR %d had bad RiscVReg", r + 32); + FlushNativeReg(mr[r + 32].nReg); + break; case MIPSLoc::MEM: - return INVALID_REG; + break; default: - _assert_(false); - return INVALID_REG; + _assert_msg_(false, "Unexpected register location %d", (int)mr[r + 32].loc); + break; } } @@ -279,8 +261,6 @@ void RiscVRegCacheFPU::DiscardR(IRReg r) { _assert_(false); break; } - mr[r + 32].loc = MIPSLoc::MEM; - mr[r + 32].nReg = -1; mr[r + 32].spillLockIRIndex = -1; } @@ -291,34 +271,6 @@ int RiscVRegCacheFPU::GetMipsRegOffset(IRReg r) { return (r) * 4; } -void RiscVRegCacheFPU::SpillLock(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidFPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); - mr[r1 + 32].spillLockIRIndex = irIndex_; - if (r2 != IRREG_INVALID) - mr[r2 + 32].spillLockIRIndex = irIndex_; - if (r3 != IRREG_INVALID) - mr[r3 + 32].spillLockIRIndex = irIndex_; - if (r4 != IRREG_INVALID) - mr[r4 + 32].spillLockIRIndex = irIndex_; -} - -void RiscVRegCacheFPU::ReleaseSpillLock(IRReg r1, IRReg r2, IRReg r3, IRReg r4) { - _dbg_assert_(IsValidFPR(r1)); - _dbg_assert_(r2 == IRREG_INVALID || IsValidFPR(r2)); - _dbg_assert_(r3 == IRREG_INVALID || IsValidFPR(r3)); - _dbg_assert_(r4 == IRREG_INVALID || IsValidFPR(r4)); - mr[r1 + 32].spillLockIRIndex = -1; - if (r2 != IRREG_INVALID) - mr[r2 + 32].spillLockIRIndex = -1; - if (r3 != IRREG_INVALID) - mr[r3 + 32].spillLockIRIndex = -1; - if (r4 != IRREG_INVALID) - mr[r4 + 32].spillLockIRIndex = -1; -} - RiscVReg RiscVRegCacheFPU::R(IRReg mipsReg) { _dbg_assert_(IsValidFPR(mipsReg)); _dbg_assert_(mr[mipsReg + 32].loc == MIPSLoc::FREG); diff --git a/Core/MIPS/RiscV/RiscVRegCacheFPU.h b/Core/MIPS/RiscV/RiscVRegCacheFPU.h index 3103101f94..1c0b18ccfd 100644 --- a/Core/MIPS/RiscV/RiscVRegCacheFPU.h +++ b/Core/MIPS/RiscV/RiscVRegCacheFPU.h @@ -31,17 +31,9 @@ public: void Init(RiscVGen::RiscVEmitter *emitter); - // Protect the RISC-V register containing a MIPS register from spilling, to ensure that - // it's being kept allocated. - void SpillLock(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - void ReleaseSpillLock(IRReg reg, IRReg reg2 = IRREG_INVALID, IRReg reg3 = IRREG_INVALID, IRReg reg4 = IRREG_INVALID); - // Returns a RISC-V register containing the requested MIPS register. RiscVGen::RiscVReg MapReg(IRReg reg, RiscVJitConstants::MIPSMap mapFlags = RiscVJitConstants::MIPSMap::INIT); - bool IsMapped(IRReg r); - bool IsInRAM(IRReg r); - void MapInIn(IRReg rd, IRReg rs); void MapDirtyIn(IRReg rd, IRReg rs, bool avoidLoad = true); void MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt, bool avoidLoad = true); @@ -62,7 +54,6 @@ protected: void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override; private: - RiscVGen::RiscVReg RiscVRegForFlush(IRReg r); int GetMipsRegOffset(IRReg r); RiscVGen::RiscVEmitter *emit_ = nullptr;