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

JIT: Don't assume the reserved bits in GQRs are zero #736

Merged
merged 1 commit into from Aug 5, 2014

Conversation

FioraAeterna
Copy link
Contributor

While the unused bits in the GQR SPR are probably not supposed to be set, some
games set them anyways (e.g. Dirt 2), which broke the JIT code.

@FioraAeterna
Copy link
Contributor Author

Note that Dirt only broke because of psq_st, but I figured I should modify psq_l for consistency, since if a game could break on the former it could break on the latter too, I'd think.

@phire
Copy link
Member

phire commented Aug 4, 2014

Great work; This should be fixed in JitIL as well.

@FioraAeterna
Copy link
Contributor Author

JitIL fixed, I think.

@@ -38,7 +38,10 @@ void Jit64::psq_st(UGeckoInstruction inst)
ADD(32, R(ECX), Imm32((u32)offset));
if (update && offset)
MOV(32, gpr.R(a), R(ECX));
MOVZX(32, 16, EAX, M(&PowerPC::ppcState.spr[SPR_GQR0 + inst.I]));
// We need to mask out the unused bits; some games (e.g. Dirt 2) incorrectly
// set the unused bits which breaks the lookup table code.

This comment was marked as off-topic.

@shuffle2
Copy link
Contributor

shuffle2 commented Aug 4, 2014

Just curious, have you looked at the offending Dirt2 code to see if it really intends to set those bits, or it could be a side effect of another bug?

@FioraAeterna
Copy link
Contributor Author

I don't know how I'd figure out whether or not Dirt2 was doing that; any suggestions?

@FioraAeterna
Copy link
Contributor Author

Okay, I wrote up some debug code and got this:

47:33:582 PowerPC\Interpreter\Interpreter_SystemRegisters.cpp:315 E[PowerPC]: GQR set to 80048004
47:33:582 PowerPC\Interpreter\Interpreter_SystemRegisters.cpp:315 E[PowerPC]: GQR set to 50005
47:33:582 PowerPC\Interpreter\Interpreter_SystemRegisters.cpp:315 E[PowerPC]: GQR set to 60006
47:33:582 PowerPC\Interpreter\Interpreter_SystemRegisters.cpp:315 E[PowerPC]: GQR set to 70007

Since the GQR isn't supposed to have bits other than 0x3F073F07 set, this looks like a mistake.

While the unused bits in the GQR SPR are probably not supposed to be set, some
games set them anyways (e.g. Dirt 2), which broke the JIT code.
@magcius
Copy link
Member

magcius commented Aug 4, 2014

Sure, but how are these bits being set? It might be a bug in our code somewhere. I still want to figure out if the hardware actually ignores these bits too. If so, it might make more sense to mask the value when the registers are actually set.

@FioraAeterna
Copy link
Contributor Author

Those log messages were directly from the interpreter, directly running game code. I don't see how it could be a bug in Dolphin; those are the values the game itself is trying to fill those registers with, unless I'm missing something about how SPRs work.

@magcius
Copy link
Member

magcius commented Aug 4, 2014

Well, those values were presumably also calculated by the interpreter. There could be another bug in the interpreter causing it to emit those bogus values, which it's eventually trying to write to the GQRs.

@neobrain
Copy link
Member

neobrain commented Aug 4, 2014

I guess the suggestion is obvious enough, but a hwtest would clear this up fairly easily, I guess :)
(although still there might be a chance that the game is simply calculating the value it's using incorrectly)

@FioraAeterna
Copy link
Contributor Author

I don't know how to do a hwtest (and I'm not back home with my Wii for another week, so I couldn't homebrew it even if I wanted to!)

@neobrain
Copy link
Member

neobrain commented Aug 4, 2014

Look at the existing ones at https://github.com/dolphin-emu/hwtests/tree/master/cputest .

If you can give me some PPC assembly code to perform such a test, I might be able to write one myself (chances are I fail too much for that, though :p)

@shuffle2
Copy link
Contributor

shuffle2 commented Aug 4, 2014

hwtest isn't the answer to my question (although it's a good idea for determining how writing those bits behaves [although it seems pretty clear they are just hardwired to 0]), it's figuring out how the values written to GQRs are calculated. Try finding the PC of the write in Dirt2 and tracing the taint back.

@FioraAeterna
Copy link
Contributor Author

I tried to track it down, but I was led only to a function that takes a memory buffer and fills the GQRs with it. I tried disabling most of the JIT and seeing if the problem remained (i.e. incorrect GQR value) and it did, so if it -is- a Dolphin bug generating those values, it's common to the interpreter too.

@FioraAeterna
Copy link
Contributor Author

Okay, the actual setting happens here:
lis r3, 0x8005
subi r0, r3, 32764
mtspr GQR2, r0

This looks really intentional; I have no idea what they're trying to do here. This is a GQR that was previously set to 0x00040004, and they're going to great effort to explicitly change it to 0x80048004. I can't imagine why...

... I really hope they're not using the upper bit as a flag or something for their own purposes

@FioraAeterna
Copy link
Contributor Author

Okay, I have a hwtest possibility, if anyone else can test it, based on this code:

lis r3, 0x8005
subi r0, r3, 32764
mtspr GQR2, r0
mfspr r0, GQR2

My question is basically: is r0 (at the end) 0x80048004 or 0x00040004?

@FioraAeterna
Copy link
Contributor Author

Okay, flacs did a hwtest and it looks like the PPC does not internally zero the unused bits -- it just doesn't use them (storing and loading keeps the bits unchanged).

@FioraAeterna
Copy link
Contributor Author

https://gist.github.com/FioraAeterna/f142b01f4dc10cab687a Here's the hardware test, for reference.

@FioraAeterna
Copy link
Contributor Author

Since it looks like games actually intentionally set these bits (for some bizarre reason), and the CPU does not clear them, we should probably stick to the AND solution, instead of masking out the bits inside mtpsr, since the latter might be incorrect (if a game stores a flag in the unused part of the GQR, it'll want the flag to still be there when it reads it out later).

delroth added a commit that referenced this pull request Aug 5, 2014
JIT: Don't assume the reserved bits in GQRs are zero
@delroth delroth merged commit b7d4481 into dolphin-emu:master Aug 5, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
6 participants