From d48fb25678e10c79bf8971892b8573fb7cb9e247 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 2 Dec 2011 20:28:29 +0000 Subject: Use DW instead of DS, add ASM source, fix some coding errors --- AsmLine.py | 15 ++++++++------- AsmParser.py | 9 ++++++--- Variables.py | 5 ++++- pp2cc.py | 24 +++++++++++++++++++----- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/AsmLine.py b/AsmLine.py index 4561b30..5a5249f 100644 --- a/AsmLine.py +++ b/AsmLine.py @@ -47,25 +47,25 @@ class AsmLine(object): line = label + ":" + line parts = self.re_whitespace.split(line, 1) - instruction = parts[0] + self.instruction = parts[0] - if instruction in Asm.operators_binary: + if self.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: + elif self.instruction in Asm.operators_branch: # skip validation of reg for speed self.register = parts[1] - elif instruction in Asm.operators_unary: + elif self.instruction in Asm.operators_unary: self.setOperand(parts[1]) - elif instruction in Asm.operators_misc_reg: + elif self.instruction in Asm.operators_misc_reg: self.register = parts[1] - elif instruction in Asm.operators_misc_noreg: + elif self.instruction in Asm.operators_misc_noreg: # no args pass else: - raise RuntimeError("Unknown instruction '{}'".format(instruction)) + raise RuntimeError("Unknown instruction '{}'".format(self.instruction)) def setOperand(self, str): """Sets the operand for this object either as a string or an identifier object @@ -112,3 +112,4 @@ class AsmLine(object): if self.operand: # join all operand parts together line += " " + "".join(str(elm) for elm in self.operand) + return line diff --git a/AsmParser.py b/AsmParser.py index 4ab25ed..24755f6 100644 --- a/AsmParser.py +++ b/AsmParser.py @@ -29,7 +29,7 @@ class AsmParser(object): self.defined_names = parent.defined_names else: self.parent = None - self.data = [] + self.data = {} self.code = [] # defined labels for the assembly files self.labels = [] @@ -99,7 +99,7 @@ class AsmParser(object): if what == "DS": # DS initializes names with zero, let's convert it to # DW to make it compatible with the Parser - self.addData(name, [0 for x in range(0, int(data))]) + self.addData(name, ["0"] * int(data)) else: self.addData(name, data.split(",")) line = "" @@ -166,4 +166,7 @@ class AsmParser(object): if self.parent: raise RuntimeError("You can only get the lines for @CODE from the" " root node") - return [elm for elm in self.code] + return [str(elm) for elm in self.code] + def getDataDefinitions(self): + """Returns the data section as a dictionary""" + return self.data \ No newline at end of file diff --git a/Variables.py b/Variables.py index bab1a34..b84d0ad 100644 --- a/Variables.py +++ b/Variables.py @@ -118,4 +118,7 @@ class GlobalVariables(Variables): # global variables are prefixed "var_" var_name = self._uniqName("var_" + name) self.global_vars[name] = var_name - self.defined_names[var_name] = size + if var_name not in self.defined_names: + self.defined_names[var_name] = [] + # insert size items, initialized with 0 + self.defined_names[var_name] += ["0"] * size diff --git a/pp2cc.py b/pp2cc.py index ffe9ee4..d3aac94 100755 --- a/pp2cc.py +++ b/pp2cc.py @@ -80,7 +80,8 @@ class Parse(object): self.binary_ops.update(self.comparison_ops) self.binary_ops.update(self.shift_ops) - # local and global variable names to be defined in @DATA + # global variable names to be defined in @DATA. key: name, value: list + # of initializers self.varNames = {} self.functions = {} # holds instructions for initializing the global variables @@ -158,16 +159,29 @@ class Parse(object): new_label = self.uniqLbl(label) self.asm_node.renameId(label, new_label) self.labels.add(new_label) + for name, init_vals in self.asm_node.getDataDefinitions().iteritems(): + if name in self.varNames: + old_count = len(self.varNames[name]) + new_count = len(init_vals) + if old_count != new_count: + self.logger.error("Global variable '{}' was defined before" + ", but the length of the initializers" + " are not equal. Old: {}, new: {}" + .format(name, old_count, new_count)) + elif self.varNames[name] != init_vals: + self.logger.warning("The initialization of global variable" + " '{}' contains different values" + .format(name)) + self.varNames[name] = init_vals self.codeSegment += self.asm_node.getCodeLines() def getSource(self): """Retrieves the ASM source. You need to compile it first""" output = [] output.append("@DATA") - for varName, size in self.varNames.iteritems(): + for varName, initializers in self.varNames.iteritems(): padding = " " * (16 - len(varName) - 1) - assert size > 0, "Size of '{}' must be at least 1".format(varName) - initializers = "0,".repeat(size)[0:-1] - output.append(varName + padding + " DW " + initializers) + assert len(initializers) > 0, "Size of '{}' must be at least 1".format(varName) + output.append(varName + padding + " DW " + ",".join(initializers)) output.append("") output.append("@CODE") # initialization of global variables -- cgit v1.2.1