mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-02-08 21:53:31 +01:00
Jit64: Fix FinalizeCarryOverflow XER[OV/SO]
FinalizeCarryOverflow didn't maintain XER[OV/SO] properly due to an oversight. Here's the code it would generate: 0: 9c pushf 1: 80 65 3b fe and BYTE PTR [rbp+0x3b],0xfe 5: 71 04 jno b <jno> 7: c6 45 3b 03 mov BYTE PTR [rbp+0x3b],0x3 000000000000000b <jno>: b: 9d popf At first glance it seems reasonable. The host flags are carefully preserved with PUSHF. The AND instruction clears XER[OV]. Next, an conditional branch checks the host's overflow flag and, if needed, skips over a MOV that sets XER[OV/SO]. Finally, host flags are restored with POPF. However, the AND instruction also clears the host's overflow flag. As a result, the branch that follows it is always taken and the MOV is always skipped. The end result is that XER[OV] is always cleared while XER[SO] is left unchanged. Putting POPF immediately after the AND would fix this, but we already have GenerateOverflow doing it correctly (and without the PUSHF/POPF shenanigans too). So let's just use that instead.
This commit is contained in:
parent
0776263c5e
commit
305cd31bd9
@ -122,15 +122,7 @@ void Jit64::FinalizeCarryOverflow(bool oe, bool inv)
|
|||||||
{
|
{
|
||||||
if (oe)
|
if (oe)
|
||||||
{
|
{
|
||||||
// Make sure not to lose the carry flags (not a big deal, this path is rare).
|
GenerateOverflow();
|
||||||
PUSHF();
|
|
||||||
// XER[OV] = 0
|
|
||||||
AND(8, PPCSTATE(xer_so_ov), Imm8(~XER_OV_MASK));
|
|
||||||
FixupBranch jno = J_CC(CC_NO);
|
|
||||||
// XER[OV/SO] = 1
|
|
||||||
MOV(8, PPCSTATE(xer_so_ov), Imm8(XER_SO_MASK | XER_OV_MASK));
|
|
||||||
SetJumpTarget(jno);
|
|
||||||
POPF();
|
|
||||||
}
|
}
|
||||||
// Do carry
|
// Do carry
|
||||||
FinalizeCarry(inv ? CC_NC : CC_C);
|
FinalizeCarry(inv ? CC_NC : CC_C);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user