Mercurial > lcfOS
view python/target.py @ 276:56d37ed4b4d2
phaa
author | Windel Bouwman |
---|---|
date | Mon, 16 Sep 2013 21:51:17 +0200 |
parents | 6f2423df0675 |
children | 046017431c6a |
line wrap: on
line source
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): 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 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: optypes = tuple(map(type, rops)) if ic.operands == optypes: return ic(*rops) raise CompilerError('No suitable instruction found for "{0}"'.format(vi))