Mercurial > lcfOS
diff python/outstream.py @ 335:582a1aaa3983
Added long branch format
author | Windel Bouwman |
---|---|
date | Mon, 17 Feb 2014 20:41:30 +0100 |
parents | 56e6ff84f646 |
children | b00219172a42 |
line wrap: on
line diff
--- a/python/outstream.py Thu Feb 13 22:02:08 2014 +0100 +++ b/python/outstream.py Mon Feb 17 20:41:30 2014 +0100 @@ -1,5 +1,6 @@ import binascii -from target import Instruction, Label, DebugInfo +from target import Instruction, DebugInfo, Alignment +from ppci.objectfile import ObjectFile """ The output stream is a stream of instructions that can be output @@ -7,76 +8,19 @@ """ -class Section: - def __init__(self): - self.address = 0 - self.instructions = [] - +class OutputStream: 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) + raise NotImplementedError('Abstract base class') 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 + raise NotImplementedError('Abstract base class') - 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) @@ -96,19 +40,30 @@ print(' 0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f) -class TextOutputStream(OutputStream): - pass - - -class BinOutputStream(OutputStream): +class BinaryOutputStream(OutputStream): + """ Output stream that writes to object file """ + def __init__(self, obj_file): + super().__init__() + self.obj_file = obj_file - @property - def Data(self): - d = self.dump() - return bytes(d) + def emit(self, item): + """ Encode instruction and add symbol and relocation information """ + assert isinstance(item, Instruction) + assert self.currentSection + section = self.currentSection + address = self.currentSection.Size + b = item.encode() + syms = item.symbols() + relocs = item.relocations() + section.add_data(b) + for sym in syms: + self.obj_file.add_symbol(sym, address, section.name) + for sym, typ in relocs: + self.obj_file.add_relocation(sym, address, typ, section.name) + # Special case for align, TODO do this different? + if type(item) is Alignment: + while section.Size % item.align != 0: + section.add_data(bytes([0])) - def dump(self): - self.backpatch() - self.backpatch() - section = self.sections[list(self.sections.keys())[0]] - return section.to_bytes() + def selectSection(self, sname): + self.currentSection = self.obj_file.get_section(sname)