riscv: Centralize IR reg cache metadata checks.

These are all largely the same between backends.
This commit is contained in:
Unknown W. Brackets committed 2023-08-17 23:03:31 -07:00
1 parent ebab0e1591
commit 4e41f83ecc
12 files changed
+268 -309

No files matched your search

+158 -2
View File
@@ -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;
+24 -1
View File
@@ -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;
+9 -13
View File
@@ -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.
+2 -2
View File
@@ -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;
+11 -14
View File
@@ -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);
+3 -3
View File
@@ -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);
+11 -19
View File
@@ -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);
+2 -2
View File
@@ -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);
+27 -162
View File
@@ -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);
-13
View File
@@ -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);
+21 -69
View File
@@ -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);
-9
View File
@@ -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;