summaryrefslogtreecommitdiff
path: root/nandgame/assembler/disas.py
diff options
context:
space:
mode:
authoruvok2026-01-05 14:27:14 +0100
committeruvok2026-01-05 14:27:14 +0100
commit572e9f8d21896bf266bd88895dc1056576f6de2c (patch)
tree89a5df8fa3858d739fa032946238d3bf158b2201 /nandgame/assembler/disas.py
parentf0ea83ca7a5342d7cb1bdebeda7b80c1e4392543 (diff)
Canonicalize ops
Diffstat (limited to 'nandgame/assembler/disas.py')
-rwxr-xr-xnandgame/assembler/disas.py52
1 files changed, 40 insertions, 12 deletions
diff --git a/nandgame/assembler/disas.py b/nandgame/assembler/disas.py
index cabdcdd..607537a 100755
--- a/nandgame/assembler/disas.py
+++ b/nandgame/assembler/disas.py
@@ -11,11 +11,13 @@ import sys
ZERO = "#0"
DEST_NONE = "_"
+JUMP_NONE = ""
def decode_jump(ins: int) -> str:
if (ins & 0x7) == 0:
- return ""
+ return JUMP_NONE
+
if (ins & 0x7) == 0x7:
return "jmp"
@@ -111,7 +113,7 @@ def decode_dest(ins: int) -> str:
return dest if dest else DEST_NONE
-def decode_instruction_complete(ins: int) -> list[str]:
+def decode_instruction(ins: int) -> list[str]:
"""
Will return a 5 element list/tuple/whatever
mnemonic, destination, X, Y, jumpdest
@@ -120,27 +122,45 @@ def decode_instruction_complete(ins: int) -> list[str]:
# mov? ldr? ldi? aaaaaaaaaaa....
return ["mov", "A", f"#{ins}", "", ""]
else:
- codename, two_op = decode_ins(ins)
+ mnemonic, two_op = decode_ins(ins)
dest = decode_dest(ins)
op1 = decode_arg1(ins)
op2 = decode_arg2(ins) if two_op else ""
jumpdest = decode_jump(ins)
+ return [mnemonic, dest, op1, op2, jumpdest]
+
- # fixups
- if op1 == ZERO and codename == "sub":
- return ["neg", dest, op2, "", jumpdest]
+def fixup_ins(ins: int) -> list[str]:
+ (mnemonic, dest, op1, op2, jumpdest) = decode_instruction(ins)
+ # fixups
+ # subtract something from #0 - subtraction
+ if op1 == ZERO and mnemonic == "sub":
+ return ["neg", dest, op2, "", jumpdest]
- return [codename, dest, op1, op2, jumpdest]
+ # 0 AND something = 0
+ # if no dest, only jump matters
+ if mnemonic == "and" and op1 == ZERO and dest == DEST_NONE:
+ # jump always or jump-if-zero --> always jump
+ if jumpdest in ["jgt", "jlt", "jne", JUMP_NONE]:
+ return ["nop", "", "", "", ""]
+ # all other jumps? <=, >=, =, <=>
+ else:
+ return ["jmp", "", "", "", ""]
+ return [mnemonic, dest, op1, op2, jumpdest]
-def print_decoded(ins: int) -> str:
- (codename, dest, op1, op2, jumpdest) = decode_instruction_complete(ins)
+
+def print_decoded(ins: int, simplify: bool) -> str:
+ if simplify:
+ (mnemonic, dest, op1, op2, jumpdest) = fixup_ins(ins)
+ else:
+ (mnemonic, dest, op1, op2, jumpdest) = decode_instruction(ins)
jumpdest_str = f".{jumpdest}" if jumpdest else ""
- opcode_str = f"{codename}{jumpdest_str}"
+ opcode_str = f"{mnemonic}{jumpdest_str}"
dest_str = f"{dest}, " if dest else 7 * " "
op1_str = f"{op1}{", " if op2 else ""}"
- return f"{opcode_str:<9}{dest_str:<6}{op1_str:<4}{op2:<5}"
+ return f"{opcode_str:<9}{dest_str:<6}{op1_str:<4}{op2}"
def main():
@@ -156,7 +176,15 @@ def main():
if not insb:
break
ins = int.from_bytes(insb)
- print(f"\t{insb[0]:02x} {insb[1]:02x}\t{print_decoded(ins)}")
+ raw_ins = f"{insb[0]:02x} {insb[1]:02x}"
+ decoded_ins = print_decoded(ins, False)
+ decoded_ins2 = print_decoded(ins, True)
+ if decoded_ins == decoded_ins2:
+ line = f"\t{raw_ins}\t{decoded_ins}"
+ else:
+ line = f"\t{raw_ins}\t{decoded_ins2:<25}; {decoded_ins}"
+
+ print(line)
except FileNotFoundError:
print(f"File {filename} not found.")