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