summaryrefslogtreecommitdiffstats
path: root/lab1asm.py
blob: 6f09bffe7883ff17b7ca5e700cbae8faa6344aa8 (plain) (blame)
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
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


if __name__ == "__main__":
    prog, labels = compile([line.strip() for line in sys.stdin])
    print("prog:")
    print("\n".join(prog))
    print()
    print("labels:")
    for label, label_nr in labels.items():
        print(label, hex(label_nr))