summaryrefslogtreecommitdiff
path: root/Asm.py
blob: 55baab1c243a32c802aa455fe28818a403a35d59 (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
#!/usr/bin/env python
"""Compiles C into assembly for the practicum processor (PP2)

Copyright (C) 2011-2014 Peter Wu <lekensteyn@gmail.com>
Licensed under the MIT license <http://opensource.org/licenses/MIT>.
"""

__author__ = "Peter Wu"
__copyright__ = "Copyright (C) 2011-2014 Peter Wu"
__credits__ = ["Peter Wu"]
__license__ = "MIT"
__version__ = "1.0"
__maintainer__ = "Peter Wu"
__email__ = "lekensteyn@gmail.com"

import re

class Asm(object):
    id_re = "[a-zA-Z_][0-9a-zA-Z_]*"
    re_identifier = re.compile("^" + id_re + "$")
    re_label = re.compile("^\s*" + id_re + "\s*:")
    # these instructions accept a label name
    operators_branch = ("BEQ", "BNE", "BCS", "BCC", "BLS", "BHI", "BVC", "BVS",
                        "BPL", "BMI", "BLT", "BGE", "BLE", "BGT", "BRA", "BRS")
    # these instructions are weird.
    operators_unary = ("JMP", "JSR", "CLRI", "SETI", "PSEM", "VSEM")
    # these instructions accept a register (arg 1) and addressing mode (arg 2)
    operators_binary = ("LOAD", "ADD", "SUB", "CMP", "MULS", "MULL", "CHCK",
                        "DIV", "MOD", "DVMD", "AND", "OR", "XOR", "STOR")
    # these operators accept a register
    operators_misc_reg = ("PUSH", "PULL")
    # these instructions accept no args
    operators_misc_noreg = ("RTS", "RTE")
    operators_misc = operators_misc_reg + operators_misc_noreg
    # all available operators
    operators_all = operators_branch + operators_unary + operators_binary
    operators_all += operators_misc
    def __init__(self):
        self.level = 0
    def is_identifier(self, text):
        return self.re_identifier.match(text) is not None
    def format_line(self, line, label="", indent_size=-1):
        """Returns an indented line optionally prefixed with label"""
        if indent_size < 0:
            indent_size = 8 + self.level * 4
        if label:
            indent_size -= len(label) + 2
            if indent_size >= 0:
                label += ": "
            else:
                label += ":"
        # strip the previous label and indentation
        line = self.re_label.sub("", line).rstrip("")
        # whitespace is generated if indent_size > 0
        indent = indent_size * " "
        return indent + label + line
    def binary_op(self, binop, reg, operand, label=""):
        # output format: BBBB RR OO...
        return self.format_line("{:<4} {:<2} {}".format(binop, reg, operand), label)
    def unary_op(self, unop, operand, label=""):
        # output format: UUUU OO...
        return self.format_line("{:<4} {}".format(unop, operand), label)
    def branch_op(self, brop, branch_label, label=""):
        # output format: BBB  LL...
        return self.format_line("{:<4} {}".format(brop, branch_label), label)
    def push(self, register, label=""):
        return self.format_line("PUSH " + register, label)
    def pull(self, register, label=""):
        return self.format_line("PULL " + register, label)
    def insert_label(self, instruction, label):
        new_instruction = instruction.lstrip(" ")
        indent_size = len(instruction) - len(new_instruction)
        return self.format_line(new_instruction, label, indent_size)
    def has_label(self, line):
        """Returns True if a line appears to contain a label, False otherwise"""
        return self.get_label(line) != ""
    def get_label(self, line):
        """Returns the label if any"""
        label = self.re_label.match(line)
        if label is None:
            return ""
        return label[0].strip(": ")
    def noop(self, label, register="R0"):
        """Returns a labelled no operation operator

        Note that the Zero, Negative and oVerflow flags are modified
        """
        return self.binary_op("LOAD", register, register, label) + " ; NOOP"