diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index c16521b240..c9f6d60919 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -118,6 +118,7 @@ public: void crXXX(UGeckoInstruction inst); void mfcr(UGeckoInstruction inst); void mtcrf(UGeckoInstruction inst); + void mcrfs(UGeckoInstruction inst); // LoadStore void lXX(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 33cf6d51b7..668e7fce26 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -687,3 +687,37 @@ void JitArm64::mtcrf(UGeckoInstruction inst) gpr.Unlock(WB); } } + +void JitArm64::mcrfs(UGeckoInstruction inst) +{ + INSTRUCTION_START + JITDISABLE(bJITSystemRegistersOff); + + u8 shift = 4 * (7 - inst.CRFS); + u32 mask = 0xF << shift; + u32 field = inst.CRFD; + + // Only clear exception bits (but not FEX/VX). + mask &= FPSCR_FX | FPSCR_ANY_X; + + gpr.BindCRToRegister(field, false); + ARM64Reg CR = gpr.CR(field); + ARM64Reg WA = gpr.GetReg(); + ARM64Reg WCR = EncodeRegTo32(CR); + ARM64Reg XA = EncodeRegTo64(WA); + + LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + LSR(WCR, WA, shift); + ANDI2R(WCR, WCR, 0xF); + + if (mask != 0) + { + ANDI2R(WA, WA, ~mask); + STR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(fpscr)); + } + + MOVP2R(XA, PowerPC::ConditionRegister::s_crTable.data()); + LDR(CR, XA, ArithOption(CR, true)); + + gpr.Unlock(WA); +} diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index 471a4566c8..a3b5cce8c9 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -315,7 +315,7 @@ constexpr std::array table63{{ {40, &JitArm64::fp_logic}, // fnegx {12, &JitArm64::frspx}, // frspx - {64, &JitArm64::FallBackToInterpreter}, // mcrfs + {64, &JitArm64::mcrfs}, // mcrfs {583, &JitArm64::FallBackToInterpreter}, // mffsx {70, &JitArm64::FallBackToInterpreter}, // mtfsb0x {38, &JitArm64::FallBackToInterpreter}, // mtfsb1x