diff python/ppci/target/basetarget.py @ 385:d056b552d3f4

Made better use of layout
author Windel Bouwman
date Thu, 01 May 2014 14:03:12 +0200
parents 6df89163e114
children 2a970e7270e2
line wrap: on
line diff
--- a/python/ppci/target/basetarget.py	Sun Apr 27 17:50:25 2014 +0200
+++ b/python/ppci/target/basetarget.py	Thu May 01 14:03:12 2014 +0200
@@ -1,5 +1,7 @@
 import types
 from ppci import CompilerError
+from ..bitfun import encode_imm32
+import struct
 
 """
   Base classes for defining a target
@@ -101,6 +103,7 @@
         self.asm_keywords = []
 
         self.generate_base_rules()
+        self.reloc_map = reloc_map  # TODO: make this target specific.
 
     def generate_base_rules(self):
         # Base rules for constants:
@@ -148,3 +151,134 @@
     def add_lowering(self, cls, f):
         """ Add a function to the table of lowering options for this target """
         self.lower_functions[cls] = f
+
+    def add_reloc(self, name, f):
+        self.reloc_map[name] = f
+
+
+
+def align(x, m):
+    while ((x % m) != 0):
+        x = x + 1
+    return x
+
+def wrap_negative(x, bits):
+    b = struct.unpack('<I', struct.pack('<i', x))[0]
+    mask = (1 << bits) - 1
+    return b & mask
+
+
+reloc_map = {}
+
+def reloc(t):
+    def f(c):
+        reloc_map[t] = c
+    return f
+
+
+@reloc('lit_add_8')
+def apply_lit8(reloc, sym_value, section, reloc_value):
+    assert sym_value % 4 == 0
+    offset = (sym_value - (align(reloc_value + 2, 4)))
+    assert offset in range(0, 1024, 4), str(offset)+str( self.dst.sections)
+    rel8 = offset >> 2
+    section.data[reloc.offset] = rel8
+
+
+@reloc('wrap_new11')
+def apply_wrap_new11(reloc, sym_value, section, reloc_value):
+    offset = sym_value - (align(reloc_value, 2) + 4)
+    assert offset in range(-2048, 2046, 2)
+    imm11 = wrap_negative(offset >> 1, 11)
+    section.data[reloc.offset] = (imm11 & 0xff)
+    section.data[reloc.offset + 1] |= (imm11 >> 8) & 0x7
+
+
+@reloc('rel8')
+def apply_rel8(reloc, sym_value, section, reloc_value):
+    assert sym_value % 2 == 0
+    offset = sym_value - (align(reloc_value, 2) + 4)
+    assert offset in range(-256, 254, 2), str(offset) + str(reloc)
+    imm8 = wrap_negative(offset >> 1, 8)
+    section.data[reloc.offset] = imm8
+
+
+@reloc('bl_imm11_imm10')
+def apply_bl_imm11(reloc, sym_value, section, reloc_value):
+    assert sym_value % 2 == 0
+    offset = sym_value - (align(reloc_value, 2) + 4)
+    assert offset in range(-16777216, 16777214, 2), str(offset)
+    imm32 = wrap_negative(offset >> 1, 32)
+    imm11 = imm32 & 0x7FF
+    imm10 = (imm32 >> 11) & 0x3FF
+    s = (imm32 >> 24) & 0x1
+    section.data[reloc.offset + 2] = imm11 & 0xFF
+    section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
+    section.data[reloc.offset] = imm10 & 0xff
+    section.data[reloc.offset + 1] |= ((imm10 >> 8) & 0x3) | (s << 2)
+
+@reloc('b_imm11_imm6')
+def apply_b_imm11_imm6(reloc, sym_value, section, reloc_value):
+    assert sym_value % 2 == 0
+    offset = sym_value - (align(reloc_value, 2) + 4)
+    assert offset in range(-1048576, 1048574, 2), str(offset)
+    imm32 = wrap_negative(offset >> 1, 32)
+    imm11 = imm32 & 0x7FF
+    imm6 = (imm32 >> 11) & 0x3F
+    s = (imm32 >> 24) & 0x1
+    section.data[reloc.offset + 2] = imm11 & 0xFF
+    section.data[reloc.offset + 3] |= (imm11 >> 8) & 0x7
+    section.data[reloc.offset] |= imm6
+    section.data[reloc.offset + 1] |= (s << 2)
+
+# ARM reloc!!
+# TODO: move to target classes???
+@reloc('b_imm24')
+def apply_b_imm24(reloc, sym_value, section, reloc_value):
+    assert sym_value % 4 == 0
+    assert reloc_value % 4 == 0
+    offset = (sym_value - (reloc_value + 8))
+    rel24 = wrap_negative(offset >> 2, 24)
+    section.data[reloc.offset+2] = (rel24 >> 16) & 0xFF
+    section.data[reloc.offset+1] = (rel24 >> 8) & 0xFF
+    section.data[reloc.offset+0] = rel24 & 0xFF
+
+
+@reloc('ldr_imm12')
+def apply_ldr_imm12(reloc, sym_value, section, reloc_value):
+    assert sym_value % 4 == 0
+    assert reloc_value % 4 == 0
+    offset = (sym_value - (reloc_value + 8))
+    U = 1
+    if offset < 0:
+        offset = -offset
+        U = 0
+    assert offset < 4096, str(sym) + str(section) + str(reloc)
+    section.data[reloc.offset+2] |= (U << 7)
+    section.data[reloc.offset+1] |= (offset >> 8) & 0xF
+    section.data[reloc.offset+0] = offset & 0xFF
+
+@reloc('adr_imm12')
+def apply_adr_imm12(reloc, sym_value, section, reloc_value):
+    assert sym_value % 4 == 0
+    assert reloc_value % 4 == 0
+    offset = (sym_value - (reloc_value + 8))
+    U = 2
+    if offset < 0:
+        offset = -offset
+        U = 1
+    assert offset < 4096
+    offset = encode_imm32(offset)
+    section.data[reloc.offset+2] |= (U << 6)
+    section.data[reloc.offset+1] |= (offset >> 8) & 0xF
+    section.data[reloc.offset+0] = offset & 0xFF
+
+@reloc('absaddr32')
+def apply_absaddr32(reloc, sym_value, section, reloc_value):
+    assert sym_value % 4 == 0
+    assert reloc_value % 4 == 0
+    offset = sym_value
+    section.data[reloc.offset+3] = (offset >> 24) & 0xFF
+    section.data[reloc.offset+2] = (offset >> 16) & 0xFF
+    section.data[reloc.offset+1] = (offset >> 8) & 0xFF
+    section.data[reloc.offset+0] = offset & 0xFF