+*.bin
*.xml
__pycache__
/element.py
--- /dev/null
+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('<f', float(value)))
+ else:
+ assert False
+ context.dot += self.size
+t_def.method(t_def.DotSpace)
+def assemble(self, context):
+ value = self.children[0].evaluate(context)
+ assert isinstance(value, t_def.ValueInt)
+ space = value.value
+ assert space >= 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('<f', float(value)))
+ else:
+ assert False
+ context.dot += self.size
--- /dev/null
+import gmpy2
+import t_def
+
+gmpy2.get_context().precision = 128
+mpfr_0 = gmpy2.mpfr('0')
+
+def to_bool(value):
+ if isinstance(value, t_def.ValueInt):
+ return value.value != 0
+ if isinstance(value, t_def.ValueFloat):
+ return value.value != mpfr_0
+ assert False
+
+@t_def.method(t_def.Expression)
+def evaluate(self, context):
+ print(self)
+ raise NotImplementedError()
+@t_def.method(t_def.ExpressionUnary)
+def evaluate(self, context):
+ value = self.children[0].evaluate(context)
+ if isinstance(value, t_def.ValueInt):
+ return self.operate_int(value.value)
+ if isinstance(value, t_def.ValueFloat):
+ return self.operate_float(value.value)
+ assert False
+@t_def.method(t_def.ExpressionLogicalNot)
+def evaluate(self, context):
+ return t_def.ValueInt(
+ value = int(not to_bool(self.children[0].evaluate(context)))
+ )
+@t_def.method(t_def.ExpressionBinary)
+def evaluate(self, context):
+ value0 = self.children[0].evaluate(context)
+ value1 = self.children[1].evaluate(context)
+ if isinstance(value0, t_def.ValueInt):
+ if isinstance(value1, t_def.ValueInt):
+ return self.operate_int(value0.value, value1.value)
+ if isinstance(value1, t_def.ValueFloat):
+ return self.operate_float(gmpy2.mpfr(value0.value), value1.value)
+ assert False
+ if isinstance(value0, t_def.ValueFloat):
+ if isinstance(value1, t_def.ValueInt):
+ return self.operate_float(value0.value, gmpy2.mpfr(value1.value))
+ if isinstance(value1, t_def.ValueFloat):
+ return self.operate_float(value0.value, value1.value)
+ assert False
+ assert False
+@t_def.method(t_def.ExpressionLogicalOr)
+def evaluate(self, context):
+ return t_def.ValueInt(
+ value = int(
+ to_bool(self.children[0].evaluate(context)) or
+ to_bool(self.children[1].evaluate(context))
+ )
+ )
+@t_def.method(t_def.ExpressionLogicalAnd)
+def evaluate(self, context):
+ return t_def.ValueInt(
+ value = int(
+ to_bool(self.children[0].evaluate(context)) and
+ to_bool(self.children[1].evaluate(context))
+ )
+ )
+@t_def.method(t_def.ExpressionCharacterConstant)
+def evaluate(self, context):
+ value = 0
+ for i in self.children:
+ if isinstance(i, t_def.Text):
+ for j in i.text[0]:
+ value = (value << 8) | (ord(j) & 0xff)
+ elif isinstance(i, t_def.SimpleEscapeSequence):
+ value = (value << 8) | (i.value & 0xff)
+ elif isinstance(i, t_def.IntegerEscapeSequence):
+ value = (value << 8) | (int(i.children[0].text[0], i.base) & 0xff)
+ else:
+ assert False
+ return t_def.ValueInt(value = value)
+@t_def.method(t_def.ExpressionConditional)
+def evaluate(self, context):
+ return self.children[
+ 1 if to_bool(self.children[0].evaluate(context)) else 2
+ ].evaluate(context)
+@t_def.method(t_def.ExpressionFloatingConstant)
+def evaluate(self, context):
+ digits0 = self.children[0].text[0]
+ digits1 = self.children[1].text[0]
+ exponent_part = self.children[2]
+ exponent = (
+ 0
+ if len(exponent_part.children) == 0 else
+ exponent_part.children[0].value * int(exponent_part.children[1].text[0])
+ )
+ return t_def.ValueFloat(
+ value = int(digits0 + digits1) * gmpy2.exp10(exponent - len(digits1))
+ )
+@t_def.method(t_def.ExpressionIdentifier)
+def evaluate(self, context):
+ if context._pass == 0:
+ return t_def.ValueInt(value = context.dot)
+ symbol = self.text[0]
+ return context.symbols[symbol]
+@t_def.method(t_def.ExpressionIntegerConstant)
+def evaluate(self, context):
+ return t_def.ValueInt(value = int(self.children[0].text[0], self.base))
+@t_def.method(t_def.ExpressionStringLiteral)
+def evaluate(self, context):
+ values = []
+ for i in self.children:
+ if isinstance(i, t_def.Text):
+ values.extend([ord(j) & 0xff for j in i.text[0]])
+ elif isinstance(i, t_def.SimpleEscapeSequence):
+ values.append(i.value & 0xff)
+ elif isinstance(i, t_def.IntegerEscapeSequence):
+ values.append(int(i.children[0].text[0], i.base) & 0xff)
+ else:
+ assert False
+ return t_def.ValueString(values = values)
+del evaluate
--- /dev/null
+import gmpy2
+import t_def
+
+@t_def.method(t_def.ExpressionUnary)
+def operate_int(self, value):
+ print(self)
+ raise NotImplementedError()
+@t_def.method(t_def.ExpressionBitwiseNot)
+def operate_int(self, value):
+ return t_def.ValueInt(value = ~value)
+@t_def.method(t_def.ExpressionMinus)
+def operate_int(self, value):
+ return t_def.ValueInt(value = -value)
+@t_def.method(t_def.ExpressionPlus)
+def operate_int(self, value):
+ return t_def.ValueInt(value = value)
+del operate_int
+
+@t_def.method(t_def.ExpressionUnary)
+def operate_float(self, value):
+ print(self)
+ raise NotImplementedError()
+@t_def.method(t_def.ExpressionMinus)
+def operate_float(self, value):
+ return t_def.ValueInt(value = -value)
+@t_def.method(t_def.ExpressionPlus)
+def operate_float(self, value):
+ return t_def.ValueInt(value = value)
+del operate_float
+
+@t_def.method(t_def.ExpressionBinary)
+def operate_int(self, value0, value1):
+ print(self)
+ raise NotImplementedError()
+@t_def.method(t_def.ExpressionAdd)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 + value1)
+@t_def.method(t_def.ExpressionBitwiseAnd)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 & value1)
+@t_def.method(t_def.ExpressionBitwiseOr)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 | value1)
+@t_def.method(t_def.ExpressionDivide)
+def operate_int(self, value0, value1):
+ sign0 = -1 if value0 < 0 else 1
+ sign1 = -1 if value1 < 0 else 1
+ return t_def.ValueInt(value = sign0 * sign1 * (abs(value0) // abs(value1)))
+@t_def.method(t_def.ExpressionExclusiveOr)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 ^ value1)
+@t_def.method(t_def.ExpressionModulo)
+def operate_int(self, value0, value1):
+ sign0 = -1 if value0 < 0 else 1
+ return t_def.ValueInt(value = sign0 * (abs(value0) % abs(value1)))
+@t_def.method(t_def.ExpressionMultiply)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 * value1)
+@t_def.method(t_def.ExpressionShiftLeft)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 << value1 & 0xff)
+@t_def.method(t_def.ExpressionShiftRight)
+def operate_int(self, value0, value1):
+ return t_def.ValueInt(value = value0 >> 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
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
#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')
/*
* 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 */
class ExpressionPlus: ExpressionUnary;
class ExpressionShiftLeft: ExpressionBinary;
class ExpressionShiftRight: ExpressionBinary;
+class ExpressionStringLiteral: Expression {
+ bool wide;
+};
class ExpressionSubtract: ExpressionBinary;
class Identifier: Node;
class Label: InputLine;
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