-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathassembler.py
More file actions
55 lines (40 loc) · 1.59 KB
/
assembler.py
File metadata and controls
55 lines (40 loc) · 1.59 KB
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
from collections import defaultdict
from collections.abc import Iterable
from instructions import ImpliedInst, Instruction
from label import Label
from modes import Addr, Val
def _assemble_mode(mode: Addr | Val) -> Iterable[int]:
match mode:
case Val():
yield mode & 0xFF
case Addr():
yield mode & 0xFF
yield mode >> 8
type AnyInst = Instruction | ImpliedInst
def assemble(elem: list[AnyInst | Label], start: int = 0x0000) -> bytearray:
result = bytearray()
label_addresses: dict[Label, int] = {}
label_holes: dict[Label, set[int]] = defaultdict(set)
address = start
for elm in elem:
start_len = len(result)
match elm:
case Label() as lbl:
label_addresses[lbl] = address
case int() as inst:
result.append(inst)
case Instruction(opcode=opcode, mode=Label() as lbl):
result.append(opcode)
label_holes[lbl].add(address + 1)
result.extend((0x00, 0x00))
case Instruction(opcode=opcode, mode=Val() | Addr() as mode):
result.append(opcode)
result.extend(_assemble_mode(mode))
address += len(result) - start_len
for lbl, holes in label_holes.items():
assert lbl in label_addresses, f"Label {lbl} not found"
print(f"{lbl.name} = {Addr(label_addresses[lbl])}")
label_addr = tuple(_assemble_mode(mode=Addr(label_addresses[lbl])))
for addr in holes:
result[addr - start : addr - start + 2] = label_addr
return result