diff options
Diffstat (limited to 'disasm.py')
-rwxr-xr-x | disasm.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/disasm.py b/disasm.py new file mode 100755 index 0000000..3ba5c2f --- /dev/null +++ b/disasm.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +import sys + +mnems = """ +nop +rot +nrt +dup +swp +ovr +drp +tck +nip +equ +neq +add +sub +mul +div +neg +slt +ult +sle +ule +lod +sto +psh +pop +""".split() +mnems.extend(['???']*(64-len(mnems))) +def opws(kw): + for k in range(16): + mnems.append(kw + str(k)) +opws("mark") # who is mark +opws("loc") +opws("ret") +opws("lit") + +def dpc(addr): + print(f"{addr:04x} | ",end='') + +def uuu(b): + u=bin(b)[2:].zfill(16) + for x in range(0,len(u),4): + yield u[x:x+4] + +def fbin(b): + return '_'.join(uuu(b)) + +pc = 0 + +MASK_CALL = 0b1000_0000_0000_0000 +MASK_LIT = 0b0110_0000_0000_0000 +MASK_JMP = 0b0100_0000_0000_0000 +def maskeq(x, m): + # must be called in the right order + return (x&m)==m + +def main(): + while True: + global pc + bys = sys.stdin.buffer.read(2) + if len(bys) < 2: break + word = int.from_bytes(bys, 'big') + dpc(pc) + dpc(word) + if maskeq(word, MASK_CALL): + disasm_call(word) + elif maskeq(word, MASK_LIT): + disasm_lit(word) + elif maskeq(word, MASK_JMP): + disasm_br(word, pc) + else: + disasm_i(word) + pc += 2 + +def disasm_call(word): + addr = word & 0b0111_1111_1111_1111 + addr = addr << 1 + print(f"c {addr:04x}") +def disasm_lit(word): + val = word & 0b0001_1111_1111_1111 + print(f"l {val:04x}") +def disasm_br(word, pc): + is_cond = (word & 0b0001_0000_0000_0000) != 0 + char = 'b' if is_cond else 'j' + rel = (word & 0b0000_1111_1111_1111) - 2048 + target = rel + pc + print(f"{char} {rel:+05x} ={target:04x}") +def disasm_i(word): + opc1 = (word&0b0011_1111_1000_0000)>>7 + opc2 = (word&0b0000_0000_0111_1111) + mnem1 = mnems[opc1] + mnem2 = mnems[opc2] + if mnem2 == "nop": mnem2 = "" + print(f"i {mnem1} {mnem2}") + + +if __name__ == "__main__": + main() |