208
|
1 import binascii
|
335
|
2 from target import Instruction, DebugInfo, Alignment
|
|
3 from ppci.objectfile import ObjectFile
|
234
|
4
|
208
|
5 """
|
|
6 The output stream is a stream of instructions that can be output
|
|
7 to a file or binary or hexfile.
|
|
8 """
|
|
9
|
219
|
10
|
335
|
11 class OutputStream:
|
237
|
12 def emit(self, item):
|
335
|
13 raise NotImplementedError('Abstract base class')
|
219
|
14
|
250
|
15 def selectSection(self, sname):
|
335
|
16 raise NotImplementedError('Abstract base class')
|
234
|
17
|
208
|
18
|
316
|
19 class OutputStreamWriter:
|
|
20 def __init__(self, extra_indent=''):
|
|
21 self.extra_indent = extra_indent
|
208
|
22
|
316
|
23 def dump(self, stream, f):
|
|
24 for s in sorted(stream.sections.keys()):
|
|
25 # print('.section '+ s)
|
|
26 self.dumpSection(stream.sections[s], f)
|
|
27
|
|
28 def dumpSection(self, s, f):
|
|
29 for i in s.instructions:
|
259
|
30 if type(i) is DebugInfo:
|
|
31 continue
|
234
|
32 addr = i.address
|
|
33 insword = i.encode()
|
|
34 assert type(insword) is bytes
|
|
35 insword = binascii.hexlify(bytes(reversed(insword))).decode('ascii')
|
|
36 asm = str(i)
|
235
|
37 if len(insword) == 0:
|
316
|
38 print(' {}'.format(asm), file=f)
|
235
|
39 else:
|
316
|
40 print(' 0x{0:08x} 0x{1} {2}'.format(addr, insword, asm), file=f)
|
208
|
41
|
296
|
42
|
335
|
43 class BinaryOutputStream(OutputStream):
|
|
44 """ Output stream that writes to object file """
|
|
45 def __init__(self, obj_file):
|
|
46 super().__init__()
|
|
47 self.obj_file = obj_file
|
208
|
48
|
335
|
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]))
|
236
|
67
|
335
|
68 def selectSection(self, sname):
|
|
69 self.currentSection = self.obj_file.get_section(sname)
|