summaryrefslogtreecommitdiff
path: root/AsmLine.py
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2011-12-02 18:43:48 +0000
committerPeter Wu <lekensteyn@gmail.com>2011-12-02 18:43:48 +0000
commita6f9617bd891074bba20cc1fc220e60a226e7fb4 (patch)
treed5634a2db32c64275aa593d8a13ca066270c3ba9 /AsmLine.py
parent45f82a1acf465c8420690a578192cdabf4bc7c04 (diff)
downloadpp2cc-a6f9617bd891074bba20cc1fc220e60a226e7fb4.tar.gz
WIP for supporting ASM parsing and initialization of variables in @DATA
Diffstat (limited to 'AsmLine.py')
-rw-r--r--AsmLine.py114
1 files changed, 114 insertions, 0 deletions
diff --git a/AsmLine.py b/AsmLine.py
new file mode 100644
index 0000000..4561b30
--- /dev/null
+++ b/AsmLine.py
@@ -0,0 +1,114 @@
+#!/usr/bin/env python
+"""Compiles C into assembly for the practicum processor (PP2)
+
+All rights reserved, you may not redistribute or use this program without prior
+permission from Peter Wu or Xander Houtman. Use of this program is entirely
+your own risk. In no circumstances can the authors of this program be held
+responsible for any damage including, but not limited to, financial damage or
+data loss. Modification of this program is not allowed without prior
+permission. The generated output (assembly and messages) are not subject to
+this license.
+"""
+
+__author__ = "Peter Wu"
+__copyright__ = "Copyright 2011, Peter Wu"
+__credits__ = ["Peter Wu"]
+__license__ = "Proprietary"
+__version__ = "1.0"
+__maintainer__ = "Peter Wu"
+__email__ = "uwretep@gmail.com"
+
+import re
+from Asm import Asm
+from Registers import Registers
+from NamedId import NamedId
+
+class AsmLine(object):
+ asm = Asm()
+ registers = Registers()
+ re_whitespace = re.compile("\s+")
+ def __init__(self, line, id_dict=None):
+ # for storing NamedId objects
+ self.id_dict = id_dict
+ self.label = ""
+ self.register = ""
+ self.operand = ""
+ line = line.split(";", 1)[0].strip()
+
+ if ":" in line:
+ self.label, line = line.split(":", 1)
+ self.label = self.label.strip()
+ line = line.strip()
+ if self.asm.is_identifier(self.label):
+ # for easier label name manipulation
+ self.getNamedId(self.label)
+ else:
+ self.label = ""
+ line = label + ":" + line
+
+ parts = self.re_whitespace.split(line, 1)
+ instruction = parts[0]
+
+ if instruction in Asm.operators_binary:
+ # a label for sure
+ reg, operand = self.re_whitespace.split(parts[1], 1)
+ self.register = reg
+ self.setOperand(operand)
+ elif instruction in Asm.operators_branch:
+ # skip validation of reg for speed
+ self.register = parts[1]
+ elif instruction in Asm.operators_unary:
+ self.setOperand(parts[1])
+ elif instruction in Asm.operators_misc_reg:
+ self.register = parts[1]
+ elif instruction in Asm.operators_misc_noreg:
+ # no args
+ pass
+ else:
+ raise RuntimeError("Unknown instruction '{}'".format(instruction))
+ def setOperand(self, str):
+ """Sets the operand for this object either as a string or an identifier
+ object
+ """
+ if self.id_dict is None:
+ self.operand = str
+ elif self.registers.is_register(str):
+ # register
+ self.operand = [str]
+ else:
+ if str.startswith("["):
+ # split by [ ] and +, grouping multiple occurences
+ self.operand = re.split("([\[\]+]+)", str)
+ else:
+ # value
+ self.operand = [str]
+ for i, part in enumerate(self.operand):
+ # skip empty elements, registers and [ ] +
+ if (part and not self.registers.is_register(part) and
+ part[0] not in "[]+"):
+ # turn named items in an object for easier manipulation of
+ # the names later
+ # if performance is an issue, you may want to skip the name
+ # validity check on the cost of NamedIds pollution
+ if self.asm.is_identifier(part):
+ self.operand[i] = self.getNamedId(part)
+ def getNamedId(self, name):
+ """Returns an NamedId object for keeping a track of all names at once
+ """
+ # if there is no dictionary to store names, just return the name
+ if self.id_dict is None:
+ return name
+ if name not in self.id_dict:
+ self.id_dict[name] = NamedId(name)
+ return self.id_dict[name]
+ def __str__(self):
+ """Returns a line of assembly"""
+ line = ""
+ if self.label:
+ line += str(self.label) + ": "
+ line += self.instruction
+ if self.register:
+ line += " " + self.register
+ if self.operand:
+ # join all operand parts together
+ line += " " + "".join(str(elm) for elm in self.operand)