This is a very simple code to decompile and the output is perfect. The only minor obstacle are references through the global offset table but both IDA and the Decompiler handle them well. Please note the difference in the number of lines to read on the left and on the right.
void __fastcall free_argv(int argc, char **argv)
{
int i; // [sp+1Ch] [+1Ch]
if ( argv )
{
for ( i = 0; i < argc; ++i )
qfree(argv[i]);
qfree(argv);
}
}
64-bit comparison
Sorry for another long assembler listing. It shows that for MIPS, as for other platforms, the decompiler can recognize 64-bit operations and collapse them into very readable constructs.
We recognize magic divisions for MIPS the same way as for other processors. Note that this listing has a non-trivial delay slot.
.globl smod199
smod199: # DATA XREF: .eh_frame:0000875C↓o
# __unwind {
lui $v1, 0x5254
sra $v0, $a0, 31
li $v1, 0x5254E78F
mult $a0, $v1
mfhi $v1
sra $v1, 6
subu $v1, $v0
li $v0, 0xC7
mul $a1, $v1, $v0
jr $ra
subu $v0, $a0, $a1
# } // starts at 4F2C
int __fastcall smod199(int a1)
{
return a1 % 199;
}
Hard cases with delay slots
The previous example was a piece of cake. This one shows a tougher nut to crack: there is a jump to a delay slot. A decent decompiler must handle these cases too and produce a correct output without misleading the user. This is what we do. (We spent quite long time inventing and testing various scenarios with delay slots).
branch_to_b_dslot: # CODE XREF: branch_to_bal_dslot+14↓p
# DATA XREF: branch_likely_cond_move+10↓o
move $t2, $a0
addiu $t3, $t2, -0x18
bltz $t3, l1
li $a0, 1
sllv $a0, $t3
b l2
l1: # CODE XREF: branch_to_b_dslot+8↑j
li $t4, 0xFFFFFFC0
li $t3, 0x18
subu $t3, $t2
srav $a0, $t3
l2: # CODE XREF: branch_to_b_dslot+14↑j
jr $ra
addu $v0, $a0, $t4
# End of function branch_to_b_dslot
We support both big-endian and little-endian code. Usually they look the same but there may be subtle differences in the assembler. The decompiler keeps track of the bits involved and produces human-readable code.
.globl upd_d2
upd_d2:
lwl $v0, 5($a0)
lwr $v0, 2($a0)
addiu $v0, $v0, 1
swl $v0, 5($a0)
swr $v0, 2($a0)
jr $ra
lb $v0, 0($a0)
# End of function upd_d2
.globl upd_d2
upd_d2:
lwl $v0, 2($a0)
lwr $v0, 5($a0)
addiu $v0, $v0, 1
swl $v0, 2($a0)
swr $v0, 5($a0)
jr $ra
lb $v0, 0($a0)
# End of function upd_d2
__int64 __fastcall lwm16_sp(int a1, int a2, int a3)
{
return a1 + a2 + a3;
}
Floating-point operations
The MIPS processor contains a number of complex floating point instructions, which perform several operations at once. It is not easy to decipher the meaning of the assembler code but the pseudocode is the simplest possible.