diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index 5723142a24..116908c656 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -115,9 +115,6 @@ static const IRMeta irMeta[] = { { IROp::FpCtrlFromReg, "FpCtrlFromReg", "_G" }, { IROp::FpCtrlToReg, "FpCtrlToReg", "G" }, { IROp::VfpuCtrlToReg, "VfpuCtrlToReg", "GI" }, - { IROp::RestoreRoundingMode, "RestoreRoundingMode", "" }, - { IROp::ApplyRoundingMode, "ApplyRoundingMode", "" }, - { IROp::UpdateRoundingMode, "UpdateRoundingMode", "" }, { IROp::SetCtrlVFPU, "SetCtrlVFPU", "TC" }, { IROp::SetCtrlVFPUReg, "SetCtrlVFPUReg", "TG" }, { IROp::SetCtrlVFPUFReg, "SetCtrlVFPUFReg", "TF" }, diff --git a/Core/MIPS/IR/IRPassSimplify.cpp b/Core/MIPS/IR/IRPassSimplify.cpp index a6c3b9b7f1..52ea66c5d4 100644 --- a/Core/MIPS/IR/IRPassSimplify.cpp +++ b/Core/MIPS/IR/IRPassSimplify.cpp @@ -695,10 +695,11 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts } break; case IROp::FpCtrlFromReg: - gpr.MapIn(inst.src1); + gpr.MapDirtyIn(IRREG_FCR31, inst.src1); + gpr.MapDirty(IRREG_FPCOND); goto doDefault; case IROp::FpCtrlToReg: - gpr.MapDirty(inst.dest); + gpr.MapDirtyInIn(inst.dest, IRREG_FPCOND, IRREG_FCR31); goto doDefault; case IROp::Vec4Init: diff --git a/Core/MIPS/RiscV/RiscVCompSystem.cpp b/Core/MIPS/RiscV/RiscVCompSystem.cpp index 8a8b995f5f..44dee67236 100644 --- a/Core/MIPS/RiscV/RiscVCompSystem.cpp +++ b/Core/MIPS/RiscV/RiscVCompSystem.cpp @@ -115,6 +115,40 @@ void RiscVJit::CompIR_Transfer(IRInst inst) { gpr.SetImm(IRREG_FPCOND, 0); break; + case IROp::FpCtrlFromReg: + gpr.MapDirtyIn(IRREG_FPCOND, inst.src1, MapType::AVOID_LOAD_MARK_NORM32); + LI(SCRATCH1, 0x0181FFFF); + AND(SCRATCH1, gpr.R(inst.src1), SCRATCH1); + // Extract the new fpcond value. + if (cpu_info.RiscV_Zbs) { + BEXTI(gpr.R(IRREG_FPCOND), SCRATCH1, 23); + } else { + SRLI(gpr.R(IRREG_FPCOND), SCRATCH1, 23); + ANDI(gpr.R(IRREG_FPCOND), gpr.R(IRREG_FPCOND), 1); + } + SW(SCRATCH1, CTXREG, IRREG_FCR31 * 4); + break; + + case IROp::FpCtrlToReg: + gpr.MapDirtyIn(inst.dest, IRREG_FPCOND, MapType::AVOID_LOAD_MARK_NORM32); + // Load fcr31 and clear the fpcond bit. + LW(SCRATCH1, CTXREG, IRREG_FCR31 * 4); + if (cpu_info.RiscV_Zbs) { + BCLRI(SCRATCH1, SCRATCH1, 23); + } else { + LI(SCRATCH2, ~(1 << 23)); + AND(SCRATCH1, SCRATCH1, SCRATCH2); + } + + // Now get the correct fpcond bit. + ANDI(SCRATCH2, gpr.R(IRREG_FPCOND), 1); + SLLI(SCRATCH2, SCRATCH2, 23); + OR(gpr.R(inst.dest), SCRATCH1, SCRATCH2); + + // Also update mips->fcr31 while we're here. + SW(gpr.R(inst.dest), CTXREG, IRREG_FCR31 * 4); + break; + 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)); diff --git a/Core/MIPS/RiscV/RiscVJit.cpp b/Core/MIPS/RiscV/RiscVJit.cpp index b38aeb5124..720fd23d5f 100644 --- a/Core/MIPS/RiscV/RiscVJit.cpp +++ b/Core/MIPS/RiscV/RiscVJit.cpp @@ -291,6 +291,8 @@ void RiscVJit::CompileIRInst(IRInst inst) { case IROp::SetCtrlVFPUFReg: case IROp::FpCondToReg: case IROp::ZeroFpCond: + case IROp::FpCtrlFromReg: + case IROp::FpCtrlToReg: case IROp::VfpuCtrlToReg: case IROp::FMovFromGPR: case IROp::FMovToGPR: