sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
shortloop_scan.py
1#!/usr/bin/env python3
2"""Usage: shortloop_scan.py <objdump> <elf or .a>...
3
4Lists R5900 short-loop erratum hazards in EE code: a conditional branch back over 6 or fewer instructions
5(branch and delay slot included), no other branch or jump inside, and a delay slot that is not a nop."""
6
7import re
8import subprocess
9import sys
10
11OBJDUMP = sys.argv[1]
12BRANCHES = {"beq", "bne", "blez", "bgtz", "bltz", "bgez", "beqz", "bnez", "bc1t", "bc1f", "beql", "bnel", "blezl",
13 "bgtzl", "bltzl", "bgezl", "bc1tl", "bc1fl", "bltzal", "bgezal", "bc0t", "bc0f"}
14JUMPS = {"j", "jal", "jr", "jalr", "b", "bal", "eret", "syscall", "break"}
15
16for elf in sys.argv[2:]:
17 out = subprocess.run([OBJDUMP, "-d", elf], capture_output=True, text=True).stdout
18 sections, ins, func, member = [], [], "?", elf
19 for line in out.splitlines():
20 if "file format" in line or line.startswith("Disassembly of section"):
21 if ins:
22 sections.append((member, ins))
23 ins = []
24 if "file format" in line:
25 member = line.split(":")[0]
26 continue
27 m = re.match(r"^([0-9a-f]+) <(.+)>:$", line)
28 if m:
29 func = m.group(2)
30 continue
31 m = re.match(r"^\s*([0-9a-f]+):\t[0-9a-f]+ \t(\S+)\s*(.*)$", line)
32 if m:
33 ins.append((int(m.group(1), 16), m.group(2), m.group(3), func))
34 if ins:
35 sections.append((member, ins))
36 hazards = 0
37 for member, ins in sections:
38 index = {a: i for i, (a, _, _, _) in enumerate(ins)}
39 for i, (addr, op, args, func) in enumerate(ins):
40 if op not in BRANCHES:
41 continue
42 t = re.search(r"([0-9a-f]+) <", args)
43 if not t:
44 continue
45 target = int(t.group(1), 16)
46 if target > addr or target not in index:
47 continue
48 n = (addr - target) // 4 + 2
49 if n > 6 or i + 1 >= len(ins):
50 continue
51 body = ins[index[target]:i]
52 if any(o in BRANCHES or o in JUMPS for _, o, _, _ in body):
53 continue
54 slot = ins[i + 1]
55 if slot[1] == "nop" or op.endswith("l"):
56 continue
57 hazards += 1
58 print(f"{member}: {func} {addr:08x} {op} {args} | {n} instructions, slot: {slot[1]} {slot[2]}")
59 print(f"{elf}: {hazards} hazards")