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