mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
8e81afd111
Recompiler bug fix: full_function_emitter treated conditional branch delay slots at function boundaries as fully resolved control flow, suppressing the fall-through tail call for the "not taken" path. This broke 15 cross-function fall-throughs across the BIOS, most critically the find-free-EvCB-slot function (BFC11800) whose search loop was silently skipped — causing OpenEvent to return garbage handles (0xF100E1E8) instead of valid slot indices (0xF1000000..0xF1000005). Fix: only suppress fall-through for unconditional flow (j/jr/jal/jalr/rfe). Conditional branches (beq/bne/blez/bgtz/bltz/bgez) now always emit `cpu->pc = next_addr; return;` for the not-taken path. Also included: - Tier 1 reverse debugger: 1M-entry write trace ring (32 MB), 64K-entry MMIO trace ring (2 MB), 8-slot multi-range address filtering, function attribution via g_debug_current_func_addr. 6 new TCP commands: wtrace_add/del/ranges/stats, mmio_dump/clear. - 3 new dispatch seeds for functions exposed by fall-through fix (SIO epilogue, exception chain walker, GTE init). - Diagnostic tools: analyze_sio_trace, decode_insn, decode_jt, mmio_tally. - Pattern 5 trampoline fix + PLAN.md Phase 4 status update. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
37 lines
1.2 KiB
Python
37 lines
1.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Decode MIPS instructions from hex."""
|
|
import struct
|
|
|
|
hex_str = "020004240c0000000800e00300000000a0000a2408004001"
|
|
data = bytes.fromhex(hex_str)
|
|
addr = 0x8005AA10
|
|
|
|
for i in range(0, len(data), 4):
|
|
w = struct.unpack('<I', data[i:i+4])[0]
|
|
op = (w >> 26) & 0x3F
|
|
rs = (w >> 21) & 0x1F
|
|
rt = (w >> 16) & 0x1F
|
|
rd = (w >> 11) & 0x1F
|
|
imm = w & 0xFFFF
|
|
simm = imm if imm < 0x8000 else imm - 0x10000
|
|
target26 = (w & 0x03FFFFFF) << 2
|
|
func = w & 0x3F
|
|
|
|
pc = addr + i
|
|
if op == 0x09: # ADDIU
|
|
print(f" {pc:08X}: addiu ${rt}, ${rs}, {simm} (0x{w:08X})")
|
|
elif op == 0x0F: # LUI
|
|
print(f" {pc:08X}: lui ${rt}, 0x{imm:04X} (0x{w:08X})")
|
|
elif op == 0x00 and func == 0x08: # JR
|
|
print(f" {pc:08X}: jr ${rs} (0x{w:08X})")
|
|
elif op == 0x00 and func == 0x00 and w == 0: # NOP
|
|
print(f" {pc:08X}: nop (0x{w:08X})")
|
|
elif op == 0x03: # JAL
|
|
jtarget = (pc & 0xF0000000) | target26
|
|
print(f" {pc:08X}: jal 0x{jtarget:08X} (0x{w:08X})")
|
|
elif op == 0x02: # J
|
|
jtarget = (pc & 0xF0000000) | target26
|
|
print(f" {pc:08X}: j 0x{jtarget:08X} (0x{w:08X})")
|
|
else:
|
|
print(f" {pc:08X}: ??? op={op} 0x{w:08X}")
|