view python/ppci/outstream.py @ 346:3bb7dcfe5529

expanded arm target
author Windel Bouwman
date Fri, 07 Mar 2014 17:05:32 +0100
parents 86b02c98a717
children 442fb043d149
line wrap: on
line source

import binascii
from ppci.target import Instruction, Alignment
from ppci.objectfile import ObjectFile

"""
 The output stream is a stream of instructions that can be output
 to a file or binary or hexfile.
"""


class OutputStream:
    def emit(self, item):
        raise NotImplementedError('Abstract base class')

    def selectSection(self, sname):
        raise NotImplementedError('Abstract base class')


class OutputStreamWriter:
    def __init__(self, extra_indent=''):
        self.extra_indent = extra_indent

    def dump(self, stream, f):
        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:
            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 BinaryOutputStream(OutputStream):
    """ Output stream that writes to object file """
    def __init__(self, obj_file):
        super().__init__()
        self.obj_file = obj_file

    def emit(self, item):
        """ Encode instruction and add symbol and relocation information """
        assert isinstance(item, Instruction), str(item) + str(type(item))
        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 selectSection(self, sname):
        self.currentSection = self.obj_file.get_section(sname)


class DummyOutputStream(OutputStream):
    def emit(self, item):
        pass

    def selectSection(self, sname):
        pass