riscv: Implement ll/sc.

This commit is contained in:
Unknown W. Brackets 2023-07-29 17:53:15 -07:00
parent 26a527bdf8
commit c24e3ef831
3 changed files with 41 additions and 3 deletions

View File

@ -315,6 +315,7 @@ enum : IRReg {
IRREG_HI = 243,
IRREG_FCR31 = 244,
IRREG_FPCOND = 245,
IRREG_LLBIT = 250,
};
enum IRFlags {

View File

@ -113,7 +113,9 @@ void RiscVJit::CompIR_Load(IRInst inst) {
break;
case IROp::Load32Linked:
CompIR_Generic(inst);
if (inst.dest != MIPS_REG_ZERO)
LW(gpr.R(inst.dest), addrReg, imm);
gpr.SetImm(IRREG_LLBIT, 1);
break;
default:
@ -258,7 +260,41 @@ void RiscVJit::CompIR_CondStore(IRInst inst) {
if (inst.op != IROp::Store32Conditional)
INVALIDOP;
CompIR_Generic(inst);
gpr.SpillLock(IRREG_LLBIT, inst.src3, inst.src1);
RiscVReg addrReg = INVALID_REG;
if (inst.src1 == MIPS_REG_ZERO) {
// This will get changed by AdjustForAddressOffset.
addrReg = MEMBASEREG;
#ifdef MASKED_PSP_MEMORY
inst.constant &= Memory::MEMVIEW32_MASK;
#endif
} else if ((jo.cachePointers || gpr.IsMappedAsPointer(inst.src1)) && inst.src3 != inst.src1) {
addrReg = gpr.MapRegAsPointer(inst.src1);
} else {
SetScratch1ToSrc1Address(inst.src1);
addrReg = SCRATCH1;
}
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);
// TODO: Safe memory? Or enough to have crash handler + validate?
FixupBranch condFailed = BEQ(gpr.R(IRREG_LLBIT), R_ZERO);
SW(gpr.R(inst.src3), addrReg, imm);
if (inst.dest != MIPS_REG_ZERO) {
LI(gpr.R(inst.dest), 1);
FixupBranch finish = J();
SetJumpTarget(condFailed);
LI(gpr.R(inst.dest), 0);
SetJumpTarget(finish);
} else {
SetJumpTarget(condFailed);
}
}
void RiscVJit::CompIR_StoreShift(IRInst inst) {

View File

@ -20,6 +20,7 @@
#endif
#include "Common/CPUDetect.h"
#include "Core/MIPS/IR/IRInst.h"
#include "Core/MIPS/RiscV/RiscVRegCache.h"
#include "Core/MIPS/JitCommon/JitState.h"
#include "Core/Reporting.h"
@ -998,7 +999,7 @@ bool RiscVRegCache::IsValidReg(IRRegIndex r) const {
if (r >= 224 && r < 224 + 16)
return false;
// Don't allow nextPC, etc. since it's probably a mistake.
if (r > 245)
if (r > IRREG_FPCOND && r != IRREG_LLBIT)
return false;
// Don't allow PC either.
if (r == 241)