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