05-29-2011, 07:01 PM
Sorry for the delay on this issue, but this one was quite hard to figure out.
Anyway, I've finally traced this bug by disassembling the compiler's instructions at the problematic execution time:
So, that's the trace output that results when the game attempts to interpret this portion of code here:
I've narrowed this down to that particular instruction "08B8CCE0:[00200008]: jr $at". Apparently, at runtime, the register $at contains 08B8CD10.
This causes the execution of "jr $at" to jump to the 0x08B8CD10 address, which in turn contains the instruction "08B8CD10:[0E260447]: jal 0x0898111C".
Now, this should make the compiler jump to the address 0x0898111C, but for some reason it's immediately jumping (not even compiling the delay slot) into 0x08A57578, which contains this:
This is changing the return address to 0x08bd1d20, so the application jumps back to here:
Weird, huh? Either the game forgot to load something at that address, or something is quite wrong with our compilation sequence (most likely ).
Anyway, I've finally traced this bug by disassembling the compiler's instructions at the problematic execution time:
Code:
85750 [user_main] DEBUG compiler - CodeInstruction.compile > 0x8B8CCA8 - addiu $sp, $sp, -16
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCAC - sw $ra, 0($sp)
85766 [user_main] DEBUG compiler - CodeInstruction.compile < 0x8B8CCB0 - jal 0x08981128
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCB4 - nop
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCB8 - lui $a1, 0x08B9 <=> li $a1, 0x08B90000
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCBC - addiu $a0, $v0, -1
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCC0 - sw $v0, -12888($a1)
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCC4 - sltiu $a1, $a0, 15
85766 [user_main] DEBUG compiler - CodeInstruction.compile < 0x8B8CCC8 - beq $a1, $zr, 0x08B8CD18
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCCC - nop
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCD0 - sll $a0, $a0, 0x0002
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCD4 - lui $at, 0x08B9 <=> li $at, 0x08B90000
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCD8 - addu $at, $at, $a0
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCDC - lw $at, -12952($at)
85766 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCE0 - jr $at
85782 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CCE4 - nop
85782 [user_main] DEBUG compiler - CodeInstruction.compile > 0x8B8CD18 - lw $ra, 0($sp)
85782 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CD1C - jr $ra
85782 [user_main] DEBUG compiler - CodeInstruction.compile 0x8B8CD20 - addiu $sp, $sp, 16
85782 [user_main] ERROR compiler - Trying to compile an invalid address 0x02DDF2E0
85782 [user_main] DEBUG compiler - Compilation failed with maxInstruction=3000
85782 [user_main] DEBUG compiler - Compiler.interpret Block 0x8bd1d20
85782 [user_main] INFO compiler - Compiling for Interpreter _S1_2_8BD1D20
85813 [user_main] DEBUG compiler - // class version 50.0 (50)
// access flags 33
public class _S1_2_8BD1D20 implements jpcsp/Allegrex/compiler/IExecutable {
// compiled from: _S1_2_8BD1D20.java
// access flags 1
public <init>()V
ALOAD 0
INVOKESPECIAL java/lang/Object.<init> ()V
RETURN
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public exec(IIZ)I throws java/lang/Exception
ILOAD 1
ILOAD 2
ILOAD 3
INVOKESTATIC _S1_2_8BD1D20.s (IIZ)I
IRETURN
MAXSTACK = 3
MAXLOCALS = 4
// access flags 9
public static s(IIZ)I throws java/lang/Exception
GETSTATIC jpcsp/Allegrex/compiler/RuntimeContext.gpr : [I
ASTORE 4
ICONST_0
ISTORE 5
LDC 146611488
ILOAD 0
ILOAD 1
ILOAD 2
INVOKESTATIC jpcsp/Allegrex/compiler/RuntimeContext.executeInterpreter (IIIZ)I
GETSTATIC jpcsp/Allegrex/compiler/RuntimeContext.currentThread : Ljpcsp/HLE/kernel/types/SceKernelThreadInfo;
DUP
GETFIELD jpcsp/HLE/kernel/types/SceKernelThreadInfo.runClocks : J
ILOAD 5
I2L
LADD
PUTFIELD jpcsp/HLE/kernel/types/SceKernelThreadInfo.runClocks : J
IRETURN
MAXSTACK = 11
MAXLOCALS = 13
}
85813 [user_main] DEBUG compiler - Executable: _S1_2_8BD1D20@13ed2e3
85813 [user_main] WARN hle - 08BD1D2C Unknown instruction 00000000000000000000000000000001 (0x00000001)
143750 [user_main] ERROR compiler - Trying to compile an invalid address 0x00008080
So, that's the trace output that results when the game attempts to interpret this portion of code here:
Code:
08B8CCA8:[27BDFFF0]: addiu $sp, $sp, -16
08B8CCAC:[AFBF0000]: sw $ra, 0($sp)
08B8CCB0:[0E26044A]: jal 0x08981128
08B8CCB4:[00000000]: nop
08B8CCB8:[3C0508B9]: lui $a1, 0x08B9 <=> li $a1, 0x08B90000
08B8CCBC:[2444FFFF]: addiu $a0, $v0, -1
08B8CCC0:[ACA2CDA8]: sw $v0, -12888($a1)
08B8CCC4:[2C85000F]: sltiu $a1, $a0, 15
08B8CCC8:[10A00013]: beq $a1, $zr, 0x08B8CD18
08B8CCCC:[00000000]: nop
08B8CCD0:[00042080]: sll $a0, $a0, 0x0002
08B8CCD4:[3C0108B9]: lui $at, 0x08B9 <=> li $at, 0x08B90000
08B8CCD8:[00240821]: addu $at, $at, $a0
08B8CCDC:[8C21CD68]: lw $at, -12952($at)
08B8CCE0:[00200008]: jr $at
08B8CCE4:[00000000]: nop
08B8CCE8:[0E260447]: jal 0x0898111C
08B8CCEC:[3404000A]: ori $a0, $zr, 10 <=> li $a0, 10
08B8CCF0:[8FBF0000]: lw $ra, 0($sp)
08B8CCF4:[03E00008]: jr $ra
08B8CCF8:[27BD0010]: addiu $sp, $sp, 16
08B8CCFC:[0E260447]: jal 0x0898111C
08B8CD00:[3404000B]: ori $a0, $zr, 11 <=> li $a0, 11
08B8CD04:[8FBF0000]: lw $ra, 0($sp)
08B8CD08:[03E00008]: jr $ra
08B8CD0C:[27BD0010]: addiu $sp, $sp, 16
08B8CD10:[0E260447]: jal 0x0898111C
08B8CD14:[3404000C]: ori $a0, $zr, 12 <=> li $a0, 12
08B8CD18:[8FBF0000]: lw $ra, 0($sp)
08B8CD1C:[03E00008]: jr $ra
08B8CD20:[27BD0010]: addiu $sp, $sp, 16
08B8CD24:[03E00008]: jr $ra
I've narrowed this down to that particular instruction "08B8CCE0:[00200008]: jr $at". Apparently, at runtime, the register $at contains 08B8CD10.
This causes the execution of "jr $at" to jump to the 0x08B8CD10 address, which in turn contains the instruction "08B8CD10:[0E260447]: jal 0x0898111C".
Now, this should make the compiler jump to the address 0x0898111C, but for some reason it's immediately jumping (not even compiling the delay slot) into 0x08A57578, which contains this:
Code:
08A57578:[8FB00000]: lw $s0, 0($sp)
08A5757C:[8FB10004]: lw $s1, 4($sp)
08A57580:[8FB20008]: lw $s2, 8($sp)
08A57584:[8FB3000C]: lw $s3, 12($sp)
08A57588:[8FB40010]: lw $s4, 16($sp)
08A5758C:[8FBF0014]: lw $ra, 20($sp)
08A57590:[03E00008]: jr $ra
This is changing the return address to 0x08bd1d20, so the application jumps back to here:
Code:
08BD1D20:[00000000]: nop
08BD1D24:[08B77CB8]: j 0x02DDF2E0
08BD1D28:[00000001]: Unknown instruction 00000000000000000000000000000001 (0x00000001)
08BD1D2C:[00002710]: mfhi $a0
08BD1D30:[08BD1C80]: j 0x02F47200
08BD1D34:[00000000]: nop
08BD1D38:[00000000]: nop
08BD1D3C:[00000000]: nop
08BD1D40:[00000000]: nop
08BD1D44:[088FF308]: j 0x023FCC20
08BD1D48:[00000000]: nop
08BD1D4C:[08BD97E0]: j 0x02F65F80
08BD1D50:[09FD7960]: j 0x07F5E580
08BD1D54:[09FD7B58]: j 0x07F5ED60
08BD1D58:[0883421C]: j 0x020D0870
08BD1D5C:[00000000]: nop
08BD1D60:[00000000]: nop
08BD1D64:[00000001]: Unknown instruction 00000000000000000000000000000001 (0x00000001)
08BD1D68:[08BD1D20]: j 0x02F47480
08BD1D6C:[00000059]: multu $zr, $zr
08BD1D70:[00000001]: Unknown instruction 00000000000000000000000000000001 (0x00000001)
08BD1D74:[08B70000]: j 0x02DC0000
08BD1D78:[FFFFFFFF]: vflush
08BD1D7C:[08E47378]: j 0x0391CDE0
08BD1D80:[00000001]: Unknown instruction 00000000000000000000000000000001 (0x00000001)
08BD1D84:[00000000]: nop
08BD1D88:[41205200]: Unimplemented MFC0
08BD1D8C:[00000000]: nop
08BD1D90:[00000000]: nop
08BD1D94:[00000000]: nop
08BD1D98:[BF80419A]: Unknown instruction 10111111100000000100000110011010 (0xBF80419A)
08BD1D9C:[00000000]: nop
08BD1DA0:[00000000]: nop
08BD1DA4:[00000000]: nop
08BD1DA8:[BF800000]: Unknown instruction 10111111100000000000000000000000 (0xBF800000)
08BD1DAC:[00000000]: nop
08BD1DB0:[00000000]: nop
Weird, huh? Either the game forgot to load something at that address, or something is quite wrong with our compilation sequence (most likely ).