Source code for m2isar.backends.disass.asm_formatter

# SPDX-License-Identifier: Apache-2.0
#
# This file is part of the M2-ISA-R project: https://github.com/tum-ei-eda/M2-ISA-R
#
# Copyright (C) 2022
# Chair of Electrical Design Automation
# Technical University of Munich

"""Fortmatter implementation for CoreDSL assembly strings."""

# Inspired by: https://stackoverflow.com/a/9558001

from string import Formatter

import re
import ast
import operator as op

[docs] operators = {ast.Add: op.add, ast.Sub: op.sub, ast.Mult: op.mul, ast.Div: op.truediv, ast.Pow: op.pow, ast.BitXor: op.xor, ast.USub: op.neg}
[docs] NAMES = { 0: "zero", 1: "ra", 2: "sp", 3: "gp", 4: "tp", 5: "t0", 6: "t1", 7: "t2", 8: "s0", 9: "s1", 10: "a0", 11: "a1", 12: "a2", 13: "a3", 14: "a4", 15: "a5", 16: "a6", 17: "a7", 18: "s2", 19: "s3", 20: "s4", 21: "s5", 22: "s6", 23: "s7", 24: "s8", 25: "s9", 26: "s10", 27: "s11", 28: "t3", 29: "t4", 30: "t5", 31: "t6", }
[docs] FNAMES = { 0: "f0", 1: "f1", 2: "f2", 3: "f3", 4: "f4", 5: "f5", 6: "f6", 7: "f7", 8: "fs0", 9: "fs1", 10: "fa0", 11: "fa1", 12: "fa2", 13: "fa3", 14: "fa4", 15: "fa5", 16: "fa6", 17: "fa7", 18: "fs2", 19: "fs3", 20: "fs4", 21: "fs5", 22: "fs6", 23: "fs7", 24: "fs8", 25: "fs9", 26: "fs10", 27: "fs11", 28: "ft8", 29: "ft9", 30: "ft10", 31: "ft11", }
[docs] class AsmFormatter(Formatter):
[docs] def get_value(self, key, args, kwargs): if isinstance(key, int): return key assert isinstance(key, str) try: value = self.eval_expr(key, args, kwargs) return value except ValueError: pass return super().get_value(key, args, kwargs)
[docs] def get_field(self, field_name, args, kwargs): return super().get_field(field_name, args, kwargs)
[docs] def eval_expr(self, expr, args, kwargs): return self.eval_(ast.parse(expr, mode='eval').body, args, kwargs)
[docs] def eval_(self, node, args, kwargs): if isinstance(node, ast.Num): # <number> return node.n elif isinstance(node, ast.Name): # <name> return super().get_value(node.id, args, kwargs) elif isinstance(node, ast.BinOp): # <left> <operator> <right> return operators[type(node.op)](self.eval_(node.left, args, kwargs), self.eval_(node.right, args, kwargs)) elif isinstance(node, ast.UnaryOp): # <operator> <operand> e.g., -1 return operators[type(node.op)](self.eval_(node.operand, args, kwargs)) elif isinstance(node, ast.Call): if node.func.id == "name": assert len(node.args) == 1 return NAMES[self.eval_(node.args[0], args, kwargs)] if node.func.id == "fname": assert len(node.args) == 1 return FNAMES[self.eval_(node.args[0], args, kwargs)] assert False else: raise TypeError(node)