Mercurial > lcfOS
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)) +