Jit64: implement tw/twi more accurately
Fixes issue 7253.
This commit is contained in:
parent
a1374dd4ba
commit
4cce79e744
|
@ -2,6 +2,8 @@
|
||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Core/PowerPC/Jit64/Jit.h"
|
#include "Core/PowerPC/Jit64/Jit.h"
|
||||||
#include "Core/PowerPC/Jit64/JitAsm.h"
|
#include "Core/PowerPC/Jit64/JitAsm.h"
|
||||||
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/JitRegCache.h"
|
||||||
|
@ -2183,56 +2185,33 @@ void Jit64::twx(UGeckoInstruction inst)
|
||||||
gpr.Flush(FLUSH_ALL);
|
gpr.Flush(FLUSH_ALL);
|
||||||
fpr.Flush(FLUSH_ALL);
|
fpr.Flush(FLUSH_ALL);
|
||||||
|
|
||||||
MOV(8, R(AL), Imm8(inst.TO));
|
|
||||||
|
|
||||||
if (inst.OPCD == 3) // twi
|
if (inst.OPCD == 3) // twi
|
||||||
CMP(32, gpr.R(a), gpr.R(inst.RB));
|
CMP(32, gpr.R(a), gpr.R(inst.RB));
|
||||||
else // tw
|
else // tw
|
||||||
CMP(32, gpr.R(a), Imm32((s32)(s16)inst.SIMM_16));
|
CMP(32, gpr.R(a), Imm32((s32)(s16)inst.SIMM_16));
|
||||||
|
|
||||||
FixupBranch al = J_CC(CC_L);
|
std::vector<FixupBranch> fixups;
|
||||||
FixupBranch ag = J_CC(CC_G);
|
CCFlags conditions[] = { CC_A, CC_B, CC_E, CC_G, CC_L };
|
||||||
FixupBranch ae = J_CC(CC_Z);
|
|
||||||
// FIXME: will never be reached. But also no known code uses it...
|
|
||||||
_assert_msg_(DYNA_REC, (inst.TO & 3) == 0, "Seems like something actually does use this.");
|
|
||||||
FixupBranch ll = J_CC(CC_NO);
|
|
||||||
FixupBranch lg = J_CC(CC_O);
|
|
||||||
|
|
||||||
SetJumpTarget(al);
|
for (int i = 0; i < 5; i++)
|
||||||
TEST(8, R(AL), Imm8(16));
|
{
|
||||||
FixupBranch exit1 = J_CC(CC_NZ);
|
if (inst.TO & (1 << i))
|
||||||
FixupBranch take1 = J();
|
{
|
||||||
SetJumpTarget(ag);
|
FixupBranch f = J_CC(conditions[i]);
|
||||||
TEST(8, R(AL), Imm8(8));
|
fixups.push_back(f);
|
||||||
FixupBranch exit2 = J_CC(CC_NZ);
|
}
|
||||||
FixupBranch take2 = J();
|
}
|
||||||
SetJumpTarget(ae);
|
FixupBranch dont_trap = J();
|
||||||
TEST(8, R(AL), Imm8(4));
|
|
||||||
FixupBranch exit3 = J_CC(CC_NZ);
|
|
||||||
FixupBranch take3 = J();
|
|
||||||
SetJumpTarget(ll);
|
|
||||||
TEST(8, R(AL), Imm8(2));
|
|
||||||
FixupBranch exit4 = J_CC(CC_NZ);
|
|
||||||
FixupBranch take4 = J();
|
|
||||||
SetJumpTarget(lg);
|
|
||||||
TEST(8, R(AL), Imm8(1));
|
|
||||||
FixupBranch exit5 = J_CC(CC_NZ);
|
|
||||||
FixupBranch take5 = J();
|
|
||||||
|
|
||||||
SetJumpTarget(take1);
|
for (const FixupBranch& fixup : fixups)
|
||||||
SetJumpTarget(take2);
|
{
|
||||||
SetJumpTarget(take3);
|
SetJumpTarget(fixup);
|
||||||
SetJumpTarget(take4);
|
}
|
||||||
SetJumpTarget(take5);
|
|
||||||
LOCK();
|
LOCK();
|
||||||
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_PROGRAM));
|
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_PROGRAM));
|
||||||
WriteExceptionExit();
|
WriteExceptionExit();
|
||||||
|
|
||||||
SetJumpTarget(exit1);
|
SetJumpTarget(dont_trap);
|
||||||
SetJumpTarget(exit2);
|
|
||||||
SetJumpTarget(exit3);
|
|
||||||
SetJumpTarget(exit4);
|
|
||||||
SetJumpTarget(exit5);
|
|
||||||
|
|
||||||
if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
|
if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
|
||||||
WriteExit(js.compilerPC + 4);
|
WriteExit(js.compilerPC + 4);
|
||||||
|
|
Loading…
Reference in New Issue