view python/target.py @ 218:494828a7adf1

added some sort of cache to assembler
author Windel Bouwman
date Fri, 05 Jul 2013 15:30:22 +0200
parents 6c6bf8890d8a
children 1fa3e0050b49
line wrap: on
line source

from asmnodes import ASymbol, AInstruction, ALabel, ANumber
from ppci import CompilerError

"""
  Base classes for defining a target
"""

# Machine code interface:
class Operand:
   """ Single machine operand """
   pass

# standard immediates:

class Imm8:
    def __init__(self, imm):
        assert imm < 256
        self.imm = imm

    @classmethod
    def Create(cls, vop):
        if type(vop) is ANumber and vop.number < 256:
            return cls(vop.number)
        
class Imm3:
    def __init__(self, imm):
        assert imm < 8
        assert type(imm) is int
        self.imm = imm

    @classmethod
    def Create(cls, vop):
        if type(vop) is ANumber and vop.number < 8:
            return cls(vop.number)

class Label:
    def __init__(self, name):
        self.name = name

    @classmethod
    def Create(cls, vop):
        if type(vop) is ASymbol:
            name = vop.name
            return cls(name)

class Register(Operand):
    def __init__(self, name):
        self.name = name

class Instruction:
    def encode(self):
        raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))

class Target:
    def __init__(self, name, desc=''):
        self.name = name
        self.desc = desc
        self.registers = []
        self.instructions = []

    def instruction(self, cls):
        """ Decorator function that registers an instruction to this target """
        self.addInstruction(cls)
        return cls

    def check(self):
        """ Check target """
        for i in self.instructions:
            assert hasattr(i, 'mnemonic')
            assert hasattr(i, 'operands'), str(i)
            assert type(i.mnemonic) is str
            assert type(i.operands) is tuple, str(i)

    def addInstruction(self, ins_class):
        self.instructions.append(ins_class)

    def mapOperand(self, operand):
        """ Try to map an operand to a target type """
        if type(operand) is ASymbol:
            # Try to map to register:
            regs = {}
            for r in self.registers:
                regs[r.name] = r
            if operand.name in regs:
                return regs[operand.name]
        raise CompilerError('Cannot map {0}'.format(operand))

    def mapInstruction(self, vi):
        assert type(vi) is AInstruction
        """ Map ast tree to real instruction for this target """

        # map to real operands:

        # look for a suitable instruction
        for ic in self.instructions:
            if ic.mnemonic == vi.mnemonic and len(ic.operands) == len(vi.operands):
                # Try to map operands to the correct operand types:
                rops = [roptype.Create(vop) for roptype, vop in zip(ic.operands, vi.operands)]

                # Check if we succeeded:
                optypes = tuple(map(type, rops))
                if ic.operands == optypes:
                    return ic(*rops)
        raise CompilerError('No suitable instruction found for "{0}"'.format(vi))