]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/ELF/Arch/PPC.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / ELF / Arch / PPC.cpp
1 //===- PPC.cpp ------------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
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 "Symbols.h"
11 #include "Target.h"
12 #include "lld/Common/ErrorHandler.h"
13 #include "llvm/Support/Endian.h"
14
15 using namespace llvm;
16 using namespace llvm::support::endian;
17 using namespace llvm::ELF;
18 using namespace lld;
19 using namespace lld::elf;
20
21 namespace {
22 class PPC final : public TargetInfo {
23 public:
24   PPC();
25   void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;
26   RelExpr getRelExpr(RelType Type, const Symbol &S,
27                      const uint8_t *Loc) const override;
28 };
29 } // namespace
30
31 PPC::PPC() {
32   NoneRel = R_PPC_NONE;
33   GotBaseSymOff = 0x8000;
34   GotBaseSymInGotPlt = false;
35 }
36
37 RelExpr PPC::getRelExpr(RelType Type, const Symbol &S,
38                         const uint8_t *Loc) const {
39   switch (Type) {
40   case R_PPC_REL14:
41   case R_PPC_REL24:
42   case R_PPC_REL32:
43     return R_PC;
44   case R_PPC_PLTREL24:
45     return R_PLT_PC;
46   default:
47     return R_ABS;
48   }
49 }
50
51 void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
52   switch (Type) {
53   case R_PPC_ADDR16_HA:
54     write16be(Loc, (Val + 0x8000) >> 16);
55     break;
56   case R_PPC_ADDR16_HI:
57     write16be(Loc, Val >> 16);
58     break;
59   case R_PPC_ADDR16_LO:
60     write16be(Loc, Val);
61     break;
62   case R_PPC_ADDR32:
63   case R_PPC_REL32:
64     write32be(Loc, Val);
65     break;
66   case R_PPC_REL14:
67     write32be(Loc, read32be(Loc) | (Val & 0xFFFC));
68     break;
69   case R_PPC_PLTREL24:
70   case R_PPC_REL24:
71     write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC));
72     break;
73   default:
74     error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
75   }
76 }
77
78 TargetInfo *elf::getPPCTargetInfo() {
79   static PPC Target;
80   return &Target;
81 }