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)