diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 0029da5287..5c986bdf81 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -2148,6 +2148,7 @@ void RiscVEmitter::FCVT(FConv to, FConv from, RiscVReg rd, RiscVReg rs1, Round r _assert_msg_(rm == Round::DYNAMIC || rm == Round::NEAREST_EVEN, "Invalid rounding mode for widening FCVT"); rm = Round::NEAREST_EVEN; } + _assert_msg_(fromFmt != toFmt, "FCVT cannot convert to same float type"); Write32(EncodeR(Opcode32::OP_FP, rd, (Funct3)rm, rs1, (RiscVReg)fromFmt, toFmt, Funct5::FCVT_SZ)); } else { Funct5 funct5 = FConvToIntegerBits(to) == 0 ? Funct5::FCVT_FROMX : Funct5::FCVT_TOX; diff --git a/Core/MIPS/IR/IRInst.h b/Core/MIPS/IR/IRInst.h index 5a2a2e25a1..795dc75233 100644 --- a/Core/MIPS/IR/IRInst.h +++ b/Core/MIPS/IR/IRInst.h @@ -315,6 +315,7 @@ enum : IRReg { IRREG_HI = 243, IRREG_FCR31 = 244, IRREG_FPCOND = 245, + IRREG_LLBIT = 250, }; enum IRFlags { diff --git a/Core/MIPS/RiscV/RiscVCompFPU.cpp b/Core/MIPS/RiscV/RiscVCompFPU.cpp index c534e35533..ead8244712 100644 --- a/Core/MIPS/RiscV/RiscVCompFPU.cpp +++ b/Core/MIPS/RiscV/RiscVCompFPU.cpp @@ -221,18 +221,32 @@ void RiscVJit::CompIR_FAssign(IRInst inst) { void RiscVJit::CompIR_FRound(IRInst inst) { CONDITIONAL_DISABLE; + // TODO: If this is followed by a GPR transfer, might want to combine. + fpr.MapDirtyIn(inst.dest, inst.src1); + switch (inst.op) { case IROp::FRound: + FCVT(FConv::W, FConv::S, SCRATCH1, fpr.R(inst.src1), Round::NEAREST_EVEN); + break; + case IROp::FTrunc: + FCVT(FConv::W, FConv::S, SCRATCH1, fpr.R(inst.src1), Round::TOZERO); + break; + case IROp::FCeil: + FCVT(FConv::W, FConv::S, SCRATCH1, fpr.R(inst.src1), Round::UP); + break; + case IROp::FFloor: - CompIR_Generic(inst); + FCVT(FConv::W, FConv::S, SCRATCH1, fpr.R(inst.src1), Round::DOWN); break; default: INVALIDOP; break; } + + FMV(FMv::W, FMv::X, fpr.R(inst.dest), SCRATCH1); } void RiscVJit::CompIR_FCvt(IRInst inst) { @@ -241,11 +255,17 @@ void RiscVJit::CompIR_FCvt(IRInst inst) { switch (inst.op) { case IROp::FCvtWS: case IROp::FCvtScaledWS: - case IROp::FCvtSW: case IROp::FCvtScaledSW: CompIR_Generic(inst); break; + case IROp::FCvtSW: + // TODO: This is probably proceeded by a GPR transfer, might be ideal to combine. + fpr.MapDirtyIn(inst.dest, inst.src1); + FMV(FMv::X, FMv::W, SCRATCH1, fpr.R(inst.src1)); + FCVT(FConv::S, FConv::W, fpr.R(inst.dest), SCRATCH1); + break; + default: INVALIDOP; break; diff --git a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp index 8cc8af74de..d6a49e6f13 100644 --- a/Core/MIPS/RiscV/RiscVCompLoadStore.cpp +++ b/Core/MIPS/RiscV/RiscVCompLoadStore.cpp @@ -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) { diff --git a/Core/MIPS/RiscV/RiscVRegCache.cpp b/Core/MIPS/RiscV/RiscVRegCache.cpp index 639c11843a..25f7b5db59 100644 --- a/Core/MIPS/RiscV/RiscVRegCache.cpp +++ b/Core/MIPS/RiscV/RiscVRegCache.cpp @@ -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)