marioparty4/tools/interpretasm.py

356 lines
12 KiB
Python

import sys
import os
def rc(s:str)->str: return s.replace(',','')
def join(*args)->str: return " ".join(args)
addrstore = {}
cmpstore = []
isObj = ""
def interpret_cmd(line: list, addr: int)->str:
global addrstore, cmpstore
ret = ""
## Storing
if line[0] == "stwu":
ret = join("Stack Size +=", line[2][1:-4])
elif line[0] == "stb" or line[0] == "sth" or line[0] == "stw" or line[0] == "stfs" or line[0] == "stfd":
if "r1" in line[2]: ret = "Stack"
else: ret = line[2][(line[2].index("(")+1):-1]
ret += join(f"[{line[2][:(line[2].index('('))]}]",
"=",
rc(line[1])
)
if "b" in line[0]: ret += join("", "(s8/u8)")
elif "h" in line[0]: ret += join("", "(s16/u16)")
elif "w" in line[0]: ret += join("", "(s32/u32)")
elif "fs" in line[0]: ret += join("", "(f32)")
elif "fd" in line[0]: ret += join("", "(f64)")
elif line[0] == "stbx" or line[0] == "sthx" or line[0] == "stwx" or line[0] == "stfsx":
if "r1" in line[2]: ret = "Stack"
else: ret = rc(line[2])
ret += join(f"[{line[3]}]",
"=",
rc(line[1])
)
if "b" in line[0]: ret += join("", "(s8/u8)")
elif "h" in line[0]: ret += join("", "(s16/u16)")
elif "w" in line[0]: ret += join("", "(s32/u32)")
elif "f" in line[0]: ret += join("", "(f32)")
elif line[0] == "psq_st":
if "r1" in line[2]: ret = "Stack"
else: ret = line[2][(line[2].index("(")+1):-1]
ret += join(f"[{line[2][:(line[2].index('('))]}]",
"=",
f"rotate({line[1]} {line[4]})",
"(128-bit)"
)
## Moving
elif line[0] == "mflr":
ret = join(line[1], "set to Link Register ")
elif line[0] == "mtlr":
ret = join("Link Register set to", line[1])
elif line[0] == "mtctr":
ret = join("Count Register set to", line[1])
elif line[0] == "mr" or line[0] == "fmr":
ret = join(rc(line[1]), "=", line[2])
## Loading
elif line[0] == "lbz" or line[0] == "lha" or line[0] == "lhz" or line[0] == "lwz" or line[0] == "lwzu" or line[0] == "lfs" or line[0] == "lfd":
ret = join(rc(line[1]), "=")
if "r1" in line[2]: ret += join("", "Stack")
else: ret += join("", line[2][(line[2].index("(")+1):-1])
ret += f"[{line[2][:(line[2].index('('))]}]"
if "b" in line[0]: ret += join("", "(s8/u8)")
elif "h" in line[0]: ret += join("", "(s16/u16)")
elif "w" in line[0]: ret += join("", "(s32/u32)")
elif "fs" in line[0]: ret += join("", "(f32)")
elif "fd" in line[0]: ret += join("", "(f64)")
elif line[0] == "lbzx" or line[0] == "lhax" or line[0] == "lhzx" or line[0] == "lwzx" or line[0] == "lfsx":
ret = join(rc(line[1]), "=")
if "r1" in line[2]: ret += join("", "Stack")
else: ret += join("", rc(line[2]))
ret += f"[{line[3]}]"
if "b" in line[0]: ret += join("", "(s8/u8)")
elif "h" in line[0]: ret += join("", "(s16/u16)")
elif "w" in line[0]: ret += join("", "(s32/u32)")
elif "f" in line[0]: ret += join("", "(f32)")
elif line[0] == "psq_l":
ret = join(f"+ rotate({line[1]} {line[4]})", "=")
if "r1" in line[2]: ret += join("", "Stack")
else: ret += join("", rc(line[2]))
ret += join(f"[{line[2][:(line[2].index('('))]}]",
"(128-bit)")
elif line[0] == "lis":
ret = join("(^u16)", rc(line[1]), "=")
if line[2][-3:] == "@ha":
ret += join("", "(^u16)", line[2][:-3])
else: ret += join("", line[2])
elif line[0] == "li":
ret = join(rc(line[1]), "=", line[2])
## Bitwise Operations
elif "and" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "&=")
else:
ret += join("", "=", rc(line[2]), "&")
ret += join("", line[3])
elif "xor" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "^=")
else:
ret += join("", "=", rc(line[2]), "^")
ret += join("", line[3])
elif "or" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "|=")
else:
ret += join("", "=", rc(line[2]), "|")
ret += join("", line[3])
elif "neg" in line[0]:
ret = join(rc(line[1]), "=", "-"+line[2])
elif line[0] == "slw" or line[0] == "slwi" or line[0] == "slawi":
ret = join(rc(line[1]), "=", rc(line[2]), "<<", line[3], "(s32/u32)", "(signed)" if line[0] == "slawi" else "")
elif line[0] == "srwi" or line[0] == "srawi":
ret = join(rc(line[1]), "=", rc(line[2]), ">>", line[3], "(s32/u32)", "(signed)" if line[0] == "srawi" else "")
## Math
elif "add" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "+=")
else:
ret += join("", "=", rc(line[2]), "+")
if line[3][-2:] == "@l":
ret += join("", "(vu16)")
ret += join("", line[3][:-2])
else: ret += join("", line[3])
elif "sub" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "-=")
else:
ret += join("", "=", rc(line[2]), "-")
ret += join("", line[3])
elif "mul" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "*=")
else:
ret += join("", "=", rc(line[2]), "*")
ret += join("", line[3])
elif "div" in line[0]:
ret = rc(line[1])
if rc(line[1]) == rc(line[2]):
ret += join("", "/=")
else:
ret += join("", "=", rc(line[2]), "/")
ret += join("", line[3])
elif "sqrt" in line[0]:
ret = join(rc(line[1]), f"= sqrt({line[2]})")
elif "abs" in line[0]:
ret = join(rc(line[1]), f"= abs({line[2]})")
## Compare And Branch
elif "cmp" in line[0] and "w" in line[0]:
cmpstore = line
cmpstore.append("(s32/u32)")
ret = "(cmp)"
elif line[0] == "fcmpo":
cmpstore = line
ret = join("(cmp", rc(line[1])+")")
elif "cmp" in line[0] and "f" in line[0]:
cmpstore = line
cmpstore.pop(1)
cmpstore.append("(f32/f64)")
ret = "(cmp)"
elif line[0] == "cror":
cmpsym = ""
if line[2] == "gt,": cmpsym += ">"
elif line[2] == "lt,": cmpsym += "<"
cmpsym += "="
ret = join(
"check", rc(cmpstore[2]),
cmpsym, cmpstore[3],
)
elif line[0] == "beq":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
"==", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "bge":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
">=", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "bne":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
"!=", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "ble":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
"<=", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "blt":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
"<", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "bgt":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join(
"if", rc(cmpstore[1]),
">", cmpstore[2],
": goto", hex(int(line[1][3:], 16)), cmpstore[3]
)
elif line[0] == "blr":
ret = "return"
elif line[0] == "bctrl":
ret = "Call to Subroutine"
elif line[0] == "bctr":
ret = "Jump to Subroutine"
elif line[0] == "b":
addrstore[hex(int(line[1][3:], 16))] = hex(addr)
ret = join("goto", hex(int(line[1][3:], 16)))
elif line[0] == "bl":
ret = join("call", line[1])
## Misc
elif line[0] == "crclr":
ret = f"clear({line[1]})"
elif line[0] == "crset":
ret = f"set({line[1]})"
elif line[0] == "extsh":
ret = join("(s32)", rc(line[1]), "= (s16)", line[2])
elif line[0] == "extsb":
ret = join("(s32)", rc(line[1]), "= (s8)", line[2])
elif line[0] == "clrlwi":
ret = join(rc(line[1]), "=", f"remove({line[2]} {line[3]})")
elif line[0] == "rlwinm":
ret = join(rc(line[1]), "=", f"rotate({line[2]} {rc(line[3])})", "& (bits", rc(line[4]), "to", line[5]+")")
elif line[0] == "frsp":
ret = join("(f32)", rc(line[1]), "= (f64)", line[2])
elif line[0] == "fctiwz":
ret = join("(s32)", rc(line[1]), "= (float)", line[2])
elif line[0] == "cntlzw":
ret = join(rc(line[1]), f"= num_leading_zeroes({line[2]})")
else:
print(line, "\n", [],"\n")
return "unable to interpret: "+str(line)
return ret
def interpret_obj(line: list)->str:
global isObj
ret = ""
if line[0] == "\t.4byte":
if isObj == True:
ret = "{\n"
ret += join("\t(s32)", line[1])
elif line[0] == "\t.string":
ret = join("\t(char[])", " ".join(line[1:]))
elif line[0] == "\t.skip":
ret = join("\tsizeof =", line[1])
elif line[0] == "\t.double":
ret = join("\t(f64)", line[1])
elif line[0] == "\t.float":
ret = join("\t(f32)", line[1])
return ret
def interpret_line(line: list)->str:
global addrstore, isObj
line = line.split(" ")
line[-1] = line[-1].replace("\n","")
ret = ""
if line[0] == ".fn":
ret = join(line[2], "function", rc(line[1])+":")
elif line[0] == ".endfn":
ret = join(line[1], "end\n")
elif line[0] == ".obj":
ret = rc(line[1])+":"
isObj = True
elif line[0] == ".endobj" and isObj == True:
ret = "}"
isObj = False
elif ".L" in line[0]:
try:
ret = join("\n\tfrom", addrstore[hex(int(line[0][3:-1], 16))]+":")
except:
ret = "\n\tfrom later address:"
elif line[0] == "/*":
address = int(line[1], 16)
line[8] = line[8].replace("*/\t","")
ret = join("\t", hex(address), "|",
interpret_cmd(line[8:], address)
)
elif "\t" in line[0]:
ret = interpret_obj(line)
isObj = line[0]
print(line, "\n", ret, "\n")
return ret
def interpret_file(file)->None:
curdir = os.path.dirname(os.path.abspath(__file__))
fs = file.split("/")[-1]
os.system(f"mkdir {curdir}/output")
f = open(file)
g = open(f"{curdir}/output/{fs[:(fs.index('.'))]}-output.txt", "w")
line = f.readline()
while line:
ret = interpret_line(line)
g.write(ret+"\n" if ret != "" else "")
line = f.readline()
g.close()
f.close()
try:
interpret_file(sys.argv[1])
except Exception:
if len(sys.argv) == 1:
print("interpretasm.py")
print("Usage: python3 interpretasm.py [file]")
print("Accepts all files that use the generated asm from ninja")
else:
raise Exception