Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jit64: Fix FinalizeCarryOverflow XER[OV/SO] #9429

Merged
merged 1 commit into from
Jan 10, 2021

Conversation

Sintendo
Copy link
Member

@Sintendo Sintendo commented Jan 9, 2021

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.

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.
@lioncash lioncash merged commit a613c2a into dolphin-emu:master Jan 10, 2021
@Sintendo Sintendo deleted the jit64fixoverflow branch January 10, 2021 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants