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 // 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);