From: Nick Downing Date: Mon, 22 Jan 2024 12:54:39 +0000 (+1100) Subject: First cut at assembly passes, expressions, symbol table and binary output X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=f2c3a8601c1c694ff6d92777f5f6c5fa9e375bda;p=c_vm.git First cut at assembly passes, expressions, symbol table and binary output --- diff --git a/.gitignore b/.gitignore index 3a1c769..1f455da 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.bin *.xml __pycache__ /element.py diff --git a/assemble.py b/assemble.py new file mode 100644 index 0000000..40ae083 --- /dev/null +++ b/assemble.py @@ -0,0 +1,114 @@ +import gmpy2 +import struct +import t_def + +gmpy2.get_context().precision = 128 + +sizes = {1, 2, 4, 8, 16} + +@t_def.method(t_def.Node) +def assemble(self, context): + for i in self.children: + i.assemble(context) +@t_def.method(t_def.Label) +def assemble(self, context): + symbol = self.children[0].text[0] + if ( + symbol not in context.symbols or + not isinstance(context.symbols[symbol], t_def.ValueInt) or + context.symbols[symbol].value != context.dot + ): + context.modified = True + context.symbols[symbol] = t_def.ValueInt(value = context.dot) +@t_def.method(t_def.Equate) +def assemble(self, context): + symbol = self.children[0].text[0] + context.symbols[symbol] = self.children[1].evaluate(context) +@t_def.method(t_def.DotAlign) +def assemble(self, context): + value = self.children[0].evaluate(context) + assert isinstance(value, t_def.ValueInt) + align = value.value + assert align in sizes + pad = -context.dot & (align - 1) + if context._pass: + context.fbin.write(bytes([0] * pad)) + context.dot += pad +@t_def.method(t_def.DotData) +def assemble(self, context): + value = self.children[0].evaluate(context) + pad = -context.dot & (self.size - 1) + if context._pass: + context.fbin.write(bytes([0] * pad)) + context.dot += pad + value = self.children[0].evaluate(context) + if self.type == t_def.TYPE_INT or self.type == t_def.TYPE_PCR: + if isinstance(value, t_def.ValueInt): + value = value.value + else: + assert False + if self.type == t_def.TYPE_PCR: + self.value -= context.dot - self.size + if context._pass: + context.fbin.write( + bytes([(value >> (i << 3)) & 0xff for i in range(self.size)]) + ) + elif self.type == t_def.TYPE_FLOAT: + if isinstance(value, t_def.ValueInt): + value = gmpy2.mpfr(value.value) + elif isinstance(value, t_def.ValueFloat): + value = value.value + else: + assert False + assert self.size == 4 # for now + if context._pass: + context.fbin.write(struct.pack('= 0 + if context._pass: + context.fbin.write(bytes([0] * space)) + context.dot += space +@t_def.method(t_def.Op) +def assemble(self, context): + if context._pass: + context.fbin.write(bytes([self.op])) + context.dot += 1 +@t_def.method(t_def.OpData) +def assemble(self, context): + t_def.Op.assemble(self, context) + pad = -context.dot & (self.size - 1) + if context._pass: + context.fbin.write(bytes([0] * pad)) + context.dot += pad + value = self.children[0].evaluate(context) + if self.type == t_def.TYPE_INT or self.type == t_def.TYPE_PCR: + if isinstance(value, t_def.ValueInt): + value = value.value + else: + assert False + if self.type == t_def.TYPE_PCR: + value -= context.dot - self.size + if context._pass: + context.fbin.write( + bytes([(value >> (i << 3)) & 0xff for i in range(self.size)]) + ) + elif self.type == t_def.TYPE_FLOAT: + if isinstance(value, t_def.ValueInt): + value = gmpy2.mpfr(value.value) + elif isinstance(value, t_def.ValueFloat): + value = value.value + else: + assert False + assert self.size == 4 # for now + if context._pass: + context.fbin.write(struct.pack('> value1 & 0xff) +@t_def.method(t_def.ExpressionSubtract) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = value0 - value1) +@t_def.method(t_def.ExpressionEqual) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 == value1)) +@t_def.method(t_def.ExpressionGreaterThan) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 > value1)) +@t_def.method(t_def.ExpressionGreaterThanOrEqual) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 >= value1)) +@t_def.method(t_def.ExpressionLessThan) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 < value1)) +@t_def.method(t_def.ExpressionLessThanOrEqual) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 <= value1)) +@t_def.method(t_def.ExpressionNotEqual) +def operate_int(self, value0, value1): + return t_def.ValueInt(value = int(value0 != value1)) +del operate_int + +@t_def.method(t_def.ExpressionBinary) +def operate_float(self, value0, value1): + print(self) + raise NotImplementedError() +@t_def.method(t_def.ExpressionAdd) +def operate_float(self, value0, value1): + return t_def.ValueFloat(value = value0 + value1) +@t_def.method(t_def.ExpressionDivide) +def operate_float(self, value0, value1): + return t_def.ValueFloat(value = value0 / value1) +@t_def.method(t_def.ExpressionMultiply) +def operate_float(self, value0, value1): + return t_def.ValueFloat(value = value0 * value1) +@t_def.method(t_def.ExpressionSubtract) +def operate_float(self, value0, value1): + return t_def.ValueFloat(value = value0 - value1) +@t_def.method(t_def.ExpressionEqual) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 == value1)) +@t_def.method(t_def.ExpressionGreaterThan) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 > value1)) +@t_def.method(t_def.ExpressionGreaterThanOrEqual) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 >= value1)) +@t_def.method(t_def.ExpressionLessThan) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 < value1)) +@t_def.method(t_def.ExpressionLessThanOrEqual) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 <= value1)) +@t_def.method(t_def.ExpressionNotEqual) +def operate_float(self, value0, value1): + return t_def.ValueInt(value = int(value0 != value1)) +del operate_float diff --git a/vm_asm.py b/vm_asm.py index 2c0bdfd..c33d2d2 100755 --- a/vm_asm.py +++ b/vm_asm.py @@ -22,6 +22,11 @@ import sys import t_def import y_tab +# by importing these we make sure they run, to add methods onto t_def classes +import assemble +import evaluate +import operate + EXIT_SUCCESS = 0 EXIT_FAILURE = 1 @@ -29,16 +34,36 @@ EXIT_FAILURE = 1 #print('yytext', f'"{lex_yy.yytext:s}"') #assert False -if len(sys.argv) < 2: - print(f'usage: {sys.argv[0]:s} in_file.asm') +if len(sys.argv) < 3: + print(f'usage: {sys.argv[0]:s} in_file.asm out_file.bin') sys.exit(EXIT_FAILURE) in_file_asm = sys.argv[1] +out_file_bin = sys.argv[2] with open(in_file_asm) as fin: lex_yy.yyin = fin y_tab.in_file = in_file_asm - expression = y_tab.yyparse(t_def.InputFile) -expression.post_process(t_def.Context()) -element.serialize(expression, 'a.xml', 'utf-8') -expression = element.deserialize('a.xml', t_def.factory, 'utf-8') -element.serialize(expression, 'b.xml', 'utf-8') + input_file = y_tab.yyparse(t_def.InputFile) + +context = t_def.Context() +while True: + print('pass', context._pass) + + prev_dot = context.dot + context.dot = 0 + context.modified = False + + if context._pass: + context.fbin = open(out_file_bin, 'wb') + input_file.assemble(context) + if context._pass: + context.fbin.close() + + if not context.modified and context.dot == prev_dot: + break + + context._pass += 1 + +element.serialize(input_file, 'a.xml', 'utf-8') +input_file = element.deserialize('a.xml', t_def.factory, 'utf-8') +element.serialize(input_file, 'b.xml', 'utf-8') diff --git a/vm_asm.t b/vm_asm.t index 683a646..3de6eac 100644 --- a/vm_asm.t +++ b/vm_asm.t @@ -479,7 +479,7 @@ class ValueExtern: Value { /* * all of the following classes can appear as children or indirect children * of the InputFile (root) node, and have Node as a superclass so that - * the post_process() routine can effortlessly recurse through all children + * the assemble() routine can effortlessly recurse through all children */ /* internal */ @@ -534,6 +534,9 @@ class ExpressionNotEqual: ExpressionBinary; class ExpressionPlus: ExpressionUnary; class ExpressionShiftLeft: ExpressionBinary; class ExpressionShiftRight: ExpressionBinary; +class ExpressionStringLiteral: Expression { + bool wide; +}; class ExpressionSubtract: ExpressionBinary; class Identifier: Node; class Label: InputLine; @@ -559,8 +562,16 @@ def factory(tag, *args, **kwargs): return tag_to_class[tag](*args, **kwargs) class Context: - pass - -@method(Node) -def post_process(self, context): - pass + def __init__( + self, + _pass = 0, + modified = False, + dot = 0, + symbols = None, + fbin = None + ): + self._pass = _pass + self.modified = modified + self.dot = dot + self.symbols = {} if symbols is None else symbols + self.fbin = fbin