Mercurial > lcfOS
view python/outstream.py @ 320:84d67cce67b7
Working burg
author | Windel Bouwman |
---|---|
date | Sun, 19 Jan 2014 16:09:44 +0100 |
parents | 56e6ff84f646 |
children | 582a1aaa3983 |
line wrap: on
line source
import binascii from target import Instruction, Label, DebugInfo """ The output stream is a stream of instructions that can be output to a file or binary or hexfile. """ class Section: def __init__(self): self.address = 0 self.instructions = [] def emit(self, item): assert isinstance(item, Instruction) self.instructions.append(item) def to_bytes(self): d = bytearray() for i in self.instructions: addr = i.address insword = i.encode() assert type(insword) is bytes d.extend(insword) return bytes(d) @property def Size(self): return len(self.to_bytes()) def debugInfos(self): di = [i for i in self.instructions if isinstance(i, DebugInfo)] return di class OutputStream: def __init__(self): self.sections = {} self.currentSection = None def emit(self, item): assert self.currentSection self.currentSection.emit(item) def selectSection(self, sname): self.currentSection = self.getSection(sname) def getLabelAddress(self, lname): assert isinstance(lname, str) for s in self.sections.values(): for i in s.instructions: if type(i) is Label: if i.name == lname: return i.address return 0 def getSection(self, name): if not name in self.sections: self.sections[name] = Section() return self.sections[name] def backpatch(self): """ Fixup references to other parts in the assembler """ for s in self.sections.values(): address = s.address for i in s.instructions: i.address = address i.resolve(self.getLabelAddress) bts = i.encode() address += len(bts) class OutputStreamWriter: def __init__(self, extra_indent=''): self.extra_indent = extra_indent def dump(self, stream, f): stream.backpatch() stream.backpatch() for s in sorted(stream.sections.keys()): # print('.section '+ s) self.dumpSection(stream.sections[s], f) def dumpSection(self, s, f): for i in s.instructions: if type(i) is DebugInfo: continue addr = i.address insword = i.encode() assert type(insword) is bytes insword = binascii.hexlify(bytes(reversed(insword))).decode('ascii') asm = str(i) if len(insword) == 0: print(' {}'.format(asm), file=f) else: print(' 0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f) class TextOutputStream(OutputStream): pass class BinOutputStream(OutputStream): @property def Data(self): d = self.dump() return bytes(d) def dump(self): self.backpatch() self.backpatch() section = self.sections[list(self.sections.keys())[0]] return section.to_bytes()