diff python/target/basetarget.py @ 290:7b38782ed496

File moves
author Windel Bouwman
date Sun, 24 Nov 2013 11:24:15 +0100
parents python/target.py@02385f62f250
children 534b94b40aa8
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/target/basetarget.py	Sun Nov 24 11:24:15 2013 +0100
@@ -0,0 +1,198 @@
+from asmnodes import ASymbol, AInstruction, 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 Imm7:
+    def __init__(self, imm):
+        assert imm < 128
+        self.imm = imm
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ANumber and vop.number < 128:
+            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 Imm32:
+    def __init__(self, imm):
+        assert imm < 2**32
+        assert type(imm) is int
+        self.imm = imm
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ANumber and vop.number < 2**32:
+            return cls(vop.number)
+
+
+class LabelRef:
+    def __init__(self, name):
+        assert type(name) is str
+        self.name = name
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            return cls(vop.name)
+
+class Instruction:
+    def encode(self):
+        raise NotImplementedError('Instruction {0} has no encode yet, TODO'.format(type(self)))
+    def resolve(self, f):
+        pass
+
+
+class Nop(Instruction):
+    """ Instruction that does nothing and has zero size """
+    def encode(self):
+        return bytes()
+
+    
+
+class PseudoInstruction(Instruction):
+    pass
+
+
+class Label(PseudoInstruction):
+    def __init__(self, name):
+        self.name = name
+        self.address = 0
+
+    def __repr__(self):
+        return '{}:'.format(self.name)
+
+    def encode(self):
+        return bytes()
+
+    @classmethod
+    def Create(cls, vop):
+        if type(vop) is ASymbol:
+            name = vop.name
+            return cls(name)
+
+
+class Comment(PseudoInstruction):
+    def __init__(self, txt):
+        self.txt = txt
+
+    def encode(self):
+        return bytes()
+
+    def __repr__(self):
+        return '; {}'.format(self.txt)
+
+
+class Alignment(PseudoInstruction):
+    def __init__(self, a):
+        self.align = a
+
+    def __repr__(self):
+        return 'ALIGN({})'.format(self.align)
+
+    def encode(self):
+        pad = []
+        address = self.address
+        while (address % self.align) != 0:
+            address += 1
+            pad.append(0)
+        return bytes(pad)
+
+class DebugInfo(PseudoInstruction):
+    def __init__(self, i):
+        self.info = i
+
+    def __repr__(self):
+        return 'DebugInfo: {}'.format(self.info)
+
+    def encode(self):
+        return bytes()
+
+class Register(Operand):
+    def __init__(self, name):
+        self.name = name
+
+
+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:
+        if vi.mnemonic.upper() == 'ALIGN' and len(vi.operands) == 1:
+            if type(vi.operands[0]) == ANumber:
+                return Alignment(vi.operands[0].number)
+
+        # look for a suitable instruction
+        for ic in self.instructions:
+            if ic.mnemonic.upper() == vi.mnemonic.upper() 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:
+                if all(isinstance(rop, optype) for rop, optype in zip(rops, ic.operands)):
+                    return ic(*rops)
+        raise CompilerError('No suitable instruction found for "{0}"'.format(vi))
+