Home | History | Annotate | Download | only in Hexagon
      1 //===- HexagonRelocator.cpp -----------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include <llvm/ADT/Twine.h>
     11 #include <llvm/Support/DataTypes.h>
     12 #include <llvm/Support/ELF.h>
     13 #include <mcld/Support/MsgHandling.h>
     14 
     15 #include "HexagonRelocator.h"
     16 #include "HexagonRelocationFunctions.h"
     17 
     18 using namespace mcld;
     19 
     20 //===--------------------------------------------------------------------===//
     21 // Relocation Functions and Tables
     22 //===--------------------------------------------------------------------===//
     23 DECL_HEXAGON_APPLY_RELOC_FUNCS
     24 
     25 /// the prototype of applying function
     26 typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc,
     27                                                HexagonRelocator& pParent);
     28 
     29 // the table entry of applying functions
     30 struct ApplyFunctionTriple
     31 {
     32   ApplyFunctionType func;
     33   unsigned int type;
     34   const char* name;
     35 };
     36 
     37 // declare the table of applying functions
     38 static const ApplyFunctionTriple ApplyFunctions[] = {
     39   DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS
     40 };
     41 
     42 //===--------------------------------------------------------------------===//
     43 // HexagonRelocator
     44 //===--------------------------------------------------------------------===//
     45 HexagonRelocator::HexagonRelocator(HexagonLDBackend& pParent)
     46   : Relocator(),
     47     m_Target(pParent) {
     48 }
     49 
     50 HexagonRelocator::~HexagonRelocator()
     51 {
     52 }
     53 
     54 Relocator::Result
     55 HexagonRelocator::applyRelocation(Relocation& pRelocation)
     56 {
     57   Relocation::Type type = pRelocation.type();
     58 
     59   if (type > 85) { // 86-255 relocs do not exists for Hexagon
     60     return Relocator::Unknown;
     61   }
     62 
     63   // apply the relocation
     64   return ApplyFunctions[type].func(pRelocation, *this);
     65 }
     66 
     67 const char* HexagonRelocator::getName(Relocation::Type pType) const
     68 {
     69   return ApplyFunctions[pType].name;
     70 }
     71 
     72 Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const
     73 {
     74   return 32;
     75 }
     76 //===--------------------------------------------------------------------===//
     77 // Relocation helper function
     78 //===--------------------------------------------------------------------===//
     79 template<typename T1, typename T2>
     80 T1 ApplyMask(T2 pMask, T1 pData) {
     81   T1 result = 0;
     82   size_t off = 0;
     83 
     84   for (size_t bit = 0; bit != sizeof (T1) * 8; ++bit) {
     85     const bool valBit = (pData >> off) & 1;
     86     const bool maskBit = (pMask >> bit) & 1;
     87     if (maskBit) {
     88       result |= static_cast<T1>(valBit) << bit;
     89       ++off;
     90     }
     91   }
     92   return result;
     93 }
     94 
     95 //=========================================//
     96 // Each relocation function implementation //
     97 //=========================================//
     98 
     99 // R_HEX_NONE
    100 HexagonRelocator::Result none(Relocation& pReloc, HexagonRelocator& pParent)
    101 {
    102   return HexagonRelocator::OK;
    103 }
    104 
    105 // R_HEX_B22_PCREL: Word32_B22 : 0x01ff3ffe  (S + A - P) >> 2 : Signed Verify
    106 HexagonRelocator::Result relocB22PCREL(Relocation& pReloc,
    107                                        HexagonRelocator& pParent)
    108 {
    109   HexagonRelocator::Address S = pReloc.symValue();
    110   HexagonRelocator::DWord   A = pReloc.addend();
    111   HexagonRelocator::DWord   P = pReloc.place();
    112 
    113   int32_t result = (int32_t) ((S + A - P) >> 2);
    114   int32_t range = 1 << 21;
    115 
    116   if ( (result < range) && (result > -range)) {
    117     pReloc.target() = pReloc.target() | ApplyMask(0x01ff3ffe, result);
    118     return HexagonRelocator::OK;
    119   }
    120   return HexagonRelocator::Overflow;
    121 }
    122 
    123 // R_HEX_B15_PCREL: Word32_B15 : 0x00df20fe  (S + A - P) >> 2 : Signed Verify
    124 HexagonRelocator::Result relocB15PCREL(Relocation& pReloc,
    125                                        HexagonRelocator& pParent)
    126 {
    127   HexagonRelocator::Address S = pReloc.symValue();
    128   HexagonRelocator::DWord   A = pReloc.addend();
    129   HexagonRelocator::DWord   P = pReloc.place();
    130 
    131   int32_t result = (int32_t) ((S + A - P) >> 2);
    132   int32_t range = 1 << 14;
    133   if ( (result < range) && (result > -range)) {
    134     pReloc.target() = pReloc.target() | ApplyMask(0x00df20fe,result);
    135     return HexagonRelocator::OK;
    136   }
    137   return HexagonRelocator::Overflow;
    138 }
    139 
    140 // R_HEX_B7_PCREL: Word32_B7 : 0x0001f18  (S + A - P) >> 2 : Signed Verify
    141 HexagonRelocator::Result relocB7PCREL(Relocation& pReloc,
    142                                       HexagonRelocator& pParent)
    143 {
    144   HexagonRelocator::Address S = pReloc.symValue();
    145   HexagonRelocator::DWord   A = pReloc.addend();
    146   HexagonRelocator::DWord   P = pReloc.place();
    147 
    148   int32_t result = (int32_t) ((S + A - P) >> 2);
    149   int32_t range = 1 << 6;
    150   if ( (result < range) && (result > -range)) {
    151     pReloc.target() = pReloc.target() | ApplyMask(0x00001f18, result);
    152     return HexagonRelocator::OK;
    153   }
    154   return HexagonRelocator::Overflow;
    155 }
    156 
    157 // R_HEX_LO16: Word32_LO : 0x00c03fff  (S + A) : Unsigned Truncate
    158 HexagonRelocator::Result relocLO16(Relocation& pReloc,
    159                                    HexagonRelocator& pParent)
    160 {
    161   HexagonRelocator::Address S = pReloc.symValue();
    162   HexagonRelocator::DWord   A = pReloc.addend();
    163 
    164   uint32_t result = (uint32_t) (S + A);
    165   pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
    166   return HexagonRelocator::OK;
    167 }
    168 
    169 // R_HEX_HI16: Word32_LO : 0x00c03fff  (S + A) >> 16 : Unsigned Truncate
    170 HexagonRelocator::Result relocHI16(Relocation& pReloc,
    171                                    HexagonRelocator& pParent)
    172 {
    173   HexagonRelocator::Address S = pReloc.symValue();
    174   HexagonRelocator::DWord   A = pReloc.addend();
    175 
    176   uint32_t result = (uint32_t) ((S + A) >> 16);
    177   pReloc.target() = pReloc.target() | ApplyMask(0x00c03fff, result);
    178   return HexagonRelocator::OK;
    179 }
    180 
    181 // R_HEX_32: Word32 : 0xffffffff : (S + A) : Unsigned Truncate
    182 HexagonRelocator::Result reloc32(Relocation& pReloc, HexagonRelocator& pParent)
    183 {
    184   HexagonRelocator::DWord A = pReloc.addend();
    185   HexagonRelocator::DWord S = pReloc.symValue();
    186 
    187   uint32_t result = (uint32_t) (S + A);
    188 
    189   pReloc.target() = result | pReloc.target();
    190   return HexagonRelocator::OK;
    191 }
    192 
    193 // R_HEX_16: Word32 : 0xffff : (S + A) : Unsigned Truncate
    194 HexagonRelocator::Result reloc16(Relocation& pReloc, HexagonRelocator& pParent)
    195 {
    196   HexagonRelocator::DWord A = pReloc.addend();
    197   HexagonRelocator::DWord S = pReloc.symValue();
    198 
    199   uint32_t result = (uint32_t) (S + A);
    200   pReloc.target() = pReloc.target() | ApplyMask(0x0000ffff, result);
    201 
    202   return HexagonRelocator::OK;
    203 }
    204 
    205 // R_HEX_8: Word32 : 0xff : (S + A) : Unsigned Truncate
    206 HexagonRelocator::Result reloc8(Relocation& pReloc, HexagonRelocator& pParent)
    207 {
    208   HexagonRelocator::DWord A = pReloc.addend();
    209   HexagonRelocator::DWord S = pReloc.symValue();
    210 
    211   uint32_t result = (uint32_t) (S + A);
    212   pReloc.target() = pReloc.target() | ApplyMask(0x000000ff, result);
    213 
    214   return HexagonRelocator::OK;
    215 }
    216 
    217 // R_HEX_B13_PCREL : Word32_B13 : 0x00202ffe  (S + A - P)>>2 : Signed Verify
    218 HexagonRelocator::Result relocB13PCREL(Relocation& pReloc,
    219                                        HexagonRelocator& pParent)
    220 {
    221   HexagonRelocator::Address S = pReloc.symValue();
    222   HexagonRelocator::DWord   A = pReloc.addend();
    223   HexagonRelocator::DWord   P = pReloc.place();
    224 
    225   int32_t result = ((S + A - P) >> 2);
    226   int32_t range = 1L << 12;
    227   if (result < range && result > -range) {
    228     pReloc.target() = pReloc.target() | ApplyMask(0x00202ffe, result);
    229     return HexagonRelocator::OK;
    230   }
    231   return HexagonRelocator::Overflow;
    232 }
    233 
    234 HexagonRelocator::Result unsupport(Relocation& pReloc,
    235                                    HexagonRelocator& pParent)
    236 {
    237   return HexagonRelocator::Unsupport;
    238 }
    239 
    240 
    241 
    242 // R_HEX_32_PCREL : Word32 : 0xffffffff  (S + A - P) : Signed Verify
    243 HexagonRelocator::Result reloc32PCREL(Relocation& pReloc,
    244                                       HexagonRelocator& pParent)
    245 {
    246   HexagonRelocator::Address S = pReloc.symValue();
    247   HexagonRelocator::DWord   A = pReloc.addend();
    248   HexagonRelocator::DWord   P = pReloc.place();
    249 
    250   int64_t result = S + A - P;
    251   int32_t range = 1 << 31;
    252 
    253   if (result < range && result > -range)  {
    254     pReloc.target() = pReloc.target() | ApplyMask(0xffffffff, result);
    255     return HexagonRelocator::OK;
    256   }
    257 
    258   return HexagonRelocator::Overflow;
    259 }
    260