summaryrefslogtreecommitdiff
path: root/nandgame/assembler
diff options
context:
space:
mode:
authoruvok2026-01-04 16:56:30 +0100
committeruvok2026-01-04 16:56:30 +0100
commitee1b3cc0312d7b812345682e07039b02364bb550 (patch)
tree08618c05ba87567f81efa5d1fbd013de0ae4b3e2 /nandgame/assembler
parente0971f599e8034f58b80743eacb7ce7f68d293ef (diff)
disas: lowercase ops, arg decode
main
Diffstat (limited to 'nandgame/assembler')
-rwxr-xr-xnandgame/assembler/disas.py113
1 files changed, 78 insertions, 35 deletions
diff --git a/nandgame/assembler/disas.py b/nandgame/assembler/disas.py
index 402df5c..42c681a 100755
--- a/nandgame/assembler/disas.py
+++ b/nandgame/assembler/disas.py
@@ -30,49 +30,92 @@ def decode_jump(ins: int) -> str:
return "; <unknown>"
-
-def decode_ins(ins: int) -> str:
+# return op, and whether it's a one-op or two-op
+def decode_ins(ins: int) -> (str, bool):
opcode = (ins >> 8) & 0x03
ar_n_log = (ins & (1<<10)) != 0
opcode |= (ar_n_log << 2)
- if opcode == 0b000: return "AND"
- if opcode == 0b001: return "OR"
- if opcode == 0b010: return "XOR"
- if opcode == 0b011: return "NEG"
- if opcode == 0b100: return "ADD"
- if opcode == 0b101: return "INC"
- if opcode == 0b110: return "SUB"
- if opcode == 0b111: return "DEC"
+ if opcode == 0b000: return "and", True
+ if opcode == 0b001: return "or", True
+ if opcode == 0b010: return "xor", True
+ if opcode == 0b011: return "neg", False
+ if opcode == 0b100: return "add", True
+ if opcode == 0b101: return "inc", False
+ if opcode == 0b110: return "sub", True
+ if opcode == 0b111: return "dec", False
return "<?>"
+# normally, X = arg1 = D
+def decode_arg1(ins: int) -> str:
+ use_mem = (ins & (1<<12)) != 0
+ zx = (ins & (1<<7)) != 0
+ sw = (ins & (1<<6)) != 0
+
+ if zx: return "0"
+# and not sw?
+# zx and swap: don't care, other arg is zeroed
+
+ if not zx and not sw and not use_mem: return "A"
+ if not zx and not sw and use_mem: return "M"
+
+ return "?"
+
+# normally, Y = arg2 = A
+def decode_arg2(ins: int) -> str:
+ use_mem = (ins & (1<<12)) != 0
+ zx = (ins & (1<<7)) != 0
+ sw = (ins & (1<<6)) != 0
+
+ if zx and sw: return "0"
+ # zx and not swap: don't care, other arg is zeroed
+
+ # zx ???
+ if sw and not use_mem: return "A"
+ if sw and use_mem: return "M"
+
+ return "?"
+
+def decode_dest(ins: int) -> str:
+ dA = (ins & (1<<5)) != 0
+ dD = (ins & (1<<4)) != 0
+ dM = (ins & (1<<3)) != 0
+ dest_s = ""
+ if dA: dest_s += "A "
+ if dD: dest_s += "D "
+ if dM: dest_s += "M"
+ if dest_s: dest_s += ", "
+ return dest_s
+
def decode(ins: int) -> str:
if (ins & 0x8000 == 0):
# mov? ldr? ldi? aaaaaaaaaaa....
- return f"mov A, #{ins}"
+ return f"mov A, #{ins}"
else:
- use_mem = (ins & (1<<12)) != 0
- zx = (ins & (1<<7)) != 0
- sw = (ins & (1<<6)) != 0
- dA = (ins & (1<<5)) != 0
- dD = (ins & (1<<4)) != 0
- dM = (ins & (1<<3)) != 0
-
- codename = decode_ins(ins)
- return f"{codename:<5}<unknown>{decode_jump(ins)}"
-
-try:
- with open(sys.argv[1], "rb") as f:
- while True:
- insb = f.read(2)
- if not insb: break
- ins = int.from_bytes(insb)
- print(f"\t{insb[0]:02x} {insb[1]:02x}\t{decode(ins)}")
-
-except FileNotFoundError:
- print(f"File not found.")
- sys.exit(1)
-# head, tail...
-except BrokenPipeError:
- sys.exit(0)
+ dest_s = decode_dest(ins)
+ codename, two_op = decode_ins(ins)
+ op1 = decode_arg1(ins)
+ op2 = decode_arg2(ins)
+
+ op2_s = f", {op2}" if two_op else ""
+ return f"{codename:<5}{dest_s:<8}{op1:<3}{op2_s:<5}{decode_jump(ins)}"
+
+def main():
+ try:
+ with open(sys.argv[1], "rb") as f:
+ while True:
+ insb = f.read(2)
+ if not insb: break
+ ins = int.from_bytes(insb)
+ print(f"\t{insb[0]:02x} {insb[1]:02x}\t{decode(ins)}")
+
+ except FileNotFoundError:
+ print(f"File not found.")
+ sys.exit(1)
+ # head, tail...
+ except BrokenPipeError:
+ sys.exit(0)
+
+if __name__ == "__main__":
+ main()