summaryrefslogtreecommitdiff
path: root/disasm.py
blob: 3ba5c2fc06bd129c7ee5a90d646fb4ac4387bcf3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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()