Mercurial > lcfOS
comparison python/ppci/linker.py @ 335:582a1aaa3983
Added long branch format
author | Windel Bouwman |
---|---|
date | Mon, 17 Feb 2014 20:41:30 +0100 |
parents | 6f4753202b9a |
children | d1ecc493384e |
comparison
equal
deleted
inserted
replaced
334:6f4753202b9a | 335:582a1aaa3983 |
---|---|
1 | 1 |
2 import struct | |
2 from .objectfile import ObjectFile | 3 from .objectfile import ObjectFile |
4 from . import CompilerError | |
5 | |
6 def align(x, m): | |
7 while ((x % m) != 0): | |
8 x = x + 1 | |
9 return x | |
10 | |
11 def wrap_negative(x, bits): | |
12 b = struct.unpack('<I', struct.pack('<i', x))[0] | |
13 mask = (1 << bits) - 1 | |
14 return b & mask | |
15 | |
16 reloc_map = {} | |
17 | |
18 def reloc(t): | |
19 def f(c): | |
20 reloc_map[t] = c | |
21 return f | |
22 | |
23 | |
24 @reloc('lit_add_8') | |
25 class LitAdd8: | |
26 def apply(self): | |
27 pass | |
28 | |
3 | 29 |
4 class Linker: | 30 class Linker: |
5 def set_symbol(self, sym): | 31 def set_symbol(self, sym): |
6 self.dst.add_symbol(sym.name, sym.value) | 32 self.dst.add_symbol(sym.name, sym.value, sym.section) |
7 | 33 |
8 def link(self, objs): | 34 def link(self, objs): |
35 # Create new object file to store output: | |
9 self.dst = ObjectFile() | 36 self.dst = ObjectFile() |
37 self.dst.get_section('code').address = 0x08000000 | |
38 | |
10 # First copy all sections into output sections: | 39 # First copy all sections into output sections: |
11 for iobj in objs: | 40 for iobj in objs: |
12 for sym in iobj.symbols: | 41 offsets = {} |
13 print(sym) | 42 # Merge sections: |
43 for in_s in iobj.sections.values(): | |
44 out_s = self.dst.get_section(in_s.name) | |
45 offsets[in_s.name] = out_s.address + out_s.Size | |
46 out_s.add_data(in_s.data) | |
47 # TODO: align section | |
48 | |
49 # Merge symbols: | |
50 for sym in iobj.symbols.values(): | |
14 self.set_symbol(sym) | 51 self.set_symbol(sym) |
15 # Do relocations: | 52 |
16 # TODO | 53 # Merge relocations: |
54 for reloc in iobj.relocations: | |
55 self.dst.add_relocation(reloc.sym, reloc.offset, reloc.typ, reloc.section) | |
56 | |
17 # Check that there are no more unresolved symbols: | 57 # Check that there are no more unresolved symbols: |
18 # TODO | 58 # Perform relocations: |
59 for reloc in self.dst.relocations: | |
60 # Lookup symbol: | |
61 if reloc.sym not in self.dst.symbols: | |
62 raise CompilerError('Undefined reference "{}"'.format(reloc.sym)) | |
63 sym = self.dst.symbols[reloc.sym] | |
64 # patch up: | |
65 section = self.dst.get_section(reloc.section) | |
66 | |
67 if reloc.typ == 'lit_add_8': | |
68 assert sym.value % 4 == 0 | |
69 offset = (sym.value - (align(reloc.offset + 2, 4))) | |
70 assert offset in range(0, 1024, 4) | |
71 rel8 = offset >> 2 | |
72 section.data[reloc.offset] = rel8 | |
73 elif reloc.typ == 'wrap_new11': | |
74 offset = sym.value - (align(reloc.offset, 2) + 4) | |
75 assert offset in range(-2048, 2046, 2) | |
76 imm11 = wrap_negative(offset >> 1, 11) | |
77 section.data[reloc.offset] = (imm11 & 0xff) | |
78 section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7 | |
79 elif reloc.typ == 'rel8': | |
80 assert sym.value % 2 == 0 | |
81 offset = sym.value - (align(reloc.offset, 2) + 4) | |
82 assert offset in range(-256, 254, 2), str(offset) + str(reloc) | |
83 imm8 = wrap_negative(offset >> 1, 8) | |
84 section.data[reloc.offset] = imm8 | |
85 elif reloc.typ == 'bl_imm11_imm10': | |
86 assert sym.value % 2 == 0 | |
87 offset = sym.value - (align(reloc.offset, 2) + 4) | |
88 assert offset in range(-16777216, 16777214, 2), str(offset) | |
89 imm32 = wrap_negative(offset >> 1, 32) | |
90 imm11 = imm32 & 0x7FF | |
91 imm10 = (imm32 >> 11) & 0x3FF | |
92 s = (imm32 >> 24) & 0x1 | |
93 section.data[reloc.offset + 2] = imm11 & 0xFF | |
94 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 | |
95 section.data[reloc.offset] = imm10 & 0xff | |
96 section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2) | |
97 elif reloc.typ == 'b_imm11_imm6': | |
98 assert sym.value % 2 == 0 | |
99 offset = sym.value - (align(reloc.offset, 2) + 4) | |
100 assert offset in range(-1048576, 1048574, 2), str(offset) | |
101 imm32 = wrap_negative(offset >> 1, 32) | |
102 imm11 = imm32 & 0x7FF | |
103 imm6 = (imm32 >> 11) & 0x3F | |
104 s = (imm32 >> 24) & 0x1 | |
105 section.data[reloc.offset + 2] = imm11 & 0xFF | |
106 section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7 | |
107 section.data[reloc.offset] |= imm6 | |
108 section.data[reloc.offset + 1] |= (s << 2) | |
109 else: | |
110 raise NotImplementedError('Unknown relocation type {}'.format(reloc.typ)) | |
111 | |
19 return self.dst | 112 return self.dst |