Jit64: implement tw/twi more accurately

Fixes issue 7253.
This commit is contained in:
Tillmann Karras 2014-05-03 06:36:55 +02:00
parent a1374dd4ba
commit 4cce79e744
1 changed files with 18 additions and 39 deletions

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <vector>
#include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64/JitAsm.h"
#include "Core/PowerPC/Jit64/JitRegCache.h"
@ -2183,56 +2185,33 @@ void Jit64::twx(UGeckoInstruction inst)
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
MOV(8, R(AL), Imm8(inst.TO));
if (inst.OPCD == 3) // twi
CMP(32, gpr.R(a), gpr.R(inst.RB));
else // tw
CMP(32, gpr.R(a), Imm32((s32)(s16)inst.SIMM_16));
FixupBranch al = J_CC(CC_L);
FixupBranch ag = J_CC(CC_G);
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);
std::vector<FixupBranch> fixups;
CCFlags conditions[] = { CC_A, CC_B, CC_E, CC_G, CC_L };
SetJumpTarget(al);
TEST(8, R(AL), Imm8(16));
FixupBranch exit1 = J_CC(CC_NZ);
FixupBranch take1 = J();
SetJumpTarget(ag);
TEST(8, R(AL), Imm8(8));
FixupBranch exit2 = J_CC(CC_NZ);
FixupBranch take2 = J();
SetJumpTarget(ae);
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();
for (int i = 0; i < 5; i++)
{
if (inst.TO & (1 << i))
{
FixupBranch f = J_CC(conditions[i]);
fixups.push_back(f);
}
}
FixupBranch dont_trap = J();
SetJumpTarget(take1);
SetJumpTarget(take2);
SetJumpTarget(take3);
SetJumpTarget(take4);
SetJumpTarget(take5);
for (const FixupBranch& fixup : fixups)
{
SetJumpTarget(fixup);
}
LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_PROGRAM));
WriteExceptionExit();
SetJumpTarget(exit1);
SetJumpTarget(exit2);
SetJumpTarget(exit3);
SetJumpTarget(exit4);
SetJumpTarget(exit5);
SetJumpTarget(dont_trap);
if (!analyzer.HasOption(PPCAnalyst::PPCAnalyzer::OPTION_CONDITIONAL_CONTINUE))
WriteExit(js.compilerPC + 4);