fixed and reenabled and slightly optimized the JIT version of fcmpo/fcmpu.

This commit is contained in:
nitsuja 2012-01-07 22:19:45 -08:00
parent 2368d88c65
commit 1603bbb5f4
2 changed files with 43 additions and 22 deletions

View File

@ -193,7 +193,7 @@ void Jit64::Init()
jo.enableFastMem = false; jo.enableFastMem = false;
#endif #endif
jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem; jo.assumeFPLoadFromMem = Core::g_CoreStartupParameter.bUseFastMem;
jo.fpAccurateFcmp = true; // Fallback to Interpreter jo.fpAccurateFcmp = Core::g_CoreStartupParameter.bEnableFPRF;
jo.optimizeGatherPipe = true; jo.optimizeGatherPipe = true;
jo.fastInterrupts = false; jo.fastInterrupts = false;
jo.accurateSinglePrecision = true; jo.accurateSinglePrecision = true;

View File

@ -229,8 +229,6 @@ void Jit64::fmrx(UGeckoInstruction inst)
void Jit64::fcmpx(UGeckoInstruction inst) void Jit64::fcmpx(UGeckoInstruction inst)
{ {
// TODO : This still causes crashes in Nights, and broken graphics
// in Paper Mario, Super Paper Mario as well as SoulCalibur 2 prolly others too.. :(
INSTRUCTION_START INSTRUCTION_START
JITDISABLE(FloatingPoint) JITDISABLE(FloatingPoint)
if (jo.fpAccurateFcmp) { if (jo.fpAccurateFcmp) {
@ -243,36 +241,59 @@ void Jit64::fcmpx(UGeckoInstruction inst)
int crf = inst.CRFD; int crf = inst.CRFD;
fpr.Lock(a,b); fpr.Lock(a,b);
if (a != b) fpr.BindToRegister(a, true); fpr.BindToRegister(b, true);
// Are we masking sNaN invalid floating point exceptions? If not this could crash if we don't handle the exception? // Are we masking sNaN invalid floating point exceptions? If not this could crash if we don't handle the exception?
UCOMISD(fpr.R(a).GetSimpleReg(), fpr.R(b)); UCOMISD(fpr.R(b).GetSimpleReg(), fpr.R(a));
FixupBranch pNaN = J_CC(CC_P); FixupBranch pNaN, pLesser, pGreater;
FixupBranch pLesser = J_CC(CC_B); FixupBranch continue1, continue2, continue3;
FixupBranch pGreater = J_CC(CC_A);
if (a != b)
{
// if B > A, goto Lesser's jump target
pLesser = J_CC(CC_A);
}
// if (B != B) or (A != A), goto NaN's jump target
pNaN = J_CC(CC_P);
if (a != b)
{
// if B < A, goto Greater's jump target
// JB can't precede the NaN check because it doesn't test ZF
pGreater = J_CC(CC_B);
}
// Equal // Equal
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2)); MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x2));
FixupBranch continue1 = J(); continue1 = J();
// Greater Than
SetJumpTarget(pGreater);
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4));
FixupBranch continue2 = J();
// Less Than
SetJumpTarget(pLesser);
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8));
FixupBranch continue3 = J();
// NAN // NAN
SetJumpTarget(pNaN); SetJumpTarget(pNaN);
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x1)); MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x1));
if (a != b)
{
continue2 = J();
// Greater Than
SetJumpTarget(pGreater);
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x4));
continue3 = J();
// Less Than
SetJumpTarget(pLesser);
MOV(8, M(&PowerPC::ppcState.cr_fast[crf]), Imm8(0x8));
}
SetJumpTarget(continue1); SetJumpTarget(continue1);
SetJumpTarget(continue2); if (a != b)
SetJumpTarget(continue3); {
SetJumpTarget(continue2);
SetJumpTarget(continue3);
}
fpr.UnlockAll(); fpr.UnlockAll();
} }