Merge pull request #2671 from degasus/jitarmbranch
JitArm64: branching fallbacks
This commit is contained in:
commit
e9921044b5
|
@ -621,6 +621,7 @@ void SConfig::LoadDefaults()
|
||||||
bJITIntegerOff = false;
|
bJITIntegerOff = false;
|
||||||
bJITPairedOff = false;
|
bJITPairedOff = false;
|
||||||
bJITSystemRegistersOff = false;
|
bJITSystemRegistersOff = false;
|
||||||
|
bJITBranchOff = false;
|
||||||
|
|
||||||
m_strName = "NONE";
|
m_strName = "NONE";
|
||||||
m_strUniqueID = "00000000";
|
m_strUniqueID = "00000000";
|
||||||
|
|
|
@ -51,10 +51,45 @@ void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
gpr.Flush(FlushMode::FLUSH_INTERPRETER, js.op);
|
gpr.Flush(FlushMode::FLUSH_INTERPRETER, js.op);
|
||||||
fpr.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);
|
Interpreter::_interpreterInstruction instr = GetInterpreterOp(inst);
|
||||||
MOVI2R(W0, inst.hex);
|
MOVI2R(W0, inst.hex);
|
||||||
MOVI2R(X30, (u64)instr);
|
MOVI2R(X30, (u64)instr);
|
||||||
BLR(X30);
|
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)
|
void JitArm64::HLEFunction(UGeckoInstruction inst)
|
||||||
|
|
|
@ -114,7 +114,6 @@ public:
|
||||||
void mtspr(UGeckoInstruction inst);
|
void mtspr(UGeckoInstruction inst);
|
||||||
|
|
||||||
// LoadStore
|
// LoadStore
|
||||||
void icbi(UGeckoInstruction inst);
|
|
||||||
void lXX(UGeckoInstruction inst);
|
void lXX(UGeckoInstruction inst);
|
||||||
void stX(UGeckoInstruction inst);
|
void stX(UGeckoInstruction inst);
|
||||||
void lmw(UGeckoInstruction inst);
|
void lmw(UGeckoInstruction inst);
|
||||||
|
|
|
@ -18,6 +18,7 @@ using namespace Arm64Gen;
|
||||||
void JitArm64::sc(UGeckoInstruction inst)
|
void JitArm64::sc(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITBranchOff);
|
||||||
|
|
||||||
gpr.Flush(FlushMode::FLUSH_ALL);
|
gpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
fpr.Flush(FlushMode::FLUSH_ALL);
|
fpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
|
@ -38,6 +39,7 @@ void JitArm64::sc(UGeckoInstruction inst)
|
||||||
void JitArm64::rfi(UGeckoInstruction inst)
|
void JitArm64::rfi(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITBranchOff);
|
||||||
|
|
||||||
gpr.Flush(FlushMode::FLUSH_ALL);
|
gpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
fpr.Flush(FlushMode::FLUSH_ALL);
|
fpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
|
@ -78,6 +80,7 @@ void JitArm64::rfi(UGeckoInstruction inst)
|
||||||
void JitArm64::bx(UGeckoInstruction inst)
|
void JitArm64::bx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITBranchOff);
|
||||||
|
|
||||||
gpr.Flush(FlushMode::FLUSH_ALL);
|
gpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
fpr.Flush(FlushMode::FLUSH_ALL);
|
fpr.Flush(FlushMode::FLUSH_ALL);
|
||||||
|
@ -115,6 +118,7 @@ void JitArm64::bx(UGeckoInstruction inst)
|
||||||
void JitArm64::bcx(UGeckoInstruction inst)
|
void JitArm64::bcx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITBranchOff);
|
||||||
|
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
FixupBranch pCTRDontBranch;
|
FixupBranch pCTRDontBranch;
|
||||||
|
@ -173,45 +177,42 @@ void JitArm64::bcx(UGeckoInstruction inst)
|
||||||
void JitArm64::bcctrx(UGeckoInstruction inst)
|
void JitArm64::bcctrx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
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
|
// 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!");
|
_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
|
ARM64Reg WB = gpr.GetReg();
|
||||||
|
u32 Jumpto = js.compilerPC + 4;
|
||||||
//NPC = CTR & 0xfffffffc;
|
MOVI2R(WB, Jumpto);
|
||||||
gpr.Flush(FlushMode::FLUSH_ALL);
|
STR(INDEX_UNSIGNED, WB, X29, PPCSTATE_OFF(spr[SPR_LR]));
|
||||||
fpr.Flush(FlushMode::FLUSH_ALL);
|
gpr.Unlock(WB);
|
||||||
|
|
||||||
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 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)
|
void JitArm64::bclrx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITBranchOff);
|
||||||
|
|
||||||
ARM64Reg WA = gpr.GetReg();
|
ARM64Reg WA = gpr.GetReg();
|
||||||
FixupBranch pCTRDontBranch;
|
FixupBranch pCTRDontBranch;
|
||||||
|
|
|
@ -18,15 +18,6 @@
|
||||||
|
|
||||||
using namespace Arm64Gen;
|
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)
|
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
|
// We want to make sure to not get LR as a temp register
|
||||||
|
|
|
@ -48,8 +48,7 @@ FixupBranch JitArm64::JumpIfCRFieldBit(int field, int bit, bool jump_if_set)
|
||||||
void JitArm64::mtmsr(UGeckoInstruction inst)
|
void JitArm64::mtmsr(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
// Don't interpret this, if we do we get thrown out
|
JITDISABLE(bJITSystemRegistersOff);
|
||||||
//JITDISABLE(bJITSystemRegistersOff)
|
|
||||||
|
|
||||||
gpr.BindToRegister(inst.RS, true);
|
gpr.BindToRegister(inst.RS, true);
|
||||||
STR(INDEX_UNSIGNED, gpr.R(inst.RS), X29, PPCSTATE_OFF(msr));
|
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)
|
void JitArm64::twx(UGeckoInstruction inst)
|
||||||
{
|
{
|
||||||
INSTRUCTION_START
|
INSTRUCTION_START
|
||||||
|
JITDISABLE(bJITSystemRegistersOff);
|
||||||
|
|
||||||
s32 a = inst.RA;
|
s32 a = inst.RA;
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ static GekkoOPTemplate table31[] =
|
||||||
|
|
||||||
{4, &JitArm64::twx}, // tw
|
{4, &JitArm64::twx}, // tw
|
||||||
{598, &JitArm64::DoNothing}, // sync
|
{598, &JitArm64::DoNothing}, // sync
|
||||||
{982, &JitArm64::icbi}, // icbi
|
{982, &JitArm64::FallBackToInterpreter}, // icbi
|
||||||
|
|
||||||
// Unused instructions on GC
|
// Unused instructions on GC
|
||||||
{310, &JitArm64::FallBackToInterpreter}, // eciwx
|
{310, &JitArm64::FallBackToInterpreter}, // eciwx
|
||||||
|
|
Loading…
Reference in New Issue