summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Arch/PPC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Arch/PPC.cpp')
-rw-r--r--lld/ELF/Arch/PPC.cpp63
1 files changed, 63 insertions, 0 deletions
diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp
new file mode 100644
index 00000000000..b5f0d5b4c68
--- /dev/null
+++ b/lld/ELF/Arch/PPC.cpp
@@ -0,0 +1,63 @@
+//===- PPC.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "Memory.h"
+#include "Symbols.h"
+#include "Target.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::support::endian;
+using namespace llvm::ELF;
+using namespace lld;
+using namespace lld::elf;
+
+namespace {
+class PPC final : public TargetInfo {
+public:
+ PPC() {}
+ void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
+ RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
+ const uint8_t *Loc) const override;
+};
+} // namespace
+
+void PPC::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
+ switch (Type) {
+ case R_PPC_ADDR16_HA:
+ write16be(Loc, (Val + 0x8000) >> 16);
+ break;
+ case R_PPC_ADDR16_LO:
+ write16be(Loc, Val);
+ break;
+ case R_PPC_ADDR32:
+ case R_PPC_REL32:
+ write32be(Loc, Val);
+ break;
+ case R_PPC_REL24:
+ write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC));
+ break;
+ default:
+ error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));
+ }
+}
+
+RelExpr PPC::getRelExpr(uint32_t Type, const SymbolBody &S,
+ const uint8_t *Loc) const {
+ switch (Type) {
+ case R_PPC_REL24:
+ case R_PPC_REL32:
+ return R_PC;
+ default:
+ return R_ABS;
+ }
+}
+
+TargetInfo *elf::createPPCTargetInfo() { return make<PPC>(); }
OpenPOWER on IntegriCloud