-
Notifications
You must be signed in to change notification settings - Fork 55
Register Mismatch Decompilation Tricks
This page contains some examples of some unintuitive or tricky compiler tricks that may be SotN specific to get registers to match.
The developers of SotN tended to use foo > bar
in if statements.
That tends to get compiled to look as foo >= bar+1
This can cause the "wrong" registers to be used. Take for example the asm
slti at,v1,0x29
bnez at,3d0
nop
Directly, this translates to
if (foo >= 0x29) {
However, that will compile to
slti v1,v1,0x29
bnez v1,3d0
nop
Which uses the register v1
instead of at
.
The "correct" translation is
if (foo> 0x28)
This is a harder one to find in PSX vs PSP.
Take the following assembly in PSX and PSP
PSX | PSP |
---|---|
lui v1,%hi(foo)
lw v1,%lo(foo)(v1)
nop
bgez v1,1c4 ~>
move v0,v1
addiu v0,v1,0x7f
sra a0,v0,0x7
sll v0,a0,0x7
subu a0,v1,v0 |
lui v0,%hi(foo)
lw v1,%lo(foo)(v0)
li v0,0x80
andi s2,v1,0x7f
bgez v1,284
nop
beqz s2,284
nop
addiu s2,s2,-0x80 |
It sure looks like this is some sort of branching statement and you may try to write something like this
bar = foo & 0x7F;
if (bar < 0 && bar != 0) {
bar -= 128;
}
However, that compiles to (PSP)
lui v0,%hi(foo)
lw v0,%lo(foo)(v0)
andi s1,v0,0x7f
bgez s1,284 ~>
nop
beqz s1,284 ~>
nop
addiu s1,s1,-0x80
Close, but not quite there. The "tell" on this situation is that we are loading 0x80
into v0
on psp, but not doing anything with it.
This may be a compiler bug (it may also be a sort of comment to help debug), but we can leverage it to know that this is actually a modulo. The correct translation is
index = foo % 0x80;