Open CreepNT opened 2 years ago
Another example:
foo:
ldr rX, [addr]
lsls rY, rX, #0x1f
bmi foo
Gets decompiled into (Ghidra 11.0):
do {
} while (*addr << 0x1f < 0);
Where it could be simplified to:
do {
} while (*addr & 1);
Is your feature request related to a problem? Please describe. In optimized code for ARMv7 in Thumb mode, bitwise test conditionals (e.g.
if (a & 0x10)
) can be turned into a sequence of instructions Ghidra fails to interpret properly, generating pseudo-code likeif ((int)(a << 0x1B) < 0)
. This "abuses" the fact that most significant bit being set results in the N bit being set in the APSR.For example, the following C snippet
would be compiled "naively" to something like:
which Ghidra decompiles to a readable snippet:
However, this sequence can be optimized to save 2 bytes by doing the following instead:
My understanding of how it works is because
lsls
sets the flags in APSR, andN
egative flag is set whenever MSB is set (thanks to 2's complement). Ghidra decompiles this assembly to the following much less readable pseudo-C code:Describe the solution you'd like Decompiler should be able to recognize such patterns and emit the proper bitwise AND check instead of convoluted shift + <0 check.
Describe alternatives you've considered At the moment, I use a lookup table to match the shift level to the proper bit (e.g.
<< 0x1B
is& 0x10
), but this is inconvenient and can be error-prone (reading& 0x20
instead of& 0x10
can lead to confusion later on if& 0x20
is used for completely different purposes).