comparison 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
comparison
equal deleted inserted replaced
334:6f4753202b9a 335:582a1aaa3983
1 import binascii 1 import binascii
2 from target import Instruction, Label, DebugInfo 2 from target import Instruction, DebugInfo, Alignment
3 from ppci.objectfile import ObjectFile
3 4
4 """ 5 """
5 The output stream is a stream of instructions that can be output 6 The output stream is a stream of instructions that can be output
6 to a file or binary or hexfile. 7 to a file or binary or hexfile.
7 """ 8 """
8 9
9 10
10 class Section: 11 class OutputStream:
11 def __init__(self):
12 self.address = 0
13 self.instructions = []
14
15 def emit(self, item): 12 def emit(self, item):
16 assert isinstance(item, Instruction) 13 raise NotImplementedError('Abstract base class')
17 self.instructions.append(item)
18
19 def to_bytes(self):
20 d = bytearray()
21 for i in self.instructions:
22 addr = i.address
23 insword = i.encode()
24 assert type(insword) is bytes
25 d.extend(insword)
26 return bytes(d)
27
28 @property
29 def Size(self):
30 return len(self.to_bytes())
31
32 def debugInfos(self):
33 di = [i for i in self.instructions if isinstance(i, DebugInfo)]
34 return di
35
36
37 class OutputStream:
38 def __init__(self):
39 self.sections = {}
40 self.currentSection = None
41
42 def emit(self, item):
43 assert self.currentSection
44 self.currentSection.emit(item)
45 14
46 def selectSection(self, sname): 15 def selectSection(self, sname):
47 self.currentSection = self.getSection(sname) 16 raise NotImplementedError('Abstract base class')
48 17
49 def getLabelAddress(self, lname):
50 assert isinstance(lname, str)
51 for s in self.sections.values():
52 for i in s.instructions:
53 if type(i) is Label:
54 if i.name == lname:
55 return i.address
56 return 0
57
58 def getSection(self, name):
59 if not name in self.sections:
60 self.sections[name] = Section()
61 return self.sections[name]
62
63 def backpatch(self):
64 """ Fixup references to other parts in the assembler """
65 for s in self.sections.values():
66 address = s.address
67 for i in s.instructions:
68 i.address = address
69 i.resolve(self.getLabelAddress)
70 bts = i.encode()
71 address += len(bts)
72 18
73 class OutputStreamWriter: 19 class OutputStreamWriter:
74 def __init__(self, extra_indent=''): 20 def __init__(self, extra_indent=''):
75 self.extra_indent = extra_indent 21 self.extra_indent = extra_indent
76 22
77 def dump(self, stream, f): 23 def dump(self, stream, f):
78 stream.backpatch()
79 stream.backpatch()
80 for s in sorted(stream.sections.keys()): 24 for s in sorted(stream.sections.keys()):
81 # print('.section '+ s) 25 # print('.section '+ s)
82 self.dumpSection(stream.sections[s], f) 26 self.dumpSection(stream.sections[s], f)
83 27
84 def dumpSection(self, s, f): 28 def dumpSection(self, s, f):
94 print(' {}'.format(asm), file=f) 38 print(' {}'.format(asm), file=f)
95 else: 39 else:
96 print(' 0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f) 40 print(' 0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f)
97 41
98 42
99 class TextOutputStream(OutputStream): 43 class BinaryOutputStream(OutputStream):
100 pass 44 """ Output stream that writes to object file """
45 def __init__(self, obj_file):
46 super().__init__()
47 self.obj_file = obj_file
101 48
49 def emit(self, item):
50 """ Encode instruction and add symbol and relocation information """
51 assert isinstance(item, Instruction)
52 assert self.currentSection
53 section = self.currentSection
54 address = self.currentSection.Size
55 b = item.encode()
56 syms = item.symbols()
57 relocs = item.relocations()
58 section.add_data(b)
59 for sym in syms:
60 self.obj_file.add_symbol(sym, address, section.name)
61 for sym, typ in relocs:
62 self.obj_file.add_relocation(sym, address, typ, section.name)
63 # Special case for align, TODO do this different?
64 if type(item) is Alignment:
65 while section.Size % item.align != 0:
66 section.add_data(bytes([0]))
102 67
103 class BinOutputStream(OutputStream): 68 def selectSection(self, sname):
104 69 self.currentSection = self.obj_file.get_section(sname)
105 @property
106 def Data(self):
107 d = self.dump()
108 return bytes(d)
109
110 def dump(self):
111 self.backpatch()
112 self.backpatch()
113 section = self.sections[list(self.sections.keys())[0]]
114 return section.to_bytes()