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

Fix various issues with the twi/tw instructions #1017

Merged
merged 2 commits into from Sep 9, 2014

Conversation

zhuowei
Copy link
Contributor

@zhuowei zhuowei commented Sep 7, 2014

This patch fixes three issues with tw/twi emulation:

1: force propagated constant into register to avoid "a1 cannot be immediate" errors

Tw/twi is a "trap if comparison is true" instruction, which means that a cmp instruction is generated.
The emitter wants a register in the first argument to cmp, but constant propagation may try to pass in a constant instead.
For now, fall back to interpreter instead of displaying error: a proper way to translate this would be to load constant into a scratch register first like cmpXX does.

Do games actually use these two instructions? I ran into this error when attempting to run Wii Linux.

2: tw/twi instruction are switched in Jit64 and JitArm
the twi instruction was generating the comparison instruction for tw, and vise versa. This corrects that mistake.

3: fix another potential logging spam in the interpreter when tw is run
#1011 got rid of the ERROR_LOG printed when twi is run in interpreter, but I missed the same logging that was present in tw. This downgrades that log to DEBUG_LOG also.

@Sonicadvance1
Copy link
Contributor

Yes, I know that PSO uses one of them in its movie player.

@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

Huh. And it doesn't pop up a dialog saying "WriteNormalOp - a1 cannot be imm"? Or is constant propagation not in effect for PSO's tw instructions?

@Sonicadvance1
Copy link
Contributor

Doesn't seem to hit it with constant propagation.

@FioraAeterna
Copy link
Contributor

This is what KillImmediate/BindToRegister is for, isn't it?

@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

Which one of the two should I use? Twi just needs to compare a register against an immediate.

I guess I need to pass doLoad=true to BindToRegister to have it load the value into a register, but what should I pass in for makeDirty?

@FioraAeterna
Copy link
Contributor

If the register isn't modified, set makeDirty to false. Otherwise, let it default to true.

@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

Modified to bind constants to a register before emitting the cmp instruction.

@@ -1997,6 +1997,9 @@ void Jit64::twx(UGeckoInstruction inst)

s32 a = inst.RA;

if (gpr.R(a).IsImm())
gpr.BindToRegister(a, true);

This comment was marked as off-topic.

@FioraAeterna
Copy link
Contributor

if you're doing "if immediate, then bind", I think KillImmediate is what you want.

if you just bind unconditionally, then use BindToRegister.

@BhaaLseN
Copy link
Member

BhaaLseN commented Sep 7, 2014

Also, possibly change the PR title since it isn't falling back to Interpreter.

@zhuowei zhuowei changed the title Fall back to interpreter for tw/twi if rA is a constant to avoid "a1 cannot be imm" error for tw/twi, force propagated constant into register to avoid "a1 cannot be immediate" errors Sep 7, 2014
@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

Changed the title, thanks.

… avoid "a1 cannot be immediate" errors from the emitter
@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

I switched to KillImmediate and marked makeDirty as false, since it only uses it to do one comparison.

@zhuowei zhuowei changed the title for tw/twi, force propagated constant into register to avoid "a1 cannot be immediate" errors Do not merge: for tw/twi, force propagated constant into register to avoid "a1 cannot be immediate" errors Sep 7, 2014
@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

I think I'm still not doing this right: Wii Linux boots farther if I disable tw/twi in the jit and make them fall back. Please don't merge this for now.

@zhuowei
Copy link
Contributor Author

zhuowei commented Sep 7, 2014

Updated PR (it turn out twi was being JIT translated as a tw and vise versa)

Can someone test this with a known working game that actually uses these instructions (for example, PSO)? I can only test with Wii Linux.

@zhuowei zhuowei changed the title Do not merge: for tw/twi, force propagated constant into register to avoid "a1 cannot be immediate" errors Fix various issues with the twi/tw instructions Sep 7, 2014
… the ERROR_LOG printed when tw is ran in the interpreter to DEBUG
@comex
Copy link
Contributor

comex commented Sep 7, 2014

@dolphin-emu-bot rebuild

@Sonicadvance1
Copy link
Contributor

PSO still works here, but it also worked before with it being wrong.
But nice catch, I just copied the JIT64 for the ARMJit which is why it was backwards there as well.
LGTM

skidau added a commit that referenced this pull request Sep 9, 2014
Fix various issues with the twi/tw instructions
@skidau skidau merged commit e8d8713 into dolphin-emu:master Sep 9, 2014
@zhuowei zhuowei deleted the tw_fallback_if_constant_ra branch September 10, 2014 14:35
CMP(32, gpr.R(a), Imm32((s32)(s16)inst.SIMM_16));
else // tw
CMP(32, gpr.R(a), gpr.R(inst.RB));

This comment was marked as off-topic.

@FioraAeterna
Copy link
Contributor

gpr.KillImmediate(a, true, false); should be gpr.BindToRegister(a, true, false);

@skidau
Copy link
Contributor

skidau commented Sep 23, 2014

Have opened PR #1153 to fix the PanicAlert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
6 participants