HexagonRelocator.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
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 18using namespace mcld; 19 20//===--------------------------------------------------------------------===// 21// Relocation Functions and Tables 22//===--------------------------------------------------------------------===// 23DECL_HEXAGON_APPLY_RELOC_FUNCS 24 25/// the prototype of applying function 26typedef Relocator::Result (*ApplyFunctionType)(Relocation& pReloc, 27 HexagonRelocator& pParent); 28 29// the table entry of applying functions 30struct ApplyFunctionTriple 31{ 32 ApplyFunctionType func; 33 unsigned int type; 34 const char* name; 35}; 36 37// declare the table of applying functions 38static const ApplyFunctionTriple ApplyFunctions[] = { 39 DECL_HEXAGON_APPLY_RELOC_FUNC_PTRS 40}; 41 42//===--------------------------------------------------------------------===// 43// HexagonRelocator 44//===--------------------------------------------------------------------===// 45HexagonRelocator::HexagonRelocator(HexagonLDBackend& pParent) 46 : Relocator(), 47 m_Target(pParent) { 48} 49 50HexagonRelocator::~HexagonRelocator() 51{ 52} 53 54Relocator::Result 55HexagonRelocator::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 67const char* HexagonRelocator::getName(Relocation::Type pType) const 68{ 69 return ApplyFunctions[pType].name; 70} 71 72Relocator::Size HexagonRelocator::getSize(Relocation::Type pType) const 73{ 74 return 32; 75} 76//===--------------------------------------------------------------------===// 77// Relocation helper function 78//===--------------------------------------------------------------------===// 79template<typename T1, typename T2> 80T1 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 100HexagonRelocator::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 106HexagonRelocator::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 124HexagonRelocator::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 141HexagonRelocator::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 158HexagonRelocator::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 170HexagonRelocator::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 182HexagonRelocator::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 194HexagonRelocator::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 206HexagonRelocator::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 218HexagonRelocator::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 234HexagonRelocator::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 243HexagonRelocator::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