Disassembly performance improvements (speed, RAM) (#478)

* Improve disasm.py RAM usage using `bisect`

This is based on AngheloAlf's work in PR #477, but uses the built-in
library `bisect` instead of adding an external dependency.

* Caching vrom_variables for ~25% faster disasm.py
This commit is contained in:
Zach Banks 2021-12-06 15:21:01 -05:00 committed by GitHub
parent e177e99933
commit b031598460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 19 deletions

33
tools/disasm/disasm.py Normal file → Executable file
View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
import argparse, ast, math, os, re, struct
import bisect
from mips_isa import *
from multiprocessing import Pool
@ -88,11 +89,11 @@ multiply_referenced_rodata = set() # rodata with more than 1 reference outside o
files = set() # vram start of file
vrom_variables = list() # (name,addr)
vrom_addrs = set() # set of addrs from vrom_variables, for faster lookup
functions_ast = None
variables_ast = None
vars_cache = {} # (address: variable + addend)
variable_addrs = None
def proper_name(symbol, in_data=False, is_symbol=True):
# hacks
@ -116,7 +117,7 @@ def proper_name(symbol, in_data=False, is_symbol=True):
return functions_ast[symbol][0]
elif symbol in variables_ast.keys():
return variables_ast[symbol][0]
elif symbol in [addr for _,addr in vrom_variables]:
elif symbol in vrom_addrs:
# prefer "start" vrom symbols
if symbol in [addr for name,addr in vrom_variables if "SegmentRomStart" in name]:
return [name for name,addr in vrom_variables if "SegmentRomStart" in name and addr == symbol][0]
@ -124,8 +125,15 @@ def proper_name(symbol, in_data=False, is_symbol=True):
return [name for name,addr in vrom_variables if addr == symbol][0]
# addends
if is_symbol and symbol in vars_cache.keys():
return vars_cache[symbol]
if is_symbol:
symbol_index = bisect.bisect(variable_addrs, symbol)
if symbol_index:
vram_addr = variable_addrs[symbol_index-1]
symbol_name, _, _, symbol_size = variables_ast[vram_addr]
if vram_addr < symbol < vram_addr + symbol_size:
return f"{symbol_name} + 0x{symbol-vram_addr:X}"
# generated names
if symbol in functions and not in_data:
@ -142,7 +150,7 @@ def proper_name(symbol, in_data=False, is_symbol=True):
def lookup_name(symbol, word):
# hacks for vrom variables in data
if word in [addr for _,addr in vrom_variables]:
if word in vrom_addrs:
if word == 0: # no makerom segment start
return "0x00000000"
if symbol in [0x801AE4A0, # effect table
@ -1112,13 +1120,8 @@ with open("tools/disasm/functions.txt", "r") as infile:
with open("tools/disasm/variables.txt", "r") as infile:
variables_ast = ast.literal_eval(infile.read())
# Precompute variable addends for all variables, this uses a lot of memory but the lookups later are fast
# Find floats, doubles, and strings
for var in sorted(variables_ast.keys()):
for i in range(var, var + variables_ast[var][3], 1):
addend = i - var
assert addend >= 0
vars_cache.update({i : f"{variables_ast[var][0]}" + (f" + 0x{addend:X}" if addend > 0 else "")})
# also add to floats, doubles & strings
var_type = variables_ast[var][1]
if var_type == "f64":
@ -1164,6 +1167,9 @@ for segment in files_spec:
if segment[3][-1][1] not in variables_ast:
variables_ast.update({segment[3][-1][1] : (f"_{segment[0]}SegmentEnd","u8","[]",0x1)})
# Construct variable_addrs, now that variable_addrs is fully constructed
variable_addrs = sorted(variables_ast.keys())
pool = Pool(jobs)
# Find symbols for each segment
for segment in files_spec:
@ -1219,6 +1225,9 @@ for segment in files_spec:
i += 1
dmadata_entry = dmadata[i*0x10:(i+1)*0x10]
# Construct vrom_addrs, now that vrom_variables is fully constructed
vrom_addrs = {addr for _, addr in vrom_variables}
def disassemble_makerom(segment):
os.makedirs(f"{ASM_OUT}/makerom/", exist_ok=True)
rom_header = segment[3][0][4]

View File

@ -3890,13 +3890,7 @@
0x801E3BB0:("D_801E3BB0","UNK_TYPE1","",0x1),
0x801E3F40:("gJpegUCodeData","UNK_TYPE1","",0x1),
0x801E3FA0:("D_801E3FA0","UNK_TYPE1","",0x1),
0x801E3FB0:("sEffTable","EffTables","",0x98e0),
0x801E4514:("D_801E4514","UNK_TYPE1","",0x1),
0x801E4E08:("D_801E4E08","UNK_TYPE1","",0x1),
0x801E531C:("D_801E531C","UNK_TYPE1","",0x1),
0x801E69E0:("D_801E69E0","UNK_TYPE1","",0x1),
0x801E9AA0:("D_801E9AA0","UNK_TYPE1","",0x1),
0x801ED4C0:("D_801ED4C0","UNK_TYPE1","",0x1),
0x801E3FB0:("sEffTable","EffTables","",0x98E0),
0x801ED890:("D_801ED890","UNK_TYPE1","",0x1),
0x801ED894:("D_801ED894","UNK_TYPE1","",0x1),
0x801ED8A0:("D_801ED8A0","UNK_TYPE1","",0x1),