1//===- HexagonAbsoluteStub.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 "HexagonAbsoluteStub.h"
11#include "HexagonLDBackend.h"
12
13#include <llvm/Support/ELF.h>
14#include <llvm/Support/MathExtras.h>
15#include <mcld/LD/ResolveInfo.h>
16#include <mcld/LD/LDSymbol.h>
17#include <mcld/Fragment/Relocation.h>
18
19using namespace mcld;
20
21//===----------------------------------------------------------------------===//
22// HexagonAbsoluteStub
23//===----------------------------------------------------------------------===//
24
25const uint32_t HexagonAbsoluteStub::TEMPLATE[] = {
26  0xbffd7f1d, /* { sp = add (sp, #-8)      */
27  0xa79dfcfe, /*   memw (sp + #-8) = r28 } */
28  0x723cc000, /* r28.h = #HI (foo)         */
29  0x713cc000, /* r28.l = #LO (foo)         */
30  0xb01d411d, /* { sp = add (sp, #8)       */
31  0x529c4000, /*   jumpr r28               */
32  0x919dc01c  /*   r28 = memw (sp) }       */
33};
34
35#define FITS_IN_NBITS(D, B) \
36    ( llvm::abs64(D) < (~(~(int64_t) 0 << ((B) - 1)) & -(4 * 4)))
37
38HexagonAbsoluteStub::HexagonAbsoluteStub(bool pIsOutputPIC)
39 : Stub(), m_Name("HexagonTrampoline"), m_pData(NULL), m_Size(0x0)
40{
41  m_pData = TEMPLATE;
42  m_Size = sizeof(TEMPLATE);
43  addFixup(8u, 0x0, llvm::ELF::R_HEX_HI16);
44  addFixup(12u, 0x0, llvm::ELF::R_HEX_LO16);
45}
46
47/// for doClone
48HexagonAbsoluteStub::HexagonAbsoluteStub(const uint32_t* pData,
49                                         size_t pSize,
50                                         const_fixup_iterator pBegin,
51                                         const_fixup_iterator pEnd)
52 : Stub(), m_Name("AbsVeneer"), m_pData(pData), m_Size(pSize)
53{
54  for (const_fixup_iterator it = pBegin, ie = pEnd; it != ie; ++it)
55    addFixup(**it);
56}
57
58HexagonAbsoluteStub::~HexagonAbsoluteStub()
59{
60}
61
62bool HexagonAbsoluteStub::isMyDuty(const class Relocation& pReloc,
63                                   uint64_t pSource,
64                                   uint64_t pTargetSymValue) const
65{
66  int nbits = 0;
67  switch (pReloc.type()) {
68    case llvm::ELF::R_HEX_B22_PCREL:
69      nbits = 24;
70      break;
71    case llvm::ELF::R_HEX_B15_PCREL:
72      nbits = 17;
73      break;
74    case llvm::ELF::R_HEX_B7_PCREL:
75      nbits = 9;
76      break;
77    case llvm::ELF::R_HEX_B13_PCREL:
78      nbits = 15;
79      break;
80    case llvm::ELF::R_HEX_B9_PCREL:
81      nbits = 17;
82      break;
83    default:
84      return false;
85  }
86
87  int64_t offset = pTargetSymValue - pSource;
88  // if offset is going to fit in nbits then we dont
89  // need a stub to be created
90  if (FITS_IN_NBITS(offset, nbits))
91    return false;
92  return true;
93}
94
95const std::string& HexagonAbsoluteStub::name() const
96{
97  return m_Name;
98}
99
100const uint8_t* HexagonAbsoluteStub::getContent() const
101{
102  return reinterpret_cast<const uint8_t*>(m_pData);
103}
104
105size_t HexagonAbsoluteStub::size() const
106{
107  return m_Size;
108}
109
110size_t HexagonAbsoluteStub::alignment() const
111{
112  return 4u;
113}
114
115Stub* HexagonAbsoluteStub::doClone()
116{
117  return new HexagonAbsoluteStub(m_pData, m_Size, fixup_begin(), fixup_end());
118}
119