diff --git a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
index 5893a76e95a4..9101ac1b8a82 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_lld_library(lldMipsELFTarget
   MipsLinkingContext.cpp
   MipsRelocationHandler.cpp
+  MipsRelocationPass.cpp
   MipsTargetHandler.cpp
   )
 
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
index 6d7b6a162511..a6c52d9c51f8 100644
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
@@ -9,6 +9,7 @@
 
 #include "Atoms.h"
 #include "MipsLinkingContext.h"
+#include "MipsRelocationPass.h"
 #include "MipsTargetHandler.h"
 
 #include "llvm/ADT/StringSwitch.h"
@@ -16,151 +17,6 @@
 using namespace lld;
 using namespace lld::elf;
 
-namespace {
-
-// Lazy resolver
-const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 };
-
-// Module pointer
-const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 };
-
-/// \brief Abstract base class represent MIPS GOT entries.
-class MipsGOTAtom : public GOTAtom {
-public:
-  MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
-
-  virtual Alignment alignment() const { return Alignment(2); }
-};
-
-/// \brief MIPS GOT entry initialized by zero.
-class MipsGOT0Atom : public MipsGOTAtom {
-public:
-  MipsGOT0Atom(const File &f) : MipsGOTAtom(f) {}
-
-  virtual ArrayRef<uint8_t> rawContent() const {
-    return llvm::makeArrayRef(mipsGot0AtomContent);
-  }
-};
-
-/// \brief MIPS GOT entry initialized by zero.
-class MipsGOTModulePointerAtom : public MipsGOTAtom {
-public:
-  MipsGOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
-
-  virtual ArrayRef<uint8_t> rawContent() const {
-    return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
-  }
-};
-
-class MipsGOTPassFile : public SimpleFile {
-public:
-  MipsGOTPassFile(const ELFLinkingContext &ctx)
-      : SimpleFile("MipsGOTPassFile") {
-    setOrdinal(ctx.getNextOrdinalAndIncrement());
-  }
-
-  llvm::BumpPtrAllocator _alloc;
-};
-
-class MipsGOTPass : public Pass {
-public:
-  MipsGOTPass(MipsLinkingContext &context)
-      : _file(context), _got0(new (_file._alloc) MipsGOT0Atom(_file)),
-        _got1(new (_file._alloc) MipsGOTModulePointerAtom(_file)) {
-    _localGotVector.push_back(_got0);
-    _localGotVector.push_back(_got1);
-  }
-
-  virtual void perform(std::unique_ptr<MutableFile> &mf) {
-    // Process all references.
-    for (const auto &atom : mf->defined())
-      for (const auto &ref : *atom)
-        handleReference(*atom, *ref);
-
-    uint64_t ordinal = 0;
-
-    for (auto &got : _localGotVector) {
-      DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding L "
-                                              << got->name() << "\n");
-      got->setOrdinal(ordinal++);
-      mf->addAtom(*got);
-    }
-
-    for (auto &got : _globalGotVector) {
-      DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding G "
-                                              << got->name() << "\n");
-      got->setOrdinal(ordinal++);
-      mf->addAtom(*got);
-    }
-  }
-
-private:
-  /// \brief Owner of all the Atoms created by this pass.
-  MipsGOTPassFile _file;
-
-  /// \brief GOT header entries.
-  GOTAtom *_got0;
-  GOTAtom *_got1;
-
-  /// \brief Map Atoms to their GOT entries.
-  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
-
-  /// \brief the list of local GOT atoms.
-  std::vector<GOTAtom *> _localGotVector;
-
-  /// \brief the list of global GOT atoms.
-  std::vector<GOTAtom *> _globalGotVector;
-
-  /// \brief Handle a specific reference.
-  void handleReference(const DefinedAtom &atom, const Reference &ref) {
-    if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
-      return;
-    assert(ref.kindArch() == Reference::KindArch::Mips);
-    switch (ref.kindValue()) {
-    case R_MIPS_GOT16:
-    case R_MIPS_CALL16:
-      handleGOT(ref);
-      break;
-    }
-  }
-
-  void handleGOT(const Reference &ref) {
-    const_cast<Reference &>(ref).setTarget(getEntry(ref.target()));
-  }
-
-  const GOTAtom *getEntry(const Atom *a) {
-    auto got = _gotMap.find(a);
-    if (got != _gotMap.end())
-      return got->second;
-
-    const DefinedAtom *da = dyn_cast<DefinedAtom>(a);
-    bool isLocal = (da && da->scope() == Atom::scopeTranslationUnit);
-
-    auto ga = new (_file._alloc) MipsGOT0Atom(_file);
-    _gotMap[a] = ga;
-    if (isLocal)
-      _localGotVector.push_back(ga);
-    else {
-      if (da)
-        ga->addReferenceELF_Mips(R_MIPS_32, 0, a, 0);
-      else
-        ga->addReferenceELF_Mips(R_MIPS_NONE, 0, a, 0);
-      _globalGotVector.push_back(ga);
-    }
-
-    DEBUG_WITH_TYPE("MipsGOT", {
-      ga->_name = "__got_";
-      ga->_name += a->name();
-      llvm::dbgs() << "[ GOT ] Create " << (isLocal ? "L " : "G ") << a->name()
-                   << "\n";
-    });
-
-    return ga;
-  }
-};
-
-} // end anon namespace
-
 MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
     : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
                                     new MipsTargetHandler(*this))) {}
@@ -181,13 +37,8 @@ bool MipsLinkingContext::isLittleEndian() const {
 }
 
 void MipsLinkingContext::addPasses(PassManager &pm) {
-  switch (getOutputELFType()) {
-  case llvm::ELF::ET_DYN:
-    pm.add(std::unique_ptr<Pass>(new MipsGOTPass(*this)));
-    break;
-  default:
-    llvm_unreachable("Unhandled output file type");
-  }
-
+  auto pass = createMipsRelocationPass(*this);
+  if (pass)
+    pm.add(std::move(pass));
   ELFLinkingContext::addPasses(pm);
 }
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
new file mode 100644
index 000000000000..ad9c14c65d09
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
@@ -0,0 +1,175 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp -------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsLinkingContext.h"
+#include "MipsRelocationPass.h"
+
+#include "Atoms.h"
+
+namespace {
+
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm::ELF;
+
+// Lazy resolver
+const uint8_t mipsGot0AtomContent[] = { 0x00, 0x00, 0x00, 0x00 };
+
+// Module pointer
+const uint8_t mipsGotModulePointerAtomContent[] = { 0x00, 0x00, 0x00, 0x80 };
+
+/// \brief Abstract base class represent MIPS GOT entries.
+class MipsGOTAtom : public GOTAtom {
+public:
+  MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
+
+  virtual Alignment alignment() const { return Alignment(2); }
+};
+
+/// \brief MIPS GOT entry initialized by zero.
+class MipsGOT0Atom : public MipsGOTAtom {
+public:
+  MipsGOT0Atom(const File &f) : MipsGOTAtom(f) {}
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return llvm::makeArrayRef(mipsGot0AtomContent);
+  }
+};
+
+/// \brief MIPS GOT entry initialized by zero.
+class MipsGOTModulePointerAtom : public MipsGOTAtom {
+public:
+  MipsGOTModulePointerAtom(const File &f) : MipsGOTAtom(f) {}
+
+  virtual ArrayRef<uint8_t> rawContent() const {
+    return llvm::makeArrayRef(mipsGotModulePointerAtomContent);
+  }
+};
+
+class MipsGOTPassFile : public SimpleFile {
+public:
+  MipsGOTPassFile(const ELFLinkingContext &ctx)
+      : SimpleFile("MipsGOTPassFile") {
+    setOrdinal(ctx.getNextOrdinalAndIncrement());
+  }
+
+  llvm::BumpPtrAllocator _alloc;
+};
+
+class MipsGOTPass : public Pass {
+public:
+  MipsGOTPass(MipsLinkingContext &context)
+      : _file(context), _got0(new (_file._alloc) MipsGOT0Atom(_file)),
+        _got1(new (_file._alloc) MipsGOTModulePointerAtom(_file)) {
+    _localGotVector.push_back(_got0);
+    _localGotVector.push_back(_got1);
+  }
+
+  virtual void perform(std::unique_ptr<MutableFile> &mf) {
+    // Process all references.
+    for (const auto &atom : mf->defined())
+      for (const auto &ref : *atom)
+        handleReference(*atom, *ref);
+
+    uint64_t ordinal = 0;
+
+    for (auto &got : _localGotVector) {
+      DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding L "
+                                              << got->name() << "\n");
+      got->setOrdinal(ordinal++);
+      mf->addAtom(*got);
+    }
+
+    for (auto &got : _globalGotVector) {
+      DEBUG_WITH_TYPE("MipsGOT", llvm::dbgs() << "[ GOT ] Adding G "
+                                              << got->name() << "\n");
+      got->setOrdinal(ordinal++);
+      mf->addAtom(*got);
+    }
+  }
+
+private:
+  /// \brief Owner of all the Atoms created by this pass.
+  MipsGOTPassFile _file;
+
+  /// \brief GOT header entries.
+  GOTAtom *_got0;
+  GOTAtom *_got1;
+
+  /// \brief Map Atoms to their GOT entries.
+  llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+
+  /// \brief the list of local GOT atoms.
+  std::vector<GOTAtom *> _localGotVector;
+
+  /// \brief the list of global GOT atoms.
+  std::vector<GOTAtom *> _globalGotVector;
+
+  /// \brief Handle a specific reference.
+  void handleReference(const DefinedAtom &atom, const Reference &ref) {
+    if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
+      return;
+    assert(ref.kindArch() == Reference::KindArch::Mips);
+    switch (ref.kindValue()) {
+    case R_MIPS_GOT16:
+    case R_MIPS_CALL16:
+      handleGOT(ref);
+      break;
+    }
+  }
+
+  void handleGOT(const Reference &ref) {
+    const_cast<Reference &>(ref).setTarget(getEntry(ref.target()));
+  }
+
+  const GOTAtom *getEntry(const Atom *a) {
+    auto got = _gotMap.find(a);
+    if (got != _gotMap.end())
+      return got->second;
+
+    const DefinedAtom *da = dyn_cast<DefinedAtom>(a);
+    bool isLocal = (da && da->scope() == Atom::scopeTranslationUnit);
+
+    auto ga = new (_file._alloc) MipsGOT0Atom(_file);
+    _gotMap[a] = ga;
+    if (isLocal)
+      _localGotVector.push_back(ga);
+    else {
+      if (da)
+        ga->addReferenceELF_Mips(R_MIPS_32, 0, a, 0);
+      else
+        ga->addReferenceELF_Mips(R_MIPS_NONE, 0, a, 0);
+      _globalGotVector.push_back(ga);
+    }
+
+    DEBUG_WITH_TYPE("MipsGOT", {
+      ga->_name = "__got_";
+      ga->_name += a->name();
+      llvm::dbgs() << "[ GOT ] Create " << (isLocal ? "L " : "G ") << a->name()
+                   << "\n";
+    });
+
+    return ga;
+  }
+};
+
+} // end anon namespace
+
+std::unique_ptr<Pass>
+lld::elf::createMipsRelocationPass(MipsLinkingContext &ctx) {
+  switch (ctx.getOutputELFType()) {
+  case llvm::ELF::ET_EXEC:
+  case llvm::ELF::ET_DYN:
+    return std::unique_ptr<Pass>(new MipsGOTPass(ctx));
+  case llvm::ELF::ET_REL:
+    return std::unique_ptr<Pass>();
+  default:
+    llvm_unreachable("Unhandled output file type");
+  }
+}
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h
new file mode 100644
index 000000000000..7b2481a9f043
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h
@@ -0,0 +1,25 @@
+//===- lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h ---------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLD_READER_WRITER_ELF_MIPS_RELOCATION_PASS_H
+#define LLD_READER_WRITER_ELF_MIPS_RELOCATION_PASS_H
+
+#include <memory>
+
+namespace lld {
+class Pass;
+
+namespace elf {
+class MipsLinkingContext;
+
+std::unique_ptr<Pass> createMipsRelocationPass(MipsLinkingContext &ctx);
+
+} // end namespace elf
+} // end namespace lld
+
+#endif