diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index 75f047129d..bace9b7971 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -621,6 +621,7 @@ void SConfig::LoadDefaults() bJITIntegerOff = false; bJITPairedOff = false; bJITSystemRegistersOff = false; + bJITBranchOff = false; m_strName = "NONE"; m_strUniqueID = "00000000"; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index b968aeacf9..a658252043 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -51,10 +51,45 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst) { gpr.Flush(FlushMode::FLUSH_INTERPRETER, js.op); fpr.Flush(FlushMode::FLUSH_INTERPRETER, js.op); + + if (js.op->opinfo->flags & FL_ENDBLOCK) + { + // also flush the program counter + ARM64Reg WA = gpr.GetReg(); + MOVI2R(WA, js.compilerPC); + STR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(pc)); + ADD(WA, WA, 4); + STR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(npc)); + gpr.Unlock(WA); + } + Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst); MOVI2R(W0, inst.hex); MOVI2R(X30, (u64)instr); BLR(X30); + + if (js.op->opinfo->flags & FL_ENDBLOCK) + { + if (js.isLastInstruction) + { + ARM64Reg WA = gpr.GetReg(); + LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(npc)); + WriteExceptionExit(WA); + } + else + { + // only exit if ppcstate.npc was changed + ARM64Reg WA = gpr.GetReg(); + LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(npc)); + ARM64Reg WB = gpr.GetReg(); + MOVI2R(WB, js.compilerPC + 4); + CMP(WB, WA); + gpr.Unlock(WB); + FixupBranch c = B(CC_EQ); + WriteExceptionExit(WA); + SetJumpTarget(c); + } + } } void JitArm64::HLEFunction(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index aa9f43add3..6b2d0c3fe8 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -114,7 +114,6 @@ public: void mtspr(UGeckoInstruction inst); // LoadStore - void icbi(UGeckoInstruction inst); void lXX(UGeckoInstruction inst); void stX(UGeckoInstruction inst); void lmw(UGeckoInstruction inst); diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp index 8efd81e0f1..4dfd88b92e 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Branch.cpp @@ -18,6 +18,7 @@ using namespace Arm64Gen; void JitArm64::sc(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); gpr.Flush(FlushMode::FLUSH_ALL); fpr.Flush(FlushMode::FLUSH_ALL); @@ -38,6 +39,7 @@ void JitArm64::sc(UGeckoInstruction inst) void JitArm64::rfi(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); gpr.Flush(FlushMode::FLUSH_ALL); fpr.Flush(FlushMode::FLUSH_ALL); @@ -78,6 +80,7 @@ void JitArm64::rfi(UGeckoInstruction inst) void JitArm64::bx(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); gpr.Flush(FlushMode::FLUSH_ALL); fpr.Flush(FlushMode::FLUSH_ALL); @@ -115,6 +118,7 @@ void JitArm64::bx(UGeckoInstruction inst) void JitArm64::bcx(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); ARM64Reg WA = gpr.GetReg(); FixupBranch pCTRDontBranch; @@ -173,45 +177,42 @@ void JitArm64::bcx(UGeckoInstruction inst) void JitArm64::bcctrx(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); + + // Rare condition seen in (just some versions of?) Nintendo's NES Emulator + // BO_2 == 001zy -> b if false + // BO_2 == 011zy -> b if true + FALLBACK_IF(!(inst.BO_2 & BO_DONT_CHECK_CONDITION)); // bcctrx doesn't decrement and/or test CTR _assert_msg_(DYNA_REC, inst.BO_2 & BO_DONT_DECREMENT_FLAG, "bcctrx with decrement and test CTR option is invalid!"); - if (inst.BO_2 & BO_DONT_CHECK_CONDITION) + // BO_2 == 1z1zz -> b always + + //NPC = CTR & 0xfffffffc; + gpr.Flush(FlushMode::FLUSH_ALL); + fpr.Flush(FlushMode::FLUSH_ALL); + + if (inst.LK_3) { - // BO_2 == 1z1zz -> b always - - //NPC = CTR & 0xfffffffc; - gpr.Flush(FlushMode::FLUSH_ALL); - fpr.Flush(FlushMode::FLUSH_ALL); - - if (inst.LK_3) - { - ARM64Reg WB = gpr.GetReg(); - u32 Jumpto = js.compilerPC + 4; - MOVI2R(WB, Jumpto); - STR(INDEX_UNSIGNED, WB, X29, PPCSTATE_OFF(spr[SPR_LR])); - gpr.Unlock(WB); - } - - ARM64Reg WA = gpr.GetReg(); - - LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(spr[SPR_CTR])); - AND(WA, WA, 30, 29); // Wipe the bottom 2 bits. - WriteExitDestInR(WA); - } - else - { - // Rare condition seen in (just some versions of?) Nintendo's NES Emulator - // BO_2 == 001zy -> b if false - // BO_2 == 011zy -> b if true - _assert_msg_(DYNA_REC, false, "Haven't implemented rare form of bcctrx yet"); + ARM64Reg WB = gpr.GetReg(); + u32 Jumpto = js.compilerPC + 4; + MOVI2R(WB, Jumpto); + STR(INDEX_UNSIGNED, WB, X29, PPCSTATE_OFF(spr[SPR_LR])); + gpr.Unlock(WB); } + + ARM64Reg WA = gpr.GetReg(); + + LDR(INDEX_UNSIGNED, WA, X29, PPCSTATE_OFF(spr[SPR_CTR])); + AND(WA, WA, 30, 29); // Wipe the bottom 2 bits. + WriteExitDestInR(WA); } void JitArm64::bclrx(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITBranchOff); ARM64Reg WA = gpr.GetReg(); FixupBranch pCTRDontBranch; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp index 9739fb35c1..19433dcda0 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_LoadStore.cpp @@ -18,15 +18,6 @@ using namespace Arm64Gen; -void JitArm64::icbi(UGeckoInstruction inst) -{ - gpr.Flush(FlushMode::FLUSH_ALL); - fpr.Flush(FlushMode::FLUSH_ALL); - - FallBackToInterpreter(inst); - WriteExit(js.compilerPC + 4); -} - void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 offset, bool update) { // We want to make sure to not get LR as a temp register diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index 72e42c1769..212c12fa8c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -48,8 +48,7 @@ FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set) void JitArm64::mtmsr(UGeckoInstruction inst) { INSTRUCTION_START - // Don't interpret this, if we do we get thrown out - //JITDISABLE(bJITSystemRegistersOff) + JITDISABLE(bJITSystemRegistersOff); gpr.BindToRegister(inst.RS, true); STR(INDEX_UNSIGNED, gpr.R(inst.RS), X29, PPCSTATE_OFF(msr)); @@ -143,6 +142,7 @@ void JitArm64::mtsrin(UGeckoInstruction inst) void JitArm64::twx(UGeckoInstruction inst) { INSTRUCTION_START + JITDISABLE(bJITSystemRegistersOff); s32 a = inst.RA; diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp index fe3bb519a4..7bf211bdc5 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_Tables.cpp @@ -302,7 +302,7 @@ static GekkoOPTemplate table31[] = {4, &JitArm64::twx}, // tw {598, &JitArm64::DoNothing}, // sync - {982, &JitArm64::icbi}, // icbi + {982, &JitArm64::FallBackToInterpreter}, // icbi // Unused instructions on GC {310, &JitArm64::FallBackToInterpreter}, // eciwx