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
|
import sys
OPS = {
"load": 0,
"store": 1,
"add": 2,
"sub": 3,
"and": 4,
"lsr": 5,
"bra": 6,
"bne": 7,
"halt": 8,
"cmp": 9,
"bge": 10,
"beq": 11,
}
def compile(lines):
addr = 0
labels = {}
compiled = []
for line in lines:
if not line:
# empty line, ignore
continue
if line.startswith(";"):
# comment
continue
if line.endswith(":"):
# label
labels[line.split(":")[0]] = addr
continue
match line.split(" "):
case [inst, gr, m, *adr]:
if int(m) == 1:
assert adr == []
compiled.append("{:02x}: {:01x}{:01x}{:02x}".format(
addr,
OPS[inst],
int(gr) * 4 + int(m),
int(adr[0], 16) if int(m) != 1 else 0,
))
case [inst, label]:
assert inst in ("bra", "bne", "bge", "beq")
compiled.append("{:02x}: {:01x}000".format(
addr,
OPS[inst],
))
addr += 1
compiled.append("{:02x}: <{}>".format(
addr,
label
))
case ["halt"]:
compiled.append("{:02x}: {:01x}000".format(addr, OPS["halt"]))
case [oper]:
compiled.append("{:02x}: {:04x}".format(addr, int(oper, 16)))
case _:
compiled.append(" !!!", line)
continue
addr += 1
linked = []
for line_nr, line in enumerate(compiled):
for label, label_nr in labels.items():
line = line.replace(f"<{label}>", f"{label_nr - line_nr:04x}")
linked.append(line)
return linked, labels
def write(prog, labels):
prog_pad = 0x100 - len(prog)
prog = "\n".join(prog + [f"{len(prog)+n:02x}: 0000" for n in range(prog_pad)])
print("PM:")
print(prog)
if __name__ == "__main__":
write(*compile([line.strip() for line in sys.stdin]))
|